2015-08-26 4 views
1

Я пытаюсь выработать XPath от <a id='me'>match</a>, который будет соответствовать элементам, находящимся на одном уровне. IE. Братья, сестры, кузены, троюродные и т.д. ...XPath для возврата всех элементов на одном уровне

Используя следующий XML, выражение XPath из первого <a id='me'>match</a>, который возвращает все элементы на одном уровне с идентификатором атрибута из «я»: -

<alpha> 
    <beta> 
     <gamma1> 
      <a id='me'>match</a> 
      <a id='me'>match me too</a> 
      <b id='me'>no match</b> 
     </gamma1> 
     <gamma2> 
      <a id='notme'>no match</a> 
      <a id='me'>match</a> 
      </b> 
     </gamma2> 
    </beta> 
    <delta> 
     <epsilon> 
      <a id='notme'>no match</a> 
      <a id='me'>match</a> 
      </b> 
      <foo> 
       <a id='me'>no match</a> 
      </foo> 
     </epsilon> 
    </delta> 
    <bar> 
     <a id='me'>no match</a> 
    </bar> 
</alpha> 

.\..\a[@id='me'] вернет два элемента в <gamma1> и .\..\..\*\a[@id='me'] вернет соответствующие элементы в <gamma1> и <gamma2>. Тем не менее, я пытаюсь сделать XPath, который вернет все соответствующие элементы на одном уровне в документе, не имеющие значения их глубины.

Я мог бы цикл в коде, идя вверх и вниз с помощью построения динамических XPaths, но это не будет очень элегантно и, вероятно, займет много времени, чтобы запустить ..

Любой человек с какой-либо идеи?

+0

Возможно [это] (http://stackoverflow.com/questions/3174622/get-elements-of-specific-hierarchy-level) может помочь? – vesan

ответ

1

Ответ, уже даваемый Lingamurthy, совершенно верен, но я хотел бы указать еще один способ взглянуть на проблему. Вы объяснили, что вы оцениваете выражения XPath с определенным узлом в качестве отправной точки, /alpha/beta/gamma1/a[1]. Поэтому я предполагаю, что вы знаете точное местоположение этого узла, даже если ничего не известно о документе.

Если это справедливо в вашем случае, вы можете просто считать родоначальниками этого узла (после ancestor::* оси) и выбрать только a элементы с одинаковым числом предков:

//a[@id = 'me' and count(ancestor::*) = count(/alpha/beta/gamma1/a[1]/ancestor::*)] 

и результат быть (отдельные результаты разделены ---------):

<a id="me">match</a> 
----------------------- 
<a id="me">match me too</a> 
----------------------- 
<a id="me">match 
</a> 
----------------------- 
<a id="me">match 
</a> 

Опять же, за исключением первого результата в этом списке с техникой, показанной на другой ответ, (...)[position() != 1], если это имеет значение для у ОУ.

К слову: ваш входной текст недействителен, есть два элемента a, которые неправильно закрыты.

+0

Предки - это то, что я искал. Решение Лингамурти работает, и это то, что я делаю; проблема заключалась в том, что мне нужно было подняться на достаточные уровни, чтобы обеспечить соответствие всех матчей на интересующем меня уровне. Проблема в том, что я могу попасть в корневой элемент. Используя ancestor :: * и подсчитывая уровни, а затем используя это для фильтрации совпадений для всех DOM, он отлично работает. Спасибо всем. –

+0

Исправлены два незакрытых элемента а также - спасибо Матиасу –

0

Как насчет:

(../../*/a[@id = 'me'])[position() != 1] 

Здесь XPath выбирает все внуки родителя родителя узла контекста, и с помощью position() != 1, он удаляет сам узел контекста (при условии, что узел контекста был первым в список, как вы упомянули в своем вопросе).

+0

Добавьте еще один '/../', чтобы также получить последний соответствующий 'a' в' delta'. '(/alpha/beta/gamma1/a[1]/../../../*/*/a[@id = 'me']) [position()! = 1]' при условии, что корневой узел в качестве отправной точки, '(../../../*/*/a[@id = 'me']) [position()! = 1]' в противном случае. –

Смежные вопросы