2008-10-22 96 views
79

任何人都知道如何使用xpath獲取節點的位置?使用xpath查找節點的位置

說我有下面的XML:

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

我可以使用下面的XPath查詢以選擇第三<b>節點(<b> TSR </B >):

a/b[.='tsr'] 

這是一切都很好,但我想返回該節點的序號位置,如:

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

(但多一點的工作!)

它甚至有可能?

編輯:忘了提及我使用.net 2,所以它的xpath 1.0!


更新:結束了使用James Sulakexcellent answer。對於那些有興趣,這裏是我的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); 
} 

回答

84

嘗試:

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

'因爲我正在使用.net及其或者我無法處理我去的權力:int position = doc.SelectNodes(「a/b [。='tsr']/preceding-Sibling :: b 「).Count + 1; if(position> 1 || doc.SelectSingleNode(「a/b [。='tsr']」)!= null)//檢查實際存在的節點{//在這裏做魔術} – 2008-10-24 09:52:59

+0

以零索引語言, t需要+1 – 2017-11-23 14:50:30

8

爲此,您可以使用XSLT,但我不知道直接XPath。

<?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> 
1

的問題是,該節點的位置沒有多大的意義不利用上下文。

下面的代碼會給你節點的位置在其父子節點

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; 
       } 
      } 
     } 
    } 
} 
+1

所以現在不是一個真正的XPath查找器,而是一個C#查找器。 – jamesh 2008-10-29 13:03:12

0

我做了很多的Novell Identity Manager已的東西,和XPath在這方面顯得有些不同。

假設你正在尋找的是一個字符串變量,稱爲目標的價值,那麼XPATH將是:

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

另外有人指出,以節省空間幾個大字,下面的以及工作:

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

我還張貼這在Novell的超酷解決方案更漂亮的版本:Using XPATH to get the position node

3

不像規定上10狡猾的「兄弟姐妹」實際上是使用的軸,而不是「前面的」,它做了完全不同的事情,它選擇文檔中當前節點的開始標記之前的所有內容。 (見http://www.w3schools.com/xpath/xpath_axes.asp

+4

不包括祖先節點。不要相信w3schools的細節! 但我同意......儘管前面的::在這種情況下工作,因爲在除了祖先之外的相關b元素之前沒有元素,它比前面的兄弟姐妹更脆弱。 OTOH,OP沒有告訴我們他想知道內部位置的情況,所以潛在的前面::可能是正確的。 – LarsH 2010-08-18 18:44:32

5

我意識到,職位是古老的..但..

replace'ing與節點名的星號會帶來更好的效果

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

,而不是

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

只是說明由詹姆斯·蘇拉克做了回答。

如果您想要考慮節點可能不存在並且希望保持純粹XPATH,那麼請嘗試以下操作,如果該節點不存在,則返回0。

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

如果你升級到XPath 2.0中,請注意,它提供的功能index-of,它解決的問題是這樣的:

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

其中:

  • 第一個參數是序列搜索
  • 第二是要搜索什麼