Выражение Xpath для поиска элемента, у которого НЕТ соответствующего предка

Я пытаюсь использовать xpath для извлечения микроданных HTML5 со страницы. По сути, я пытаюсь сказать «найти вложенные узлы с атрибутом itemprop = name, которые не вложены в другой элемент itemscope (на любой глубине)». В следующем примере я пытаюсь найти название продукта (обувь), но мне не нужно название бренда (Nike).

<div itemscope itemtype="http://schema.org/Product>
  <div itemscope itemtype="http://schema.org/Brand">
    <div itemprop="name">Nike</div> <!-- don't want this -->
  </div>
  <div itemprop="name">shoes</div> <!-- do want this -->
</div>

Я могу легко найти элемент itemprop = name, используя что-то вроде // * [@ itemprop = name], но это также приведет к появлению названия бренда. Кстати, элементы, показанные в примере, могут быть вложены в другие теги, поэтому я не могу просто сказать, «чей непосредственный родитель не имеет атрибута itemscope». Я считаю, что может быть что-то, относящееся к предкам, которое я могу использовать, но я не знаю хватит про xpath. Любые идеи?


person Community    schedule 14.10.2014    source источник
comment
В этом примере shoes находится внутри itemscope, поэтому для пояснения вы хотите, чтобы имена имели не более одного itemscope предка, но не имена, у которых более одного?   -  person Ian Roberts    schedule 14.10.2014
comment
Или вы имеете в виду, что для любого данного itemscope элемента X извлекать все имена, которые находятся внутри X, но не внутри любого другого itemscope?   -  person Ian Roberts    schedule 14.10.2014
comment
Я использую libxml2 (xmlsoft.org) через python. Чтобы ответить на ваши первоначальные вопросы, на самом деле в этом контексте будет достаточно любого сценария, но я думаю, что в целом второй сценарий, вероятно, ближе.   -  person    schedule 14.10.2014
comment
libxml2 ограничен XPath 1.0, поэтому подход с использованием не более одного предка - лучшее, что вы действительно можете сделать в одном XPath.   -  person Ian Roberts    schedule 14.10.2014
comment
круто, это должно сработать. Из интереса, можно ли сделать все имена, которые находятся внутри X, но не внутри любой другой области, используя несколько выражений?   -  person    schedule 14.10.2014
comment
См. Последнее изменение моего ответа.   -  person Ian Roberts    schedule 14.10.2014
comment
Большое спасибо, Ян, очень признателен   -  person    schedule 14.10.2014


Ответы (2)


Одно выражение для поиска всех itemprop="name" элементов с не более чем одним itemscope предком было бы

//*[@itemprop = 'name'][not(ancestor::*[@itemscope][2])]

Если вы хотите начать с одного конкретного itemscope узла и найти имена, вложенные именно в it (а не во вложенную область видимости), то это не то, что вы можете сделать в одном выражении XPath 1.0. Вам нужно сначала извлечь его имена потомков

.//*[@itemprop='name']

а затем для каждого из них найдите ближайшего itemscope предка

ancestor::*[@itemscope][1]

и проверьте (на стороне Python), совпадает ли этот узел с тем, с которого вы начали. В XPath 2.0 это можно было сделать одновременно с

for $me in . return (.//*[@itemprop='name'][ancestor::*[@itemscope][1] is $me])

но 1.0 не имеет структуры for $x in Y return Z для привязки переменных или оператора is для сравнения идентичности узлов.

person Ian Roberts    schedule 14.10.2014
comment
Предок itemscope правильно? вот как я понял ваш xpath - person ; 14.10.2014
comment
@TobyHobson Да, извините, я исправил опечатку. - person Ian Roberts; 14.10.2014

Пожалуйста, попробуйте это:

//*[@itemprop = 'name' and not(ancestor::*[@itemscope][2])]
person JLRishe    schedule 14.10.2014