it-swarm.com.de

Finden Sie die Position eines Knotens mit xpath

Weiß jemand, wie man die Position eines Knotens mit xpath ermittelt?

Angenommen, ich habe die folgende XML:

<a>
    <b>zyx</b>
    <b>wvu</b>
    <b>tsr</b>
    <b>qpo</b>
</a>

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

a/b[.='tsr']

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

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

(aber ein bisschen mehr Arbeit!)

Ist es überhaupt möglich?

edit : Ich habe vergessen zu erwähnen, dass ich .net 2 benutze, also ist es xpath 1.0!


Update : Endete mit James Sulak 's ausgezeichnete Antwort . Für diejenigen, die interessiert sind, ist hier 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);
}
85
Wilfred Knievel

Versuchen:

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

Sie können dies mit XSLT tun, bei XPath bin ich mir jedoch nicht sicher.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" encoding="utf-8" indent="yes" 
              omit-xml-declaration="yes"/>
  <xsl:template match="a/*[text()='tsr']">
    <xsl:number value-of="position()"/>
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>
9
Steven Huwig

Mir ist klar, dass die Post uralt ist .. aber ..

wenn Sie den Stern durch den Knotennamen ersetzen, erhalten Sie bessere Ergebnisse

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

anstatt

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

Wenn Sie jemals ein Upgrade auf XPath 2.0 durchführen, beachten Sie, dass es die Funktion index-of bietet. Das Problem wird folgendermaßen gelöst:

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

Woher:

  • Der erste Parameter ist die Suchsequenz
  • 2. ist was zu suchen
3
CroWell

Anders als zuvor angegeben, ist "Vorhergehendes Geschwister" eigentlich die zu verwendende Achse und nicht "Vorhergehendes Geschwister", was etwas völlig anderes bewirkt. Es wählt alles im Dokument aus, was vor dem Starttag des aktuellen Knotens liegt. (Siehe http://www.w3schools.com/xpath/xpath_axes.asp )

3
Damien

Nur eine Anmerkung zu der Antwort von James Sulak.

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

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

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

Der folgende Code gibt die Position des Knotens in den übergeordneten untergeordneten Knoten an

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;
                }
            }
        }
    }
}
0
Andrew Cox

Ich mache viel mit Novell Identity Manager, und XPATH sieht in diesem Zusammenhang etwas anders aus.

Angenommen, der gesuchte Wert befindet sich in einer Zeichenfolgenvariablen mit dem Namen TARGET. Dann wäre der XPATH:

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

Darüber hinaus wurde darauf hingewiesen, dass zum Einsparen einiger weniger Zeichen auch Folgendes funktionieren würde:

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

Ich habe auch eine schönere Version davon bei Novells Cool Solutions gepostet: Verwenden von XPATH, um den Positionsknoten zu erhalten

0
geoffc