# JDOM - aus Children-Liste ein Child direkt ansprechen ohne XPath?



## geneticZ (27. Mai 2011)

Hallo allerseits,
ich schlage mich derzeit mit dem Auslesen und Verwerten eines Crystal-Reports rum. ;-(
Leider habe ich von vorn herein JDOM verwendet und will das jetzt ungern in DOM umbauen.
Egal wie, nun zu meiner Frage: Gibt es die Möglichkeit aus einer Children-Liste direkt ein Child anzusprechen welches den Attribute Wert "irgendwas" hat und  zwar ohne mit dem Iterator durch alle Children zu rennen und zu vergleichen?

Mit XPath ginge das, aber ich laufe davor schon durch mehrer Group Level und übergebe an meine Klasse dann nur noch ein Knotenelement. Soweit ich weiss muss man mit XPath von Root starten. Ich könnte natürlich umbauen aber es wäre eben schön wenn das auch ganz normal mit einer Abfrage möglich wäre. 


```
<CrystalReport xsi:........>
<Group Level="1">
    <GroupHeader>
        <Section SectionNumber="0">...</Section>
        <Section SectionNumber="1">...</Section>
        <Section SectionNumber="2">...</Section>
        <Section SectionNumber="3">...</Section>
    </GroupHeader>
</Group>
</CrystalReport>
```


```
Element root = doc.getRootElement();
Namespace ns = root.getNamespace();
Element group = root.getChild("GroupHeader", ns);
Element groupHeader = group.getChild("GroupHeader", ns);
// Hier direkt auf Section SectionNumber="0" möglich??
```

Vielen Dank für die Hilfe!
geneticZ


----------



## eRaaaa (27. Mai 2011)

geneticZ hat gesagt.:


> Soweit ich weiss muss man mit XPath von Root starten.



Nö


----------



## geneticZ (27. Mai 2011)

eRaaaa hat gesagt.:


> Nö



OK! 
So dann oder wie?


```
Object section_1 = XPath.selectSingleNode( groupHeader, "/Section[0]/" );
System.out.println( ((Element) section_1.getValue() );
```


----------



## eRaaaa (27. Mai 2011)

Mhm? So wie ich dich verstanden habe willst du doch nach einem bestimmten Attribut filtern oder nicht? Oder weisst du schon an welcher Stelle der Knoten steht oder wie?

Probiere mal

```
Element valueList = (Element) XPath.selectSingleNode(groupHeader.getChildren(), "//Section[@SectionNumber=0]");
System.out.println(section_1.getValue());
```

oder habe ich dich missverstanden?


----------



## geneticZ (29. Mai 2011)

Danke! Hab lange nicht gerafft dass ich auch noch die jaxen.jar mit einbinden muss 

EDIT:
Oje, jetzt habe ich Probleme mit dem Namespace.
Weiß jemand wie die Abfrage mit Namespace aussehen muss?

```
<?xml version="1.0" encoding="UTF-8" ?>
<CrystalReport xmlns="urn:crystal-reports:schemas:report-detail"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:crystal-reports:schemas:report-detail http://www.businessobjects.com/products/xml/CR2008Schema.xsd">
<Group Level="1">
    <GroupHeader>
        <Section SectionNumber="0">Section 0</Section>
        <Section SectionNumber="1">Section 1</Section>
        <Section SectionNumber="2">Section 2</Section>
        <Section SectionNumber="3">Section 3</Section>
    </GroupHeader>
</Group>
</CrystalReport>
```

EDIT 2:
Hab's selber hinbekommen!

```
XPath xpath = XPath.newInstance("//foo:Section[@SectionNumber=1]");
xpath.addNamespace("foo", "urn:crystal-reports:schemas:report-detail");
Element valueList = (Element) xpath.selectSingleNode( groupHeader.getChildren() );
System.out.println(valueList.getValue());
```

Vielen Dank!


----------



## geneticZ (30. Mai 2011)

EDIT 3: 
Verdammt, jetzt ist alles schön und gut solange der XPath nicht dynamisch neue Werte annehmen muss, was wohl an der Instance liegt! Hat da einer ne Lösung für? :-(

Hier mal das veränderte XML mit mehreren Gruppen (nicht nur einer!):

```
<?xml version="1.0" encoding="UTF-8" ?>
<CrystalReport xmlns="urn:crystal-reports:schemas:report-detail"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:crystal-reports:schemas:report-detail http://www.businessobjects.com/products/xml/CR2008Schema.xsd">
<Group Level="1">
    <GroupHeader>
        <Section SectionNumber="0">Group 1 Section 0</Section>
        <Section SectionNumber="1">Group 1 Section 1</Section>
        <Section SectionNumber="2">Group 1 Section 2</Section>
        <Section SectionNumber="3">Group 1 Section 3</Section>
    </GroupHeader>
</Group>
<Group Level="1">
    <GroupHeader>
        <Section SectionNumber="0">Group 2 Section 0</Section>
        <Section SectionNumber="1">Group 2 Section 1</Section>
        <Section SectionNumber="2">Group 2 Section 2</Section>
        <Section SectionNumber="3">Group 2 Section 3</Section>
    </GroupHeader>
</Group>
<Group Level="1">
    <GroupHeader>
        <Section SectionNumber="0">Group 3 Section 0</Section>
        <Section SectionNumber="1">Group 3 Section 1</Section>
        <Section SectionNumber="2">Group 3 Section 2</Section>
        <Section SectionNumber="3">Group 3 Section 3</Section>
    </GroupHeader>
</Group>
</CrystalReport>
```

Und hier der java - Code der aber leider immer nur die erste Gruppe ausliest wahrscheinlich wegen der Instanz:

```
this.doc = new SAXBuilder().build(xmlFile);
Element root = doc.getRootElement();
Namespace ns = root.getNamespace();
List<?> childList = root.getChildren();
//Mit einem Iterator diese Liste durchlaufen 
Iterator<?> iter = childList.iterator();
    while (iter.hasNext()) { 
	Element group = (Element)iter.next();
	Element groupHeader = group.getChild("GroupHeader", ns);
	XPath xpath = XPath.newInstance("//foo:Section[@SectionNumber=1]");
	xpath.addNamespace("foo", "urn:crystal-reports:schemas:report-detail");
	Element valueList = (Element) xpath.selectSingleNode( groupHeader.getChildren() );
	System.out.println(valueList.getValue());
    }
```

Vielen Dank für die Hilfe!


----------



## eRaaaa (30. Mai 2011)

Ok also vllt sprechen wir die ganze Zeit aneinander vorbei, daher nochmal die Frage: Was genau willst du jetzt raus bekommen? Was erwartest du? 

```
Group 1 Section 1
Group 2 Section 1
Group 3 Section 1
```

Das? Am Anfang dachte ich du willst wirklich nur *ein* bestimmtes Element selektieren, daher auch selectSingleNode, aber in dem Fall kannst du dir doch eine Liste holen mit allen Section-Elementen, wo SectionNumber=1


```
this.doc = new SAXBuilder().build(xmlFile);
		Element root = doc.getRootElement();
		Namespace ns = root.getNamespace();
		List<?> childList = root.getChildren();
		XPath xpath = XPath.newInstance("//foo:Section[@SectionNumber=1]");
		xpath.addNamespace("foo", "urn:crystal-reports:schemas:report-detail");
		List<Element> valueList = xpath.selectNodes(childList);
		for (Element element : valueList) {
			System.out.println(element.getValue());
		}
```


----------



## geneticZ (30. Mai 2011)

Nein, ganz so ist es leider nicht!
Ich habe eine existierende Datenbank mit jeder Menge Datensätzen, diese werden mittels CrystalReports in ein XML-File exportiert.
Das ist leider so und liegt auch nicht in meiner Hand daran irgendwas zu ändern...

Was ich jetzt machen muss, dieses CrystalReports-File nehmen und die einzelnen Values einlesen und in "unsere" Datenbank importieren. Das Problem ist aber jetzt dass ich in einer Gruppe exakt einen Datensatz habe. In einem CrystalReport mehrere Gruppen. Ich gehe in die erste Gruppe -> brauche Section SectionNumber=0 -> speicher es in Variable "irgendwas" und muss danach in Section SectionNumber=1 -> wieder in neue Variable etc.

Wenn dieser Datensatz durch ist werden die Variablen in unsere Datenbank gejagt und der Iterator geht in die nächste Gruppe und wiederholt alles.

Blöd ist halt dass der dumme Crystalreport jede menge Tags hat, teilweise auch unnütze, aber wie gesagt das liegt eben nicht in meiner Hand. Cool wäre es wenn ich, egal welches Tag, irgendwie direkt ansprechen könnte. Alle Felder der Section SectoinNumber=0 aus jeder Gruppe bringt mir zum Beispiel erstmal nichts...


----------



## eRaaaa (30. Mai 2011)

Sorry, viele Worte, aber so ganz verständlich war es jetzt nicht(zumindest für mich ) bzw das Problem welches du jetzt hast sehe ich nicht. Lässt sich doch alles mit dme Code von oben machen oder nicht? oO
Gib doch mal ein Beispiel!


----------



## geneticZ (30. Mai 2011)

Hm, wenn ich so überlege könnte dein letztes Snippet aber doch funktionieren... 
Ich müsste dann halt erst alle SectionNumber 0 einlesen, dann alle Number 1 usw., alles in neue Listen speichern und am Schluss die Daten hochschupsen auf den Server.


----------

