XPath: получить узлы, где дочерний узел содержит атрибут - PullRequest
95 голосов
/ 22 сентября 2009

Предположим, у меня есть следующий 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>

Есть намеки? Заранее спасибо.

Ответы [ 5 ]

152 голосов
/ 22 сентября 2009

Попробуйте

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

Это гласит:

  • получить все book элементов
    • с хотя бы одним title
      • с атрибутом lang
        • со значением "it"

Вы можете найти это полезным - это статья Рональда Бурре под названием "XPath в пяти абзацах" .

Но, честно говоря, //book[title[@lang='it']] и выше должны быть эквивалентны, если у вашего движка XPath нет «проблем». Таким образом, это может быть что-то в коде или примере XML, которое вы нам не показываете - например, ваш образец представляет собой фрагмент XML. Может ли быть так, что корневой элемент имеет пространство имен, и вы не учитываете это в своем запросе? И вы только сказали нам, что это не сработало, но вы не сказали нам, какие результаты вы получили.

43 голосов
/ 08 мая 2013

Спустя годы, но полезным вариантом будет использование осей XPath (https://www.w3schools.com/xml/xpath_axes.asp). В частности, вы хотите использовать потомков осей.

Полагаю, этот пример поможет:

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

Это позволяет вам выбрать все элементы book, которые содержат дочерний элемент title (независимо от его глубины вложенности), содержащий значение атрибута языка, равное 'it'.

Я не могу точно сказать, относится ли этот ответ к 2009 году, поскольку я не уверен на 100%, что в то время существовали Оси XPath. Я могу подтвердить, что они существуют сегодня, и я нашел их чрезвычайно полезными в навигации по XPath, и я уверен, что вы тоже это сделаете.

9 голосов
/ 22 сентября 2009
//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 ");*/

      }
  }
}
3 голосов
/ 21 декабря 2012

Я думаю, что ваше собственное предложение верно, однако xml не совсем корректен. Если вы используете //book[title[@lang='it']] на <root>[Your"XML"Here]</root>, то бесплатные онлайн-тестеры xPath, такие как здесь , найдут ожидаемый результат.

0 голосов
/ 23 декабря 2011

Попробуйте использовать это выражение xPath:

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

Это должно дать вам все узлы книги в "it" lang

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...