package io.gitlab.jfronny.ImgJava.util; import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; /** * Klasse zum Vereinfachten Zugriff auf XML-Dokumente * Diese Klasse ist für den Einsatz in der Schule gedacht und soll den Schülern * einen einfachen Zugriff auf XML-Dokumente ermöglichen. Die zur Verfügung * stehenden Befehle sind wie in Processing realisiert. * Dabei ist jeder Teilbaum des Dokuments wieder als XML-Objekt zugreifbar, das * intern auf die gleiche XML-Dokumentstruktur zugreift. * Dies ermöglicht bei unsachgemäßem Gebrauch die XML-Struktur zu zerstören. Im * normalen Gebrauch sollte dies aber nicht relevant sein. *

* Benötigt: jdom-1.1.3.jar * * @author Thomas Schaller * @version 1.0 vom 31.01.2019 */ public class XML { // Anfang Attribute // XML-Dokumentstruktur private Document doc; // Zeiger auf das aktuelle Element private Element current; // Ende Attribute /** * Erzeugt ein leeres XMLDokument */ public XML() { this.doc = new Document(); this.current = null; } /** * Erzeugt ein XML-Dokument aus einer Datei * * @param file Dateiname der XML-Datei */ public XML(Path file) throws IOException, JDOMException { loadXML(file); } /** * interner Konstruktor, um ein XML Objekt zu erzeugen, das auf einen bestimmten Knoten verweist * * @param doc die XML-Dokumentstruktur * @param current Zeiger auf das aktuelle Element */ private XML(Document doc, Element current) { this.doc = doc; this.current = current; } // Anfang Methoden /** * Öffnet das durch den Dateinamen gegebene Dokument * * @param file Dateiname des XML-Files */ public void loadXML(Path file) throws IOException, JDOMException { doc = null; // Das Dokument erstellen SAXBuilder builder = new SAXBuilder(); doc = builder.build(Files.newInputStream(file)); // Zeiger im Baum auf Root-Element current = doc.getRootElement(); } /** * Speichert den XML-Baum im angegebenen Dateinamen * * @param file Dateiname des XML-Files */ public void saveXML(Path file) throws IOException { // new XMLOutputter().output(doc, System.out); XMLOutputter xmlOutput = new XMLOutputter(); // display nice nice xmlOutput.setFormat(Format.getPrettyFormat()); OutputStream outputFile = Files.newOutputStream(file); System.out.println("Speicher in : " + file.toAbsolutePath()); xmlOutput.output(doc, outputFile); outputFile.close(); System.out.println("File Saved!"); } //----------------------------------------------- Zeigerbewegungen -------------------------------------------------- /** * liefert ein XML-Objekt, das auf den Vaterknoten des aktuellen Elements zeigt. * * @return Vater des aktuellen Objekts. */ public XML getParent() { if (current != null) { Element parent = current.getParentElement(); if (parent == null) { return null; } else { return new XML(doc, parent); } } return null; } /** * Überprüft, ob das Element irgendwelche Kinder hat oder nicht, und gibt das Ergebnis als boolean zurück. * * @return true, wenn Kinder vorhanden sind, sonst false */ public boolean hasChildren() { if (current == null) { return doc.hasRootElement(); } else { return current.getChildren().size() > 0; } } /** * Ermittelt die Namen aller Kinder des Elements und gibt die Namen als ein Array von Strings zurück. * Dies ist dasselbe wie das Durchlaufen und Aufrufen von getName() auf jedem untergeordneten Element einzeln. * * @return Liste aller Namen der Kinder */ public String[] listChildren() { if (current == null) { if (doc.hasRootElement()) { String[] names = new String[0]; names[0] = doc.getRootElement().getName(); return names; } else { return null; } } else { List ch_element = current.getChildren(); String[] names = new String[ch_element.size()]; for (int i = 0; i < ch_element.size(); i++) { names[i] = ch_element.get(i).getName(); } return names; } } /** * Liefert alle Kinder des Elements als Array von XML-Objekten. * * @return Array der Kinder als XML-Objekte */ public XML[] getChildren() { if (current == null) { if (doc.hasRootElement()) { XML[] ch_xml = new XML[1]; ch_xml[0] = new XML(doc, doc.getRootElement()); return ch_xml; } else { return null; } } else { List ch_element = current.getChildren(); XML[] ch_xml = new XML[ch_element.size()]; for (int i = 0; i < ch_element.size(); i++) { ch_xml[i] = new XML(doc, ch_element.get(i)); } return ch_xml; } } /** * Liefert bestimmte Kinder des Elements als Array von XML-Objekten. * Die Methode gibt dabei alle Kinder zurück, die dem angegebenen Namen entsprechen. * * @param name Name der gesuchten Kind-Objekte * @return Array der Kinder als XML-Objekte */ public XML[] getChildren(String name) { if (current == null) { if (doc.hasRootElement()) { XML[] ch_xml = new XML[1]; ch_xml[0] = new XML(doc, doc.getRootElement()); if (doc.getRootElement().getName().equals(name)) { return ch_xml; } else { return null; } } else { return null; } } else { List ch_element = current.getChildren(name); XML[] ch_xml = new XML[ch_element.size()]; for (int i = 0; i < ch_element.size(); i++) { ch_xml[i] = new XML(doc, ch_element.get(i)); } return ch_xml; } } /** * Liefert das erste Kind des Elements mit einem bestimmten Namen. * Die Methode gibt das erste Kind zurück, das dem angegebenen Namen entsprechen. * * @param name Name des gesuchten Kind-Objektes * @return Kind als XML-Objekt */ public XML getChild(String name) { if (current == null) { Element e = doc.getRootElement(); if (e.getName().equals(name)) { return new XML(doc, e); } else { return null; } } else { String[] names = name.split("/"); Element e = current; int i = 0; while (i < names.length) { e = e.getChild(names[i]); if (e == null) return null; i++; } return new XML(doc, e); } } /** * Liefert das i. Kind des Elements. * Die Methode gibt das i. Kind des aktuellen Elements zurück. * * @param i Nummer des Kindes * @return Kind als XML-Objekt */ public XML getChild(int i) { if (current == null) { return new XML(doc, doc.getRootElement()); } else { List ch_element = current.getChildren(); if (i >= ch_element.size()) return null; return new XML(doc, ch_element.get(i)); } } //--------------------------------------------------- Methoden für das aktuelle Element ------------------------------------------------- /** * Frage den Namen des aktuellen Elements ab * * @return Namen des Elements */ public String getName() { if (current == null) return ""; return current.getName(); } /** * Setze den Namen des aktuellen Elements. * * @param name Neuer Name des Elements */ public void setName(String name) { if (current == null) return; current.setName(name); } /** * liefert die Anzahl der Attribute eines Elements. * * @return Anzahl des Attribute */ public int getAttributeCount() { if (current == null) return 0; return current.getAttributes().size(); } /** * liefert zurück, ob das aktuelle Element Attribute hat . * * @return true, wenn es Attribute gibt */ public boolean hasAttribute() { if (current == null) return false; return current.getAttributes().size() > 0; } /** * Ruft alle Attribute des angegebenen Elements ab und gibt sie als Array von Strings zurück. * * @return Liste der Attributnamen */ public String[] listAttributes() { if (current == null) return null; List attr = current.getAttributes(); String[] names = new String[attr.size()]; for (int i = 0; i < attr.size(); i++) { names[i] = attr.get(i).getName(); } return names; } /** * Fragt einen Attributwert des aktuellen Elements ab * * @param attribute Name des Attributs * @return Wert des Attributs */ public String getString(String attribute) { if (current == null) return ""; return current.getAttributeValue(attribute); } /** * Fragt einen Attributwert des aktuellen Elements ab * Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben * * @param attribute Name des Attributs * @param defaultValue Standardwert, falls es das Attribut nicht gibt * @return Wert des Attributs */ public String getString(String attribute, String defaultValue) { if (current == null) return defaultValue; return current.getAttributeValue(attribute, defaultValue); } /** * Setzt einen Attributwert des aktuellen Elements * * @param attribute Name des Attributs * @param text neuer Wert des Attributs */ public void setString(String attribute, String text) { if (current == null) return; current.setAttribute(attribute, text); } /** * Fragt einen Attributwert des aktuellen Elements ab * * @param attribute Name des Attributs * @return Wert des Attributs als Integer-Zahl */ public int getInt(String attribute) { if (current == null) return 0; try { int i = Integer.parseInt(current.getAttributeValue(attribute)); return i; } catch (Exception e) { return 0; } } /** * Fragt einen Attributwert des aktuellen Elements ab * Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben * * @param attribute Name des Attributs * @param defaultValue Standardwert, falls es das Attribut nicht gibt * @return Wert des Attributs als Integer-Zahl */ public int getInt(String attribute, int defaultValue) { if (current == null) return defaultValue; try { int i = Integer.parseInt(current.getAttributeValue(attribute)); return i; } catch (Exception e) { return defaultValue; } } /** * Setzt einen Attributwert des aktuellen Elements * * @param attribute Name des Attributs * @param value neuer Wert des Attributs */ public void setInt(String attribute, int value) { if (current == null) return; current.setAttribute(attribute, "" + value); } /** * Fragt einen Attributwert des aktuellen Elements ab * * @param attribute Name des Attributs * @return Wert des Attributs als Float-Zahl */ public float getFloat(String attribute) { if (current == null) return 0; try { float i = Float.parseFloat(current.getAttributeValue(attribute)); return i; } catch (Exception e) { return 0; } } /** * Fragt einen Attributwert des aktuellen Elements ab * Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben * * @param attribute Name des Attributs * @param defaultValue Standardwert, falls es das Attribut nicht gibt * @return Wert des Attributs als Float-Zahl */ public float getFloat(String attribute, float defaultValue) { if (current == null) return defaultValue; try { float i = Float.parseFloat(current.getAttributeValue(attribute)); return i; } catch (Exception e) { return defaultValue; } } /** * Setzt einen Attributwert des aktuellen Elements * * @param attribute Name des Attributs * @param value neuer Wert des Attributs */ public void setFloat(String attribute, float value) { if (current == null) return; current.setAttribute(attribute, "" + value); } /** * Fragt einen Attributwert des aktuellen Elements ab * * @param attribute Name des Attributs * @return Wert des Attributs als Double-Zahl */ public double getDouble(String attribute) { if (current == null) return 0; try { double i = Double.parseDouble(current.getAttributeValue(attribute)); return i; } catch (Exception e) { return 0; } } /** * Fragt einen Attributwert des aktuellen Elements ab * Sollte es das Attribut nicht geben, wird ein default-Wert zurückgegeben * * @param attribute Name des Attributs * @param defaultValue Standardwert, falls es das Attribut nicht gibt * @return Wert des Attributs als double-Zahl */ public double getDouble(String attribute, double defaultValue) { if (current == null) return defaultValue; try { double i = Double.parseDouble(current.getAttributeValue(attribute)); return i; } catch (Exception e) { return defaultValue; } } /** * Setzt einen Attributwert des aktuellen Elements * * @param attribute Name des Attributs * @param value neuer Wert des Attributs */ public void setDouble(String attribute, double value) { if (current == null) return; current.setAttribute(attribute, "" + value); } /** * Fragt den Inhalt/Text des aktuellen Elements ab * * @return Inhalt des Elements */ public String getContent() { if (current == null) return ""; return current.getText(); } /** * Setzt den Inhalt/Text des aktuellen Elements * * @param text Neuer Inhalt des Elements */ public void setContent(String text) { if (current == null) return; current.setText(text); } /** * Fragt den Inhalt/Text des aktuellen Elements ab * Hat das Element keinen Inhalt wird der defaultValue zurückgegeben. * * @param defaultValue Standardtext * @return Inhalt des Elements */ public String getContent(String defaultValue) { if (current == null) return defaultValue; String t = current.getText(); if (t.equals("")) t = defaultValue; return t; } /** * Fragt den Inhalt des aktuellen Elements als Integerzahl ab * Hat das Element keinen Inhalt wird der defaultValue zurückgegeben. * * @param defaultValue Standardwert * @return Inhalt des Elements */ public int getIntContent(int defaultValue) { if (current == null) return defaultValue; try { int i = Integer.parseInt(current.getText()); return i; } catch (Exception e) { return defaultValue; } } /** * Fragt den Inhalt des aktuellen Elements als Integerzahl ab * * @return Inhalt des Elements */ public int getIntContent() { if (current == null) return 0; try { int i = Integer.parseInt(current.getText()); return i; } catch (Exception e) { return 0; } } /** * Setzt den Inhalt des aktuellen Elements * * @param value Neuer Inhalt des Elements */ public void setIntContent(int value) { if (current == null) return; current.setText("" + value); } /** * Fragt den Inhalt des aktuellen Elements als Floatzahl ab * Hat das Element keinen Inhalt wird der defaultValue zurückgegeben. * * @param defaultValue Standardwert * @return Inhalt des Elements */ public float getFloatContent(float defaultValue) { if (current == null) return defaultValue; try { float i = Float.parseFloat(current.getText()); return i; } catch (Exception e) { return defaultValue; } } /** * Fragt den Inhalt des aktuellen Elements als Floatzahl ab * * @return Inhalt des Elements */ public float getFloatContent() { if (current == null) return 0; try { float i = Float.parseFloat(current.getText()); return i; } catch (Exception e) { return 0; } } /** * Setzt den Inhalt des aktuellen Elements * * @param value Neuer Inhalt des Elements */ public void setFloatContent(float value) { if (current == null) return; current.setText("" + value); } /** * Fragt den Inhalt des aktuellen Elements als Doublezahl ab * Hat das Element keinen Inhalt wird der defaultValue zurückgegeben. * * @param defaultValue Standardwert * @return Inhalt des Elements */ public double getDoubleContent(double defaultValue) { if (current == null) return defaultValue; try { double i = Double.parseDouble(current.getText()); return i; } catch (Exception e) { return defaultValue; } } /** * Fragt den Inhalt des aktuellen Elements als Doublezahl ab * * @return Inhalt des Elements */ public double getDoubleContent() { if (current == null) return 0; try { double i = Double.parseDouble(current.getText()); return i; } catch (Exception e) { return 0; } } /** * Setzt den Inhalt des aktuellen Elements * * @param value Neuer Inhalt des Elements */ public void setDoubleContent(double value) { if (current == null) return; current.setText("" + value); } // ----------------------------------------------- XML-Struktur aufbauen ------------------------------------------------ /** * Erzeuge neues Element nach der aktuellen Position und setze dieses als aktuelles Element * * @param name Name des neuen Elements * @return neues Element als XML-Objekt */ public XML addChild(String name) { Element e = new Element(name); if (current == null) { // man ist auf Root-Ebene doc.setRootElement(e); } else { current.addContent(e); } // end of if-else return new XML(doc, e); } /** * liefert das aktuelle Element als jdom-Element-Objekt * * @return aktuelles Element */ private Element getCurrent() { return current; } /** * löscht ein Kind des aktuellen Knotens. * Ist kid kein Kind des aktuellen Elements passiert gar nichts. * * @param kid XML-Objekt des Kindes */ public void removeChild(XML kid) { if (current == null) return; Element e = kid.getCurrent(); int index = current.indexOf(e); if (index >= 0) { current.removeContent(e); } } }