# unbekannte XML Datei parsen und ausgeben



## Saxony (8. Nov 2007)

Hiho,

ich möchte gerne mit dem DOM Parser eine beliebige XMLDatei parsen und diese dann als JTree anzeigen.


```
import org.w3c.dom.Document;
[...]
File xmlFile = null;
xmlFile = new File("data/MyXML.xml");

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();

Document doc = builder.parse(xmlFile);
```

Das einlesen klappt ja soweit.
Nun die Frage wie iteriere ich nun über alle Knoten und Blätter des DOM Baumes ohne das ich irgendwelche TagNamen usw. weiß ?

Vielen Dank
bye Saxony


----------



## stevieboy (8. Nov 2007)

Ich würde schätzen, dass es eine Methode gibt, die eine Liste aller Kind-Knoten eines Knotens rausgibt.

Diese Methode müsste dann rekursiv aufgerufen werden mit ROOT als Startwert.
<PSEUDOCODE>

```
private void printAllNodes(Node startNode){

List nodeList = startNode.getAllChilds();

for (Node node : nodeList){
      //JTREE-Knoten hier einfügen
      // ...jtree-code...

   if( node.hasChilds() ){
      //methode aufrufen um alle Kindknoten des Knotens   anzuzeigen 
      printAllNodes(node);
   }
}
```
</PSEUDOCODE>

So ungefähr könnte das gehen. Oder?


----------



## Murray (8. Nov 2007)

Mit dem W3C-DOM sähe das dann wohl etwa so aus:

```
private void printAllElements( Element startElem){

		NodeList nl = startElem.getChildNodes();

		int len = nl.getLength();
		for ( int i=0; i<len; i++) {
			Node ni = nl.item( i);
			if ( ni instanceof Element) {
				Element el = (Element)ni;
				//JTREE-Knoten hier einfügen
				// ...jtree-code...

				//methode aufrufen um alle Kindknoten des Knotens   anzuzeigen
				printAllElements( el);
		   }
		}
	}
```


----------



## FenchelT (8. Nov 2007)

Saxony hat gesagt.:
			
		

> Hiho,
> 
> ich möchte gerne mit dem DOM Parser eine beliebige XMLDatei parsen und diese dann als JTree anzeigen.
> 
> ...




Hallo Saxony,

habe das vor ein paar Tagen selbst benoetigt und bin fast fertig.
Das einzige was noch anzupassen ist, ich gebe im Moment ein zweiDim Array zurueck, werde das noch in ArrayList oder etwas anderes aendern.

Ansonsten funktioniert das schon ganz gut 
Du benoetigst die jdom.jar und kannst dann diesen COde nutzen:



```
package trial.XML;

import java.util.*;
import java.io.*;
import org.jdom.*;
import org.jdom.input.*;

/**
 * 
 * @author  FenchelT
 * @version 1.0
 * @since   25-10-2007
 * 
 */
public class ReadXMLStructures 
{
	private String strFilename;
	private String[][] strTableDefDouble;
	private int dimOne = 0;
	private int dimTwo = 0;
	
	

/**
 * 
 * @param filename		= Name und Pfad der XML-Datei
 * 
 */	
	public ReadXMLStructures(String filename)
	{
		this.strFilename = filename;
		this.strTableDefDouble = new String[200][2];
	}

/**
 * 
 * @return Ein zweiDim Array mit den Daten zur Tabellenstruktur
 * Im FehlerFall enthaelt das Array an Pos[0][0] den Wert "Fehler"
 */
	
	

	public String[][] getDataFromXML()
	{
		try
		{
			/**
			 * Read XML File
			 */ 
			SAXBuilder builder = new SAXBuilder();
			Document doc = builder.build(new File (this.strFilename));
			
			
			/**
			 * Lese das WurzelVerzeichnis
			 * Root Element = Clearing
			 */
			Element root = doc.getRootElement();
			
			strTableDefDouble[dimOne][dimTwo] = root.getName();
			dimOne++;
			
			
			/**
			 * Lese Root Attribute
			 */
			getAttributes(root);
			

			/**
			 * Lese Elemente
			 */
			getElements(root, 0);
			
		}
		catch (Exception ex)
		{
			this.strTableDefDouble[0][0] = "Fehler";
			ex.printStackTrace();			
		}
			
			
		return this.strTableDefDouble;
	}
	
	
	
	private void getElements(Element elem, int zaehler)
	{
		
		List listElements = elem.getChildren();
		
		for (int i=0; i <= listElements.size() -1; i++)
		{
			Element el = (Element) (listElements.get(i));
			
			if(el.getChildren().size()== 0)
			{
				strTableDefDouble[dimOne][dimTwo] = el.getName();
				strTableDefDouble[dimOne][dimTwo+1] = el.getValue();
				dimOne++;
			}
			else
			{
				strTableDefDouble[dimOne][dimTwo] = el.getName();
				dimOne++;
			}
			
			getAttributes(el);
			
			
			if (zaehler < listElements.size())
			{
				
				getElements(el, zaehler);
				
			}
		
			
			zaehler++;
		}
	}
	
	
	private void getAttributes(Element elem)
	{
		List listAttributes = elem.getAttributes();
		
		for (int p = 0; p <= listAttributes.size()-1; p++)
		{
			
			Attribute attr = (Attribute) (listAttributes.get(p));
			
			strTableDefDouble[dimOne][dimTwo] = attr.getName();
			strTableDefDouble[dimOne][dimTwo+1] = attr.getValue();
			dimOne++;
		}
	}
}


Viel Spass
```


----------



## Saxony (8. Nov 2007)

Hiho,

also ich habe nun folgendes probiert:


```
private void printAllNodes(Node aStartNode, DefaultMutableTreeNode aParent) {

    NodeList nodeList = aStartNode.getChildNodes();

    for (int i = 0; i < nodeList.getLength(); i++) {

        Node node = nodeList.item(i);

        if (!node.getNodeName().equals("#text")) {

            String name = node.getNodeName();
            String text = node.getTextContent();
				
            DefaultMutableTreeNode child = new DefaultMutableTreeNode(name + " | " + text);
				
            aParent.add(child);
				
            if (node.hasAttributes()) {

                NamedNodeMap attributes = node.getAttributes();

                for (int j = 0; j < attributes.getLength(); j++) {

                    Node attr = (Node) attributes.item(j);

                    String attrName = attr.getNodeName();
                    String attrValue = attr.getNodeValue();
						
                    DefaultMutableTreeNode attrChild 
                    = new DefaultMutableTreeNode(attrName + " | " + attrValue);
						
                    child.add(attrChild);
                }
            }

            if (node.hasChildNodes()) {

                printAllNodes(node, child);
            }
        }
    }
}
```

Soweit so gut.

Meine XMLDatei sieht so aus:


```
<?xml version="1.0" encoding="iso-8859-1"?>
<application>
	<frame layout="null">
		<item type="button">
			<bounds>
				<startx>10</startx>
				<starty>10</starty>
				<width>50</width>
				<height>10</height>
			</bounds>
		</item>
	</frame>
</application>
```

Hier kann man sehen was dann als JTree rauskommt.

So nun folgendes:

Als erstes muss ich immer solche komischen #text elemente rausfiltern - was ist das und was bedeuten die?
Weiterhin zeigt mir node.getTextContent() leider auch den Text der Kinder XML-Tags mit an. Ich möchte aber nur den TextContent des aktuellen Elementes haben.
Also bei frame, item und bounds brauche ich zum beispiel nicht den Text der erst zu startx,starty usw. gehört.

nunja
bye Saxony


----------



## Murray (8. Nov 2007)

Die NodeList enthält eben alle Nodes, nicht nur die Knoten. Um alles andere auszufiltern (eben z.B. diese Text-Nodes, die für irgendwelche Whitespace-Sequenzen in der Quelldate stehen), hatte ich in meinen Beispiel geprüft, ob die Nodes "instanceof Element" sind. Wenn du das machst, kannst du dir das Filern über den Namen sparen.


----------



## Saxony (8. Nov 2007)

Murray hat gesagt.:
			
		

> Die NodeList enthält eben alle Nodes, nicht nur die Knoten. Um alles andere auszufiltern (eben z.B. diese Text-Nodes, die für irgendwelche Whitespace-Sequenzen in der Quelldate stehen), hatte ich in meinen Beispiel geprüft, ob die Nodes "instanceof Element" sind. Wenn du das machst, kannst du dir das Filern über den Namen sparen.



Fabulös, das funktioniert.

Nun brauch ich nur noch den TextContent des aktuellen Node und nicht gleich komplett den seiner ganzen Kinder.

Hat da einer ne Idee?

bye Saxony


----------



## Murray (8. Nov 2007)

Brauchst du das in deinem Fall denn wirklich? Das ist doch eigentlich nur dann ein Problem, wenn man "mixed content" hat, also Elemente, die sowohl Text- als auch strukturierten Content haben, also so etwas:

```
<a>
  etwas text
  [b]auch text[/b]
  <c/>
</a>
```

Bei dir haben die Elemente doch entweder Text-Content oder eben weitere Kind-Elemente; insofern könnte man sich den Text-Content ja nur dann holen, wenn keine inneren Elemente vorhanden sind.


----------



## Saxony (8. Nov 2007)

Hiho,

naja wie gesagt es handelt sich um eine unbekannte XML-Datei also könnte es auch sein, dass auch schon ein Parent TextContent enthält und nicht erst die Blätter der Hierarchie.

bye Saxony


----------



## Saxony (13. Nov 2007)

Hiho,

ich nochmal. Hat nicht vielleicht doch jemand ne Idee mit dem TextContent ohne Child TextContent ?

So naja hat sich soweit erstma geklärt, nehme jetzt JDOM zum Auslesen.   

bye Saxony


----------



## Saxony (15. Nov 2007)

Hiho,

ich nochmal.

Falls jemand noch die Lösung zur Generierung eines TreeNode-Baumes aus einer beliebigen XMLDatei im JDOM Stil braucht:


```
private void printAllNodes(Element aStartNode,
			DefaultMutableTreeNode aParent) {

		List nodeList = aStartNode.getChildren();

		for (int i = 0; i < nodeList.size(); i++) {

			Object obj = nodeList.get(i);

			if (obj instanceof Element) {

				Element node = (Element) obj;

				String name = node.getName();
				String text = node.getText();

				DefaultMutableTreeNode child = new DefaultMutableTreeNode(name
						+ " | " + text);

				aParent.add(child);

				List attributes = node.getAttributes();

				for (int j = 0; j < attributes.size(); j++) {

					Object obj2 = attributes.get(j);

					if (obj2 instanceof Attribute) {

						Attribute attr = (Attribute) obj2;

						String attrName = attr.getName();
						String attrValue = attr.getValue();

						DefaultMutableTreeNode attrChild = new DefaultMutableTreeNode(
								attrName + " | " + attrValue);

						child.add(attrChild);
					}
				}

				printAllNodes(node, child);
			}
		}
	}
```

bye Saxony


----------

