누구나 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 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);
}
답변
시험:
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;
}
}
}
}
}
