# XML Hierarchie



## fget (21. Sep 2012)

Moin, ma ne Frage ich möchte eine eingelesene CSV datei als XML Datei ausgeben, soweit so gut, nur kommt folgendes bei heraus(Zuordnungen stimmen) aber Hierarchie nicht:

[XML]<?xml version='1.0' encoding='UTF-8'?>
<Person>
<Vorname>
Muster
</Vorname>
<Name>
Mustermann
</Name>
<Geb.Datum>
30.03.2007
</Geb.Datum>
<Ort>
Ismaning
</Ort>
</Person>[/XML]

Und es sollte halt alles ein bisschen eingerückt sein, ihr wisst schon 
Meine Klassen(2):

1.:

```
package test;

import java.io.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;

public class Main
{
  static Document document;
  String[] list;
  String[] head;

  public static void main(String string[])
  {

    Main demo = new Main("ConvertTest.xml");

    demo.createXMLBasic();
    demo.loadCSV("ConvertTest.csv");
    demo.speichern("ConvertTest.xml");
  }

  public Main(String string)
  {
    newXMLFile(string);
  }

  public void newXMLFile(String string)
  {
    try
    {
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder = factory.newDocumentBuilder();
      document = builder.newDocument();
    }
    catch (ParserConfigurationException pce)
    {
      pce.printStackTrace();
    }
    catch (Throwable t)
    {
      t.printStackTrace();
    }
  }

  public void createXMLBasic()
  {
    Element root = document.createElement("Person");
    document.appendChild(root);
  }

  public void loadCSV(String string)
  {
    // Methode zum Laden von CSV

    String zeile = "";
    try
    {
      FileReader Eingabestrom = new FileReader(string);
      BufferedReader input = new BufferedReader(Eingabestrom);

      if((zeile = input.readLine()) != null){
        head = zeile.split(";");
        while ((zeile = input.readLine()) != null)
        {


          list = makeArrayForXML(zeile);
          addData(list);
        }
      }

      input.close();
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }


  public void addData(String[] data)
  {
    Element root = document.getDocumentElement();

    try
    {
      for(int i =0; i<head.length ;i++)
      {
        Element element = document.createElement(head[i]);
        root.appendChild(element);
        if(!data[i].equals("nullString"))
          element.appendChild(document.createTextNode(data[i]));
      }


    }
    catch (DOMException ex)
    {
      ex.printStackTrace();
    }
  }


  private String[] makeArrayForXML (String zeile){
    if(zeile.startsWith(";")){
      zeile = ";"+zeile;
    }
    for(int i = 0; i < 2; i++){
      zeile = zeile.replaceAll(";;", ";nullString;");
    }
    return zeile.split(";");
  }

  public void speichern(String string)
  {
    try
    {
      XMLOutputterNeu outputter = new XMLOutputterNeu();

      outputter.output(document,new FileOutputStream(string));
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }
  }
}
```

_______________________________

2. Klasse:


```
import java.io.*;
import org.w3c.dom.*;

public class XMLOutputterNeu
{
    public void output(Document document, OutputStream out)
    {
        PrintWriter writer = new PrintWriter(out);
        travers(document, writer);
        writer.close();
    }

    private void travers(Node node, PrintWriter out)
    {
        switch (node.getNodeType())
        {
        case Document.DOCUMENT_NODE:
            NodeList list = node.getChildNodes();
            out.println("<?xml version='1.0' encoding='UTF-8'?>");
            for (int i = 0; i < list.getLength(); i++)
            {
                travers(list.item(i), out);
            }
            break;

        case Document.ELEMENT_NODE:
            list = node.getChildNodes();
            out.println("<" + node.getNodeName() + ">");
            for (int i = 0; i < list.getLength(); i++)
            {
                travers(list.item(i), out);
            }
            out.println("</" + node.getNodeName() + ">");
            break;

        case Document.TEXT_NODE:
            out.println(node.getNodeValue());
            break;
        }
    }
}
```

Hoffe es kann einer helfen. :rtfm:


----------



## SlaterB (21. Sep 2012)

füge in der rekursiven Methode einen Parameter int tiefe oder String prefix hinzu,
wann immer rekursiv aufgerufen wird die Tiefe erhöhen oder beim prefix Leerzeichen dazu,
und diese Parameter-Information dann geeignet vor die Ausgabe setzen zu Beginn jeder Zeile

vielleicht kann man auch aus dem Node selber die Tiefe berechnen, Parents abfragen und zählen usw.

-------

in einem Objekt, welches nur für eine Ausgabe zuständig ist, könnte 'PrintWriter out' auch Attribut sein,
nicht überall mitschleppen

------

machst du das nur zum Spass/ Lernen eigenhängig? dann ok,
sonst gibt es auch Einstellmöglichkeiten beim normalen XMLOutputter, allerdings teils mit Problemen, siehe
http://www.java-forum.org/xml-co/141692-jdom-xmloutputter-getprettyformat.html


----------



## fget (21. Sep 2012)

Danke schonmal, vllt. nen kurzes Code Beispiel? Wäre nett.

LG

Fget.


----------



## SlaterB (21. Sep 2012)

'nett' widerspricht meinen Prinzipien 
also nein, nur die Idee, zum selber arbeiten, wobei die sogar noch viel abstrakter zu formulieren wäre,
ist ja schon ne Einzelanleitung
(und sorry falls ich dann den Thread zu schnell an mich gerissen habe und andere vielleicht Code gepostet hätten, wobei noch möglich)


----------



## fget (21. Sep 2012)

SlaterB hat gesagt.:


> (und sorry falls ich dann den Thread zu schnell an mich gerissen habe und andere vielleicht Code gepostet hätten, wobei noch möglich)



Jop :applaus:   :autsch::autsch::autsch:


----------



## Firephoenix (21. Sep 2012)

fget hat gesagt.:


> Jop :applaus:   :autsch::autsch::autsch:



Das was SlaterB dir da gepostet hat ist doch schon fast die fertige Lösung.



> füge in der rekursiven Methode einen Parameter int tiefe oder String prefix hinzu,
> wann immer rekursiv aufgerufen wird die Tiefe erhöhen oder beim prefix Leerzeichen dazu,
> und diese Parameter-Information dann geeignet vor die Ausgabe setzen zu Beginn jeder Zeile



Aufgabe: Finde die Rekursive Methode, erweitere sie um einen passenden Parameter (int oder String) und ermittle über den den die Einrückungstiefe die du dann passend davor ausgibst.

Wenn der Code von dir ist sollte das doch kein großer Akt sein?



> vielleicht kann man auch aus dem Node selber die Tiefe berechnen, Parents abfragen und zählen usw.



Wenn man in der Lage ist mal die API zu blättern, sieht man, dass man aus einem Node den Parent bestimmen kann, gibt es keinen parent bekommt man null zurück.
Damit könnte man (allerdings unperformanter als der 1. Ansatz) ebenfalls die Tiefe des Knotens bestimmen und sich z.b. so eine Methode bauen:

```
private String createIntendationForNode(Node node)
```
Die entsprechend der Anzahl der Parents des Nodes einen String (oder einen Leeren String bei keinem Parent) zurückgibt der die nötigen Zeilenvorschübe enthält.

Wo genau hängt es bei den Ansätzen denn?

[EDIT]Da das garantiert eh gleich kommt: Nein ich poste hier keinen Code der zu einer Lösung verwendet werden kann.[/EDIT]

Gruß


----------

