รับโหนดที่โหนดลูกมีแอตทริบิวต์


116

สมมติว่าฉันมี XML ต่อไปนี้:

<book category="CLASSICS">
  <title lang="it">Purgatorio</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

<book category="CLASSICS">
  <title lang="it">Inferno</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>

<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>

ฉันต้องการทำ xpath ที่คืนโหนดหนังสือทั้งหมดที่มีโหนดหัวเรื่องที่มีแอตทริบิวต์ภาษาเป็น "it"

ความพยายามของฉันมีลักษณะดังนี้:

//book[title[@lang='it']]

แต่นั่นไม่ได้ผล ฉันคาดหวังว่าจะได้รับโหนดกลับคืนมา:

<book category="CLASSICS">
  <title lang="it">Purgatorio</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

<book category="CLASSICS">
  <title lang="it">Inferno</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

คำแนะนำใด ๆ ?


การติดตั้ง XPath คืออะไร
Pavel Minaev

คำตอบ:


175

ลอง

//book[title/@lang = 'it']

สิ่งนี้อ่าน:

  • รับbookองค์ประกอบ ทั้งหมด
    • ที่มีอย่างน้อยหนึ่ง title
      • ซึ่งมีแอตทริบิวต์ lang
        • ด้วยค่า "it"

คุณอาจพบว่าสิ่งนี้มีประโยชน์ - เป็นบทความชื่อ"XPath in Five Paragraphs"โดย Ronald Bourret

แต่ด้วยความสัตย์จริงทั้งหมด//book[title[@lang='it']]และข้างต้นควรจะเทียบเท่าเว้นแต่เอ็นจิ้น XPath ของคุณจะมี "ปัญหา" ดังนั้นอาจเป็นบางอย่างในโค้ดหรือ XML ตัวอย่างที่คุณไม่ได้แสดงให้เราเห็นตัวอย่างเช่นตัวอย่างของคุณเป็นส่วน XML เป็นไปได้ไหมว่าองค์ประกอบรากมีเนมสเปซและคุณไม่ได้นับรวมในข้อความค้นหาของคุณ และคุณบอกเราเพียงว่ามันไม่ได้ผล แต่คุณไม่ได้บอกเราว่าคุณได้ผลลัพธ์อะไร


4
จะทำอย่างไรถ้าtitleไม่ใช่ลูกโดยตรงbookแต่อยู่ลึกลงไปและเราไม่รู้ว่าอยู่ที่ไหนกันแน่? //book[/title/@lang = 'it']ดูเหมือนจะไม่ทำงาน?
Martin Konicek

5
มาร์ตินคุณสามารถใช้ //book[.//title/@lang = 'it'] ฉันเชื่อว่าเคล็ดลับคือ "." ในจุดเริ่มต้นของเงื่อนไข
Bruno Caponi

1
ขอบคุณสำหรับลิงค์บทความที่ยอดเยี่ยม ฉันใช้ xPath มาหลายปีแล้ว แต่สิ่งนี้ช่วยให้ฉันเข้าใจตรรกะพื้นฐานจริงๆ!
swensor

57

หลายปีต่อมา แต่ตัวเลือกที่มีประโยชน์คือการใช้ XPath Axes ( https://www.w3schools.com/xml/xpath_axes.asp ) โดยเฉพาะอย่างยิ่งคุณต้องการใช้แกนลูกหลาน

ฉันเชื่อว่าตัวอย่างนี้จะใช้เคล็ดลับ:

//book[descendant::title[@lang='it']]

สิ่งนี้ช่วยให้คุณสามารถเลือกbookองค์ประกอบทั้งหมดที่มีtitleองค์ประกอบลูก(ไม่ว่าจะซ้อนกันลึกแค่ไหน) ที่มีค่าแอตทริบิวต์ภาษาเท่ากับ "it"

ฉันไม่สามารถพูดได้อย่างแน่นอนว่าคำตอบนี้เกี่ยวข้องกับปี 2009 หรือไม่เนื่องจากฉันไม่แน่ใจ 100% ว่ามีแกน XPath อยู่ในเวลานั้น สิ่งที่ฉันสามารถยืนยันได้ก็คือมันมีอยู่จริงในปัจจุบันและฉันพบว่าพวกมันมีประโยชน์อย่างมากในการนำทาง XPath และฉันมั่นใจว่าคุณจะทำได้เช่นกัน


12
//book[title[@lang='it']]

เทียบเท่ากับ

 //book[title/@lang = 'it']

ฉันลองใช้ vtd-xml ทั้งสองนิพจน์พ่นผลลัพธ์เดียวกัน ... คุณใช้เอ็นจิ้นประมวลผล xpath ตัวใด ฉันเดาว่ามันมีปัญหาด้านความสอดคล้องด้านล่างนี้คือรหัส

import com.ximpleware.*;
public class test1 {
  public static void main(String[] s) throws Exception{
      VTDGen vg = new VTDGen();
      if (vg.parseFile("c:/books.xml", true)){
          VTDNav vn = vg.getNav();
          AutoPilot ap = new AutoPilot(vn);
          ap.selectXPath("//book[title[@lang='it']]");
                  //ap.selectXPath("//book[title/@lang='it']");

          int i;
          while((i=ap.evalXPath())!=-1){
              System.out.println("index ==>"+i);
          }
          /*if (vn.endsWith(i, "< test")){
             System.out.println(" good ");  
          }else
              System.out.println(" bad ");*/

      }
  }
}

+1 ว่าเป็นปัญหาการปฏิบัติตามข้อกำหนดและไวยากรณ์สร้างชุดโหนดเดียวกัน รหัสที่คล้ายกันใน C # ก็ใช้ได้เช่นกัน
Zach Bonham

-1: Mr. Zhang ฉันพยายามช่วยคุณด้วยการลบรหัสที่ไม่เกี่ยวข้องกับคำถามออก ทำให้ฉันไม่สามารถลงคะแนนให้คุณได้ซึ่งตอนนี้ฉันรู้สึกว่าต้องทำ โปรดทราบว่าไม่มีคำตอบอื่น ๆ รวมรหัสเพื่อเรียกใช้แบบสอบถาม
John Saunders

6
+1: เพราะฉันคิดไม่ออกว่านายแซนเดอร์พูดถึงอะไร - ไม่มีคำตอบอื่นใดที่เพิ่มรหัสใด ๆ และคำตอบนี้แสดงรหัสที่ใช้เพื่อให้เราสามารถ 1: ตรวจสอบวิธีการของเขาและ 2: ทำการทดสอบด้วยตัวเอง รหัสสั้นและอ่านง่าย ฉันไม่เห็นปัญหา
DuckPuppy

4

ฉันคิดว่าคำแนะนำของคุณถูกต้องอย่างไรก็ตาม xml นั้นไม่ถูกต้องนัก หากคุณใช้งาน//book[title[@lang='it']]บน<root>[Your"XML"Here]</root>ผู้ทดสอบ xPath ออนไลน์ฟรีเช่นที่นี่จะพบผลลัพธ์ที่คาดหวัง


2

ลองใช้นิพจน์ xPath นี้:

//book/title[@lang='it']/..

สิ่งนี้ควรให้โหนดหนังสือทั้งหมดในภาษา "it"


2
ผลลัพธ์ของนิพจน์นั้นคือโหนดหัวเรื่องไม่ใช่โหนดหนังสือ
Caleth

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