誰でも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']
これはすべてうまくいきますが、私はそのノードの順序位置をreturnしたいです:
a/b[.='tsr']/position()
(しかし、もう少し機能します!)
それも可能ですか?
edit:.net 2を使用していることを忘れていたため、xpath 1.0です!
Update: James Sulak の excellent 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);
}
試してください:
count(a/b[.='tsr']/preceding-sibling::*)+1.
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>
私はこのポストが古代であることに気づきました。
アスタリスクをノード名に置き換えると、より良い結果が得られます
count(a/b[.='tsr']/preceding::a)+1.
の代わりに
count(a/b[.='tsr']/preceding::*)+1.
XPath 2.0にアップグレードする場合、関数 index-of を提供することに注意してください。この方法で問題が解決します。
index-of(//b, //b[.='tsr'])
どこ:
前述の「preceding-sibling」は実際に使用する軸であり、まったく異なることを行う「preceding」とは異なり、現在のノードの開始タグの前にあるドキュメント内のすべてを選択します。 ( http://www.w3schools.com/xpath/xpath_axes.asp を参照)
James Sulakによる回答へのメモ。
ノードが存在しない可能性があることを考慮し、純粋にXPATHを保持したい場合は、ノードが存在しない場合に0を返す以下を試してください。
count(a/b[.='tsr']/preceding-sibling::*)+number(boolean(a/b[.='tsr']))
問題は、ノードの位置がコンテキストなしではあまり意味がないことです。
次のコードは、親子ノード内のノードの場所を提供します
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;
}
}
}
}
}
私は多くのNovell Identity Managerのことをしていますが、そのコンテキストでのXPATHは少し異なっています。
探している値がTARGETという文字列変数にあると仮定すると、XPATHは次のようになります。
count(attr/value[.='$TARGET']/preceding-sibling::*)+1
さらに、スペースのいくつかの文字を節約するために、以下も同様に機能することが指摘されました:
count(attr/value[.='$TARGET']/preceding::*) + 1
また、NovellのCool Solutionsにこのきれいなバージョンを投稿しました。 XPATHを使用して位置ノードを取得