2014-10-14 3 views
1

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

<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 = имя элемента, используя что-то вроде // * [@ itemprop = имя], но это также будет тянуть в названии бренда. Btw элементы, показанные в примере, могут быть вложены внутри других тегов, поэтому я не могу просто сказать: «У ближайшего родителя нет атрибута itemscope». Я полагаю, что может быть что-то относящееся к предкам, которые я могу использовать, но я не знаю достаточно о xpath. Есть идеи?

+0

В этом примере 'shoes' _is_ внутри' itemscope', поэтому для уточнения вы хотите, чтобы имена, которые имеют _that наиболее одного_ 'objectcope' предка, но не те, у которых более одного? –

+0

Или вы имеете в виду, что для _any_ данного элемента 'itemscope' X, извлекайте все имена, которые находятся внутри X, но также не находятся внутри каких-либо других предметов? –

+0

Я использую libxml2 (http://xmlsoft.org/) через python. Чтобы ответить на ваши исходные вопросы, на самом деле сценарий был бы достаточным в этом контексте, но я думаю, что второй вариант, вероятно, ближе. –

ответ

0

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

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

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

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

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

ancestor::*[@itemscope][1] 

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

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

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

+0

объект предка правого правого? вот как я понял ваш xpath –

+0

@TobyHobson Да, извините, я исправил опечатку. –

0

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

//*[@itemprop = 'name' and not(ancestor::*[@itemscope][2])] 
Смежные вопросы