ค้นหาตำแหน่งของโหนดโดยใช้ xpath


86

ใครทราบวิธีรับตำแหน่งของโหนดโดยใช้ 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!


ปรับปรุง : สิ้นสุดการใช้เจมส์ 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);
}

โปรดพยายามอย่าโพสต์คำตอบในคำถาม -> จะเป็นการดีกว่าหากโพสต์สิ่งนี้เป็นคำตอบจากนั้นอาจเชื่อมโยงกับคำถามนั้น
theMayer

คำตอบ:


95

ลอง:

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

1
'เพราะฉันใช้. net & อย่างใดอย่างหนึ่งหรือฉันไม่สามารถจัดการกับพลังที่ฉันใช้: int position = doc.SelectNodes ("a / b [. =' tsr '] / preceding-Sibling :: b") . นับ + 1; if (position> 1 || doc.SelectSingleNode ("a / b [. = 'tsr']")! = null) // ตรวจสอบว่าโหนดมีอยู่จริง {// Do magic here}
Wilfred Knievel

ในภาษาที่จัดทำดัชนีเป็นศูนย์คุณไม่จำเป็นต้องใช้ +1
JonnyRaa

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>

9

นึกว่ากระทู้โบราณ.. แต่ ..

การแทนที่เครื่องหมายดอกจันด้วย nodename จะให้ผลลัพธ์ที่ดีกว่า

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

แทน

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

5

หากคุณเคยอัปเกรดเป็น XPath 2.0 โปรดทราบว่ามีฟังก์ชันindex-ofซึ่งจะแก้ปัญหาด้วยวิธีนี้

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

ที่ไหน:

  • พารามิเตอร์ที่ 1 คือลำดับสำหรับการค้นหา
  • อันดับ 2 คือสิ่งที่ต้องค้นหา

ควรสังเกตว่าสิ่งนี้ใช้ได้กับ XPath 2+ เท่านั้น สิ่งใดก็ตามที่ด้านล่างนี้จะต้องใช้ฟังก์ชันการนับ 'แปลก'
Dan Atkinson

1
@ แดนมันถูกบันทึกไว้ในลิงค์ไปยังเอกสารต้นฉบับเพิ่มการแจ้งให้ทราบอย่างชัดเจนขอบคุณ!
CroWell

3

ต่างจากที่ระบุไว้ก่อนหน้านี้คือแกนที่จะใช้ไม่ใช่ 'นำหน้า' ซึ่งทำสิ่งที่แตกต่างไปจากเดิมอย่างสิ้นเชิงโดยจะเลือกทุกอย่างในเอกสารที่อยู่ก่อนแท็กเริ่มต้นของโหนดปัจจุบัน (ดูhttp://www.w3schools.com/xpath/xpath_axes.asp )


4
ไม่รวมโหนดบรรพบุรุษ อย่าไว้ใจ w3schools ในรายละเอียด! แต่ฉันเห็นด้วย ... แม้ว่าจะนำหน้า :: ใช้งานได้ในกรณีนี้เนื่องจากไม่มีองค์ประกอบก่อนองค์ประกอบ b ที่เกี่ยวข้องนอกเหนือจากบรรพบุรุษมันบอบบางกว่าพี่น้องก่อนหน้า OTOH OP ไม่ได้บอกเราว่าบริบทใดที่เขาต้องการทราบตำแหน่งภายในดังนั้นจึงอาจนำหน้า :: อาจถูกต้อง
LarsH

2

เพียงแค่ทราบคำตอบของเจมส์สุลักษณ์

หากคุณต้องการพิจารณาว่าโหนดอาจไม่มีอยู่และต้องการเก็บไว้เป็น XPATH อย่างหมดจดให้ลองสิ่งต่อไปนี้ที่จะคืนค่า 0 หากโหนดไม่มีอยู่

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

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

1
ดังนั้นตอนนี้ไม่ใช่ตัวค้นหา XPath แต่เป็นตัวค้นหา C #
jamesh

0

ฉันทำหลายอย่างเกี่ยวกับ Novell Identity Manager และ XPATH ในบริบทนั้นดูแตกต่างกันเล็กน้อย

สมมติว่าค่าที่คุณกำลังมองหาอยู่ในตัวแปรสตริงที่เรียกว่า TARGET จากนั้น XPATH จะเป็น:

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

นอกจากนี้ยังชี้ให้เห็นว่าในการประหยัดพื้นที่สองสามอักขระสิ่งต่อไปนี้จะได้ผลเช่นกัน:

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

ฉันยังโพสต์เวอร์ชันที่สวยกว่านี้ไว้ที่ Cool Solutions ของ Novell: การใช้ XPATH เพื่อรับโหนดตำแหน่ง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.