# nochmal XPath  :-)



## phipsnet (2. Mai 2005)

ich kann ja mit XPath auch einen einzelnen knoten ansprechen, oder ?

bsp.:

```
XPath myXPath = XPath.newInstance("//text/page[@nummer='" + PageNo + "']");
```

bei pageNo=2
....springt auf das knotenelement <page nummer="2">

wie kann ich auf diesem knoten weiterarbeiten ? resp. 
kann ich mit methoden aus jdom auf diesem knoten (als element)
weiterarbeiten, zb. mit   ?.getChildren("irgendwas") 


danke (vor allem fuer ausauer und geduld) & gruß
.p


----------



## clemson (2. Mai 2005)

mit was arbeitest du?

wenn du mit jdom arbeitet, dann geht das so:

du legst dir eine neue abfrage an.


```
XPath myXPath = XPath.newInstance("//text/page[@nummer='" + PageNo + "']");
```

mittels


```
List ls = myXPath.selectNodes(org.jdom.Document);
```

bzw.


```
Object el = myXPath.selectSingleNode(org.jdom.Document);
```

dein element holen.

jetzt weisst du, dass der abgefragte String ein "org.jdom.Element" auf ein org.jdom.Element zeigt.

das heisst, du musst nur noch das Ergebnis casten, und dann hast du dein Element, mit dem du weiter arbeiten kannst (kinder holen, neue kinder dazu, ...)


```
org.jdom.Element element = (org.jdom.Element) ls.get(0);
```

bzw.


```
org.jdom.Element element = (org.jdom.Element) el;
```

und jetzt kannst du mittels


```
java.util.List kinder = element.getChildren();
```

auf die Kinder zugreifen...


----------



## phipsnet (3. Mai 2005)

hallo nochmal;

leider wirft meine methode immer eine zeilenanzahl von 0 zurueck.
hier die methode:


```
//Liefert Abzahl der Zeilen einer bestimmten Seite
    public int var_getLinesSum(int PageNo) throws Exception, JDOMException {
        XPath myXPath = XPath.newInstance("//text/page[@nummer='" + PageNo + "']"); 
 		List pageX = myXPath.selectNodes( doc );
 		Element page = (org.jdom.Element)pageX.get(0);
 		List lines = page.getChildren("line");
 		Iterator lines_it = lines.iterator();
 		int i = 0;
 		while(lines_it.hasNext()) {
 			Element current = (Element)lines_it.next();
 			i++;
 		}
 		return i;
    }
```


die methode rufe ich zb. mit parameter 1 auf, sodass er iom xml auf den knoten <page nummer="1"> springen soll und dort die kinder "line" aufsammelt und durchzaehlt, danach die anzahl zurueckgibt. koennte es sein, dass <line> garkein kind von <page> ist ? (ich hab das xml leider nicht fabriziert und auch keine dtd dazu) falls das so ist: wie komme ich sonst an die anzahl der zeilen fuer eine bestimmte seite.
(falls du das gesamte xml sehen moechtest: http://www.karlson.homepage.t-online.de/klageV2.xml)

1000dank; & lg.
.p


----------



## clemson (3. Mai 2005)

phipsnet hat gesagt.:
			
		

> koennte es sein, dass <line> garkein kind von <page> ist ?



so ist es, <line> ist kein kind von <page> sondern von <text> ...

wenn du die anzahl aller //text/line elemente willst, kannst du beispielsweise die count - funktion von xpath benützen:


```
count(//text/line)
```

liefert mir bei diesem XML 19.0


----------



## phipsnet (3. Mai 2005)

aber wie kann ich dann die <line> knoten zaehlen, die zwischen zwei <page> knoten stecken ?

also:

```
<page nummer="1"/>
<line/>
<line/>
<page nummer="2"/>
<line>

usw...
```

hast du eine idee ?


----------



## clemson (3. Mai 2005)

ich würde mir den start-knoten mittels XPath-Abfrageholen

Bsp.:

```
//text/page[@nummer='1']
```

dann würde ich in JDOM eine while schleife machen, welche mir jeden namen des jeweiligen geschwister-elements auf gleichheit mit "line" macht, ist das geschwister-element ein line element, so wird eine zählervariable erhöht.

ist das element jedoch ein page element, so wird abgebrochen...


----------



## phipsnet (3. Mai 2005)

supi; danke. aber wie kann ich 


```
count(//text/line)
```

einbinden ?


----------



## clemson (3. Mai 2005)

folgende xpath abfrage zählt dir alle line elemente, welche zwischen 2 page elementen sind...


```
count(//text/page[@nummer=1]/following-sibling::*[name()='line' and following-sibling::page[@nummer=2]])
```


bring mir bei deinem beispiel 3.0


das erspart dir die ganze sache mit der while schleife.


----------



## phipsnet (3. Mai 2005)

laeuft das dann auch mit:


```
XPath lines = XPath.newInstance( count(//text/page[@nummer=1]/following-sibling::*[name()='line' and following-sibling::page[@nummer=2]]))
```

?


----------



## clemson (3. Mai 2005)

ja, aber es muss heissen:


```
XPath lines = XPath.newInstance( "count(//text/page[@nummer=1]/following-sibling::*[name()='line' and following-sibling::page[@nummer=2]])");
```


----------



## phipsnet (3. Mai 2005)

damit ich mich jetzt hier total oute...

wie ziehe ich aus der abrage einen int, den ich zurueckgeben muss ?


----------



## clemson (3. Mai 2005)

phipsnet hat gesagt.:
			
		

> wie ziehe ich aus der abrage einen int, den ich zurueckgeben muss ?



was meinst du? wie du aus der abfrage die anzahl der line objekte bekommst??

frage einfach mal den String ab und dann lädst du das ergebnis in ein object. schau dir dann an, welchen typ dieses objekt hat, und dann schauen wir weiter 


etwas so


```
XPath xp = XPath.newInstance( "count(//text/page[@nummer=1]/following-sibling::*[name()='line' and following-sibling::page[@nummer=2]])" );
Object nr = xp.selectSingleNode(doc);
System.out.println(nr.getClass().toString());
```


----------



## phipsnet (3. Mai 2005)

die methode, die die anzahl der zeilen auf einer best. seite ermittelt, soll ja einen int
zurureckgeben, deshalb fragte ich, wie ich den int aus dieser abfrage ziehen kann...
(also wie ich das ergebnis dieser abfrage in einem int speichern kann...)

ausserdem frage ich mich, ob sowas hier geht:

im methodenaufrauf wird der methode eine seitenzahl (int PageNo) als parameter uebergeben, die ich gerne in meine xpath abfrage einbauen moechte...


```
( "count(//text/page[@nummer='" + PageNo + "']/following-sibling::*[name()='line' and following-sibling::page[@nummer='" + PageNo + 1 + "']])");
```


----------



## phipsnet (3. Mai 2005)

der typ des objekts was zurueckgegeben wird , ist

class java.lang.Double


...


----------



## clemson (3. Mai 2005)

okay,

dann erstell die jetz ein Double Objekt:


```
Double anzahl = (Double) nr;
```

und dann müsste er mittels anzahl.intValue() den int Wert zurückgeben..


probier das mal...


----------



## phipsnet (3. Mai 2005)

kool,
das geht. was offensichtlich nicht geht, ist eine abrfage der folgenden art:


```
( "count(//text/page[@nummer='" + PageNo + "']/following-sibling::*[name()='line' and following-sibling::page[@nummer='" + PageNo + 1 + "']])");
```

weisst du, warum ?


----------



## clemson (3. Mai 2005)

was geht denn nicht?

vielleicht liegts daran, dass du die int Werte innerhalb von einfachen anführungszeichen steckst ( ' )...

und bei der abfrage


```
...page[@nummer='" + PageNo + 1 + "']]...
```

musst du - wenn ich deinen gedankengang richitg verstanden habe - 


```
...page[@nummer='" + (PageNo + 1) + "']]...
```

schreiben. sonst schreibt er      page[@nummer='11']     anstatt        page[@nummer='2']


----------



## phipsnet (3. Mai 2005)

macht sinn & funktioniert auch.


1000dank - mal wieder -


----------



## clemson (3. Mai 2005)

eine frage hab ich noch:

wie hast du das jetzt mit der abfrage realisiert??

könntest du mal bitte den ganzen java-code posten...


----------



## phipsnet (3. Mai 2005)

klar kann ich, aber:

wald und baeume...
;-)

was meinst du genau ?


----------



## phipsnet (3. Mai 2005)

den hier?

klassenkopf + konstruktor:

```
public class ImportEd {
  	 	
    private int allPageNo;
    private int var_allLines;
    protected String path; 
    protected Element root;
    protected Document doc;
	

    public ImportEd(String path)throws Exception, ClassCastException {
    this.path = path;
    SAXBuilder builder = new SAXBuilder();
    this.doc = builder.build(new File(path));
    this.root = doc.getRootElement();
    this.allPageNo = 0;
    }
```


...und die besagte methode:

```
//Liefert Anzahl der Zeilen einer bestimmten Seite
    public int var_getLinesSum(int PageNo) throws Exception, JDOMException {
        
      XPath xp = XPath.newInstance( "count(//text/page[@nummer='" + PageNo + "']/following-sibling::*[name()='line' and following-sibling::page[@nummer='" + (PageNo + 1) + "']])" );
		Object o = xp.selectSingleNode(doc);
		Double anzahl = (Double) o;
		return anzahl.intValue();
	}
```


----------



## clemson (3. Mai 2005)

ich wollte nur mal sehen, wie du das jetzt mit der abfrage realisiert hast.

man muss also doch die einfachen anführungszeichen machen....


----------



## phipsnet (3. Mai 2005)

ha!
der clou ist natuerlich, dass es zwar eine schoene idee ist, aber beim aufruf der methode mit parameterwert fuer die letzte seite im dokument, wie PageNo +1 natuerlich nicht gefunden und das ergebnis fuer die letzte seite ist deshalb immer 0

:-(


----------

