# XPath - frage zur Adressierung



## redbomber (4. Feb 2011)

Hallo zusammen,
ich bin gerade dabei mittels XPath auf die Attribute und Elemente eines XML Dokuments zuzugreifen.

Hier ein Beispiel für für ein XML-File:

```
<DataObject name="aName">
    <ASubObject name ="anotherName">
      ...
    </ASubObject>
    <AnotherSubObject>
      <Measurement>
        <DataPoints>
          <Point  c="0"/>
          <Point  c="0.5" />
          <Point  c="1" />
          <Point  c="1.5"  />
          <Point  c="2" />
          <Point  c="2.5" />
          <Point  c="3."  />
          <Point  c="3.5"  />
          <Point  c="4" />
          <Point  c="4.5" />
          <Point  c="5" />
          <Point  c="5.5"  />
          <Point  c="6" />
          <Point  c="6.5" />
        </DataPoints>
      </Measurement>
    </AnotherSubObject>
</DataObject>
```

So. Möchte ich nun auf die einzelnen Datenpunkte zugreifen. Dies mache ich das wie folgt:

```
XPathExpression expr = null;
expr = xpath.compile("/DataObject/AnotherSubObject/Measurement/DataPoints/Point[position() >= 2 and (position() <= 5)]/@c");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
     System.out.println(nodes.item(i).getNodeName()); 
}
```
Hier erhalte ich dann alle Werte zwischen den Elementen 2 und 5, was auch funktioniert.

Wenn ich allerdings folgendes XML Format vorliegen habe:


```
<DataObject name="aName">
    <ASubObject name ="anotherName">
      ...
    </ASubObject>
    <AnotherSubObject>
      <Measurement>
        <DataPoints>
          <Point  c="0"/>
          ...
          <Point  c="6.5" />
        </DataPoints>
      </Measurement>
    </AnotherSubObject>
</DataObject>
<DataObject name="aSecondName">
    <ASubObject name ="anotherName">
      ...
    </ASubObject>
    <AnotherSubObject>
      <Measurement>
        <DataPoints>
          <Point  c="0"/>
          ...
          <Point  c="9.5" />
        </DataPoints>
      </Measurement>
    </AnotherSubObject>
</DataObject>
```

Dann würde ich von jedem Element im XML-Dokument "DataObject" die Datenpunkte aus dem Bereich bekommen.
Also habe ich dann eine lange Liste von Datenpunkten wo ich ja nicht weiss von welchem "DataObject" die jeweiligen werte sind.


So nun meine Frage:
1. Wisst ihr wie ich mit XPath dieses Problem lösen könnte?
Ich stelle mir folgendes vor:
Suche für jedes XML-Element "DataObject" die Datenpunkte heraus.

Ich hoffe ihr versteht in etwa mein Problem und wisst worauf ich hinaus möchte :/


----------



## eRaaaa (4. Feb 2011)

Aufbauend auf deine Lösung: Ist es evtl. akzeptabel einfach beides zu selektieren (Also den DataObject Attribute und das Point Attibute?)

```
expr = xpath.compile("//DataObject/@name | //Point[position() >= 2 and (position() <= 5)]/@c");
		Object result = expr.evaluate(doc, XPathConstants.NODESET);
		NodeList nodes = (NodeList) result;
		for (int i = 0; i < nodes.getLength(); i++) {
			Node n = nodes.item(i);
			System.out.println(n.getNodeName()+" "+n.getNodeValue());
		}
```
Sollte dann so etwas liefern wie 
name aName
c 2.0
c 2.5
...
name ...
c ....
Dann könntest du eben anhand des Node-namens (getNodeName()) differenzieren.
Oder man selektiert nicht das Attribute vom DataObject, sondern das DataObject Node an sich, dann kann man über den NodeType (getNodeType) differenzieren....
Oder aber so etwas wie

```
NodeList dataObjects = doc.getElementsByTagName("DataObject");
		for (int i = 0; i < dataObjects.getLength(); i++) {
			Element obj = (Element) dataObjects.item(i);
			System.out.println(obj.getAttribute("name"));
			NodeList points = obj.getElementsByTagName("Point");
			for (int j = 0; j < points.getLength(); j++) {
				Element point = (Element) points.item(j);
				System.out.println(point.getAttribute("c"));
			}
		}
```

wobei ..naja


----------



## redbomber (8. Feb 2011)

Hey, also erst einmal vielen vielen Dank!
Hat perfekt geklappt so wie du es vorgeschlagen hast.

Also die erste Variante ist auch das was ich brauche, da ich die "extraktion" der Daten komplett per XPath ausdrücken realisieren möchte. Die Idee ist meinen Code variable zu halten und dass nur von der Oberfläche aus ein solcher XPath erzeugt werden kann.

Jetzt habe ich aber doch noch eine Frage:

Und zwar kann ich mit dem Ausruck:

```
"//DataObject/@name | //Point[position() >= 2 and (position() <= 5)]/@c"
```

wie du beschrieben hast folgende Ausgabe generieren:
name aName
c 2.0
c 2.5
...
name ...
c ....

Jetzt versuche ich aber gerade einen Ausdruck zu erzeugen, bei den ich den Namen von "DataObject" angebe und wodurch ich NUR von diesem Element die Werte von "Point" erhalte. Natürlich ist dem Benutzer der Name von "DataObject" bekannt (sonst machts ja keinen Sinn).

Ich denke da an so etwas:

```
"/DataObject[@name='aName']/AnotherSubObject/Measurement/DataPoints/Point[position() >= 2 and (position() <= 5)]/@c"
```
was aber nicht funktioniert.
Also hiermit */DataObject[@name='aName']* denke ich auf das gewünschte "DataObject" zuzugreifen und mit der Erweiterung
*AnotherSubObject/Measurement/DataPoints/Point[...]/@c"* greife ich auf auf die gewünschten "Points" von eben *nur diesem* "DataObject" zu.


----------



## redbomber (8. Feb 2011)

hmm...geht jetzt doch!
Hat sich dann also erledigt.


----------

