91

XPath を使用してノードの位置を取得する方法を知っている人はいますか?

次の xml があるとします。

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

次の xpath クエリを使用して、3 番目の <b> ノード (<b>tsr</b>) を選択できます。

a/b[.='tsr']

これで問題ありませんが、次のようなノードの序数位置を返したいと思います。

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

(しかし、もう少し機能します!)

それは可能ですか?

編集:.net 2を使用していることに言及するのを忘れたので、xpath 1.0です!


更新: James Sulak優れた回答を使用することになりました。興味のある方のために、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);
}
4

8 に答える 8

102

試す:

count(a/b[.='tsr']/preceding-sibling::*)+1.
于 2008-10-22T18:46:02.790 に答える
9

投稿が古いことに気づきました..しかし..

アスタリスクをノード名に置き換えると、より良い結果が得られます

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

それ以外の

count(a/b[.='tsr']/preceding::*)+1.
于 2010-08-09T02:32:11.663 に答える
9

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>
于 2008-10-22T16:39:01.627 に答える
6

XPath 2.0 にアップグレードする場合は、関数index-of が提供されていることに注意してください。これにより、次のように問題が解決されます。

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

どこ:

  • 第1引数は検索用の配列
  • 2つ目は何を探すか
于 2015-09-21T16:14:12.480 に答える
3

前に述べたように、「preceding-sibling」は実際に使用する軸であり、まったく異なることを行う「preceding」ではなく、現在のノードの開始タグの前にあるドキュメント内のすべてを選択します。(http://www.w3schools.com/xpath/xpath_axes.aspを参照)

于 2010-08-04T20:57:07.833 に答える
2

James Sulakによる回答へのメモ。

ノードが存在しない可能性があることを考慮して、純粋に XPATH を維持したい場合は、ノードが存在しない場合に 0 を返す次のことを試してください。

count(a/b[.='tsr']/preceding-sibling::*)+number(boolean(a/b[.='tsr']))
于 2014-11-27T14:35:02.060 に答える
0

問題は、ノードの位置がコンテキストなしではあまり意味がないことです。

次のコードは、親子ノード内のノードの場所を示します

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;
                }
            }
        }
    }
}
于 2008-10-23T08:20:51.850 に答える
0

私は多くの Novell Identity Manager を使用していますが、そのコンテキストでの XPATH は少し異なります。

探している値が TARGET という文字列変数にあると仮定すると、XPATH は次のようになります。

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

さらに、数文字のスペースを節約するために、以下も同様に機能することが指摘されました。

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

また、Novell's Cool Solutions: Using XPATH to get the position nodeにこれのよりきれいなバージョンを投稿しました。

于 2008-11-12T20:07:22.623 に答える