XPath: รับโหนดแม่จากโหนดลูก


157

ฉันต้องการรับโหนดแม่สำหรับโหนดลูก title 50

ในขณะที่ฉันกำลังใช้เท่านั้น

//*[title="50"]

ฉันจะรับผู้ปกครองได้อย่างไร ผลลัพธ์ควรเป็นstoreโหนด


<?xml version="1.0" encoding="utf-8"?>
<d:data xmlns:d="defiant-namespace" d:mi="23">
    <store d:mi="22">
        <book price="12.99" d:price="Number" d:mi="4">
            <title d:constr="String" d:mi="1">Sword of Honour</title>
            <category d:constr="String" d:mi="2">fiction</category>
            <author d:constr="String" d:mi="3">Evelyn Waugh</author>
        </book>
        <book price="8.99" d:price="Number" d:mi="9">
            <title d:constr="String" d:mi="5">Moby Dick</title>
            <category d:constr="String" d:mi="6">fiction</category>
            <author d:constr="String" d:mi="7">Herman Melville</author>
            <isbn d:constr="String" d:mi="8">0-553-21311-3</isbn>
        </book>
        <book price="8.95" d:price="Number" d:mi="13">
            <title d:constr="String" d:mi="10">50</title>
            <category d:constr="String" d:mi="11">reference</category>
            <author d:constr="String" d:mi="12">Nigel Rees</author>
        </book>
        <book price="22.99" d:price="Number" d:mi="18">
            <title d:constr="String" d:mi="14">The Lord of the Rings</title>
            <category d:constr="String" d:mi="15">fiction</category>
            <author d:constr="String" d:mi="16">J. R. R. Tolkien</author>
            <isbn d:constr="String" d:mi="17">0-395-19395-8</isbn>
        </book>
        <bicycle price="19.95" d:price="Number" d:mi="21">
            <brand d:constr="String" d:mi="19">Cannondale</brand>
            <color d:constr="String" d:mi="20">red</color>
        </bicycle>
    </store>
</d:data>

คำตอบ:


296

ใช้parentแกนที่มีชื่อโหนดแม่

//*[title="50"]/parent::store

XPath storeนี้จะเลือกโหนดแม่ถ้ามันเป็น

แต่คุณสามารถใช้อย่างใดอย่างหนึ่งเหล่านี้

//*[title="50"]/parent::*
//*[title="50"]/..

xpaths เหล่านี้จะเลือกโหนดพาเรนต์ใด ๆ ดังนั้นหากเอกสารเปลี่ยนแปลงคุณจะต้องเลือกโหนดเสมอแม้ว่าจะไม่ใช่โหนดที่คุณคาดไว้ก็ตาม

แก้ไข

เกิดอะไรขึ้นในตัวอย่างที่กำหนดซึ่งผู้ปกครองเป็นจักรยาน แต่ผู้ปกครองของผู้ปกครองเป็นร้านค้า

มันขึ้นหรือไม่

//*[title="50"]ไม่มีก็เพียงเลือกร้านถ้ามันเป็นแม่ของโหนดที่ตรงกับ

ถ้าไม่มีวิธีการขึ้นในกรณีดังกล่าวและส่งกลับไม่มีถ้าไม่มีผู้ปกครองดังกล่าวหรือไม่?

ใช่คุณสามารถใช้ancestorขวาน

//*[title="50"]/ancestor::store

สิ่งนี้จะเลือกบรรพบุรุษทั้งหมดของการจับคู่โหนด//*[title="50"]ที่เป็น `stores เช่น

<data xmlns:d="defiant-namespace" d:mi="23">
    <store mi="1">
        <store mi="22">
            <book price="8.95" d:price="Number" d:mi="13">
                <title d:constr="String" d:mi="10">50</title>
                <category d:constr="String" d:mi="11">reference</category>
                <author d:constr="String" d:mi="12">Nigel Rees</author>
            </book>
        </store>
    </store>
</data>

ผลการเลือก XPath


7
นอกจากนี้คุณยังสามารถใช้parent::*ไวยากรณ์ยาก..(ตัวอย่าง: //*[title="50"]/..) หรือกริยาที่ซ้อนกัน (ตัวอย่าง: //*[*[title="50"]])
แดเนียลเฮลีย์

1
ข้อมูลเพิ่มเติม: w3.org/TR/xpath/#axesและw3.org/TR/xpath/#path-abbrev
Daniel Haley

3
หรือparent::node()ซึ่งสอดคล้องกับทางลัด..และดีกว่าในความคิดของฉัน ในความparent::*เป็นจริงจะถูก จำกัด ประเภทโหนดหลักของแกนซึ่งในกรณีส่วนใหญ่ไม่เป็นปัญหา
Ludovic Kuty

3
หากคุณกำลังใช้ลอง.xpath('..')หรือxpath('parent::node()')
briankip

"XPath นี้จะเลือกโหนดแม่ถ้าเป็นร้านค้า" - และอะไรจะเกิดขึ้นในตัวอย่างที่กำหนดซึ่งผู้ปกครองอยู่bicycleแต่ผู้ปกครองของผู้ปกครองคือstoreอะไร? มันขึ้นหรือไม่ ถ้าไม่มีวิธีการขึ้นในกรณีดังกล่าวและส่งคืนNoneหากไม่มีผู้ปกครองดังกล่าวหรือไม่?
Martin Thoma

31

คุณสามารถใช้ancestorแทน

//*[title="50"]/ancestor::store

มันมีพลังมากกว่าที่parentจะได้รับแม้กระทั่งปู่ย่าตายายหรือปู่ย่าตายายที่ดี


20
มันไม่ได้ "มีประสิทธิภาพมากขึ้น" มันแตกต่างกันเพียง ดังนั้นทางเลือกของแกนขึ้นอยู่กับกรณีการใช้งาน
Ludovic Kuty

11

คุณสามารถใช้จุดสองจุดที่จุดสิ้นสุดของนิพจน์ได้เช่นกัน ดูตัวอย่างนี้:

//*[title="50"]/..

2

ใหม่คำตอบที่ปรับปรุงแล้วสำหรับคำถามเก่าที่พบบ่อย ...

ฉันจะรับผู้ปกครองได้อย่างไร ผลลัพธ์ควรเป็นstoreโหนด

ใช้เพรดิเคตแทนที่จะเป็นparent::หรือancestor::แกน

คำตอบส่วนใหญ่ที่นี่เลือกtitleและจากนั้นเข้าไปยังผู้ปกครองเป้าหมายหรือstoreองค์ประกอบบรรพบุรุษ ( ) วิธีที่ง่ายและตรงไปตรงมาคือการเลือกองค์ประกอบหลักหรือองค์ประกอบที่บรรพบุรุษโดยตรงในสถานที่แรกโดยการตัดความต้องการที่จะสำรวจไปยังแกนparent::หรือancestor:::

//*[book/title = "50"]

ควรองค์ประกอบการแทรกแซงแตกต่างกันในชื่อ:

//*[*/title = "50"]

หรือในชื่อและความลึก:

//*[.//title = "50"]

สิ่งนี้ไม่ตอบคำถาม ผู้เขียนไม่จำเป็นต้องรู้ชื่อผู้ปกครองล่วงหน้า
Kenn Sebesta

1
@ KennSebesta: ฉันได้อัปเดตคำตอบเพื่อแก้ไขข้อกังวลของคุณแล้ว โปรดลบ downvote ของคุณหากการคัดค้านของคุณได้รับการแก้ไขหรือแจ้งให้เราทราบหากคุณรู้สึกว่ามีบางอย่างผิดปกติกับคำตอบ ขอบคุณ
kjhughes

0

มันใช้งานได้ในกรณีของฉัน ฉันหวังว่าคุณจะสามารถแยกความหมายออกมาได้

//div[text()='building1' and @class='wrap']/ancestor::tr/td/div/div[@class='x-grid-row-checker']
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.