XPath: Як вибрати елементи на основі їх значення?


221

Я новачок у використанні XPath, і це може бути основним питанням. Ласкаво поводьтеся зі мною і допоможіть мені у вирішенні питання. У мене такий XML-файл:

<RootNode>
  <FirstChild>
    <Element attribute1="abc" attribute2="xyz">Data</Element>
  <FirstChild>
</RootNode>

Я можу підтвердити наявність <Element>тегу за допомогою:

// Element [@ attribute1 = "abc" та @ attribute2 = "xyz"]

Тепер я також хочу перевірити значення тега для рядка "Data". Для досягнення цього мені сказали:

// Element [@ attribute1 = "abc" та @ attribute2 = "xyz" та Дані]

Коли я використовую пізніший вираз, я отримую таку помилку:

Повідомлення про помилку твердження: Ніякі вузли не збігаються //Element[@attribute1="abc" and @attribute2="xyz" and Data]

Будь ласка, надайте мені свої поради, чи вираження XPath, яке я використав, є дійсним. Якщо ні, що буде дійсним виразом XPath?

Відповіді:


329

Умова нижче:

//Element[@attribute1="abc" and @attribute2="xyz" and Data]

перевіряє наявність елемента Дані в Елементі, а не на значення даних Елемент.

Натомість ви можете використовувати

//Element[@attribute1="abc" and @attribute2="xyz" and text()="Data"]

25
//Element[@attribute1="abc" and @attribute2="xyz" and .="Data"]

Причина, чому я додаю цю відповідь, полягає в тому, що я хочу пояснити взаємозв'язок .і text().

Перше, що при використанні []є лише два типи даних:

  1. [number] щоб вибрати вузол з набору вузлів
  2. [bool] для фільтрації набору вузлів з набору вузлів

У цьому випадку значення оцінюється булевим за функцією boolean(), і існує правило:

Фільтри завжди оцінюються відповідно до контексту.

Коли вам потрібно порівняти text()або .з рядком "Data", він спочатку використовує string()функцію для перетворення їх у тип рядка, ніж отримує бульний результат.

Є два важливих правила щодо string():

  1. string()Функція перетворює набір вузлів в рядок, повертаючи строкове значення першого вузла в наборі вузлів, який в деяких випадках може привести до непередбачуваних результатів.

    text()- відносний шлях, який повертає набір вузлів, містить увесь текстовий вузол поточного вузла (контекстний вузол), наприклад ["Data"]. Коли він буде оцінений string(["Data"]), він поверне перший вузол набору вузлів, тому ви отримаєте "Дані" лише тоді, коли в наборі вузлів є лише один текстовий вузол.

  2. Якщо ви хочете, щоб string()функція об'єднала весь дочірній текст, вам слід передавати один вузол замість набору вузлів.

    Наприклад, ми отримуємо набір вузлів ['a', 'b'], ви можете передати туди батьківський вузол string(parent), він повернеться 'ab', і причиною string(.)у вашому випадку повернеться об'єднана рядок "Data".

Обидва способи отримають однаковий результат лише тоді, коли є текстовий вузол.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.