Finden Sie die Position eines Knotens mit xpath

Wer weiß, wie man mit xpath die Position eines Knotens bekommt?

Angenommen, ich habe das folgende XML:

 zyx wvu tsr qpo  

Ich kann die folgende xpath-Abfrage verwenden, um den dritten Knoten ( tsr ) auszuwählen:

 a/b[.='tsr'] 

Das ist alles gut und gut, aber ich möchte die Ordinalposition dieses Knotens zurückgeben, etwas wie:

 a/b[.='tsr']/position() 

(Aber ein bisschen mehr Arbeit!)

Ist es überhaupt möglich?

edit : Vergessen zu erwähnen, dass ich .net 2 verwende, also ist es xpath 1.0!


Update : Beendet mit James Sulaks ausgezeichneter Antwort . Für diejenigen, die hier interessiert sind, ist meine Implementierung in C #:

 int position = doc.SelectNodes("a/b[.='tsr']/preceding-sibling::b").Count + 1; // Check the node actually exists if (position > 1 || doc.SelectSingleNode("a/b[.='tsr']") != null) { Console.WriteLine("Found at position = {0}", position); } 

   

Versuchen:

 count(a/b[.='tsr']/preceding-sibling::*)+1. 

Sie können dies mit XSLT tun, aber ich bin mir nicht sicher über gerade XPath.

 < ?xml version="1.0" encoding="UTF-8" standalone="yes"?>        

Ich merke, dass die Post uralt ist .. aber ..

Das Ersetzen des Sternchens durch den Knotennamen würde Ihnen bessere Ergebnisse bringen

 count(a/b[.='tsr']/preceding::a)+1. 

Anstatt von

 count(a/b[.='tsr']/preceding::*)+1. 

Anders als vorher gesagt, ist ‘vorhergehendes Geschwister’ wirklich die zu verwendende Achse, nicht ‘vorhergehend’, was etwas völlig anderes tut, es wählt alles in dem Dokument aus, das vor dem Start-Tag des aktuellen Knotens ist. (siehe http://www.w3schools.com/xpath/xpath_axes.asp )

Wenn Sie ein Upgrade auf XPath 2.0 durchführen, beachten Sie, dass es die function index-of bietet, die das Problem auf diese Weise triggers:

 index-of(//b, //b[.='tsr']) 

Woher:

  • 1. Parameter ist die Reihenfolge für die Suche
  • 2. ist was zu suchen

Das Problem ist, dass die Position des Knotens ohne Kontext nicht viel bedeutet.

Der folgende Code gibt Ihnen den Speicherort des Knotens in seinen übergeordneten untergeordneten Knoten

 using System; using System.Xml; public class XpathFinder { public static void Main(string[] args) { XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(args[0]); foreach ( XmlNode xn in xmldoc.SelectNodes(args[1]) ) { for (int i = 0; i < xn.ParentNode.ChildNodes.Count; i++) { if ( xn.ParentNode.ChildNodes[i].Equals( xn ) ) { Console.Out.WriteLine( i ); break; } } } } } 

Nur eine Notiz zu der Antwort von James Sulak.

Wenn Sie berücksichtigen möchten, dass der Knoten möglicherweise nicht existiert und Sie ihn nur XPATH beibehalten möchten, versuchen Sie Folgendes, das 0 zurückgibt, wenn der Knoten nicht existiert.

 count(a/b[.='tsr']/preceding-sibling::*)+number(boolean(a/b[.='tsr'])) 

Ich mache viele Novell Identity Manager Sachen, und XPATH in diesem Kontext sieht ein bisschen anders aus.

Angenommen, der gesuchte Wert befindet sich in einer String-Variablen namens TARGET, dann wäre XPATH:

 count(attr/value[.='$TARGET']/preceding-sibling::*)+1 

Zusätzlich wurde darauf hingewiesen, dass zum Speichern von ein paar Zeichen Speicherplatz auch Folgendes funktionieren würde:

 count(attr/value[.='$TARGET']/preceding::*) + 1 

Ich habe auch eine schönere Version von Novell’s Cool Solutions veröffentlicht: XPATH verwenden, um den Positionsknoten zu erhalten