Bagaimana cara memilih node menggunakan XPath jika node saudara memiliki nilai tertentu?

89

Saya memiliki dokumen berikut:

<a>
  <bb>abc</bb>
  <cc>ccc</cc>
  <dd>ddd</dd>
</a>
<a>
  <bb>zz</bb>
  <cc>1</cc>
  <dd>2</dd>
</a>

Bagaimana saya bisa mendapatkan nilai <cc>menggunakan XPath jika <bb>ada zz?

HOE SENGKIANG
sumber
1
Masalahnya adalah saya tahu cara mengakses node tertentu, tetapi saya tidak tahu mengakses node jika saudara kandung memiliki nilai tertentu. Bisakah itu menjadi sesuatu seperti ini / a / cc / contains (/ a / bb = 'zz')?
HOE SENGKIANG

Jawaban:

101

Tidak yakin mengapa semua orang menanyakan saudara kandung, Anda juga dapat memeriksa <bb/>-elements yang cocok dengan predikat dari <a/>predikat:

//a[bb/text() = "zz"]/cc/text()
Jens Erat
sumber
24
"Tidak yakin mengapa semua orang menanyakan tentang saudara kandung" : Mungkin karena pertanyaannya untuk saudara kandung .. ;-)
hr_117
4
Sepertinya saya sebenarnya tidak membaca judulnya. :) Jawaban tetap valid.
Jens Erat
2
Pertanyaan jawaban Anda untuk saudara kandung juga. Anda hanya tidak menggunakan *-siblingsumbu. +1 sekalipun.
LarsH
Ini tidak menjawab pertanyaan tetapi menjawab pertanyaan saya yang sebenarnya yang saya rumuskan dengan buruk. Terima kasih!
Pengguna9213
37

Yang Anda butuhkan adalah following-siblingsumbu XPath

//a/bb[text()="zz"]/following-sibling::cc[1]/text()

Uji Xpath di sini: http://www.xpathtester.com/obj/b55ec3ac-dfa4-4f44-81e8-f963ea4a0625

Stanley
sumber
4
@HOESENGKIANG: Anda harus mengklik tanda centang untuk "menerima" jawaban ini, atau siapa pun yang menurut Anda paling menjawab pertanyaan.
LarsH
23

T: Bagaimana cara memilih node menggunakan XPath jika node saudara memiliki nilai tertentu?
Karena hanya ada "Sumbu XPath" untuk saudara berikut dan saudara sebelumnya, Anda dapat menggunakan salah satu dari mereka jika posisinya ditetapkan.

Tetapi lebih baik: Carilah jika ccorang tua memiliki anak bbdengan nilai 'zz':

//cc[../bb='zz']
hr_117
sumber
6
Baik itu atau //a[bb = 'zz']/cc.
Tomalak
Tidak yakin apa yang Anda maksud dengan 'hanya "XPath Axes" untuk saudara-saudara berikut dan saudara-saudara sebelumnya'. Apakah Anda mengacu pada fakta bahwa tidak ada satu sumbu untuk semua saudara kandung?
LarsH
@ LarsH: Ya maaf, (maafkan bahasa Inggris saya yang buruk :-() - itulah yang ingin saya katakan. (Karena pertanyaannya untuk saudara kandung.)
hr_117
6

Pertama, contoh Anda bukanlah XML dengan format yang baik. Melihat itu dan bahwa Anda tidak menggambarkan maksud Anda dengan baik (Apa sebenarnya yang ingin Anda pilih dalam kondisi apa?), Saya berasumsi Anda ingin melakukan ini:

//cc[preceding-sibling::bb[text()="zz"]]/text()

Itu memilih

TEXT VALUES OF ALL <CC> ELEMENTS
//cc                                    /text()
    THAT HAVE A PRECEDING SIBLING <BB>
    [preceding-sibling::bb             ]
                          THAT HAS TEXT VALUE EQUAL TO "zz"
                          [text()="zz"]

Anda bisa menulis juga sebagai

//bb[text()="zz"]/following-sibling::cc/text()

Silakan lihat spesifikasinya , ini memiliki beberapa contoh yang dapat dibaca dengan sangat baik dari mana Anda akan belajar banyak.

Petr Janeček
sumber
1
@ LarsH Terima kasih atas koreksi dari "tidak valid" menjadi "tidak terbentuk dengan baik". Saya belajar sesuatu yang baru hari ini.
Petr Janeček
4
//a/cc[../bb='zz']/text()

// a: Memilih semua elemen 'a' dimanapun itu.

// a / cc: Memilih elemen 'cc' yang merupakan turunan dari elemen 'a' (di mana pun a berada).

..: Memilih induk dari node saat ini.

[../bb='zz ']: dimana nilai dari elemen sibling' bb 'adalah zz.

Referensi: http://www.w3schools.com/xsl/xpath_syntax.asp

Bae Cheol Shin
sumber
4

Solusi lain untuk masalah ini adalah

//bb[contains(.,'zz')]/../cc/text()

Penjelasan : Setiap bbyang berisi 'zz'string di semua node anak bbkemudian pergi ke node induk yang bbmenggunakan .., sekarang kita dapat mengakses ccteks yang kembali.

Saya harap penjelasan itu tidak rumit.

Saleh Mahmood
sumber