2012-02-06 3 views
6

Вот что-то очень простое (по крайней мере, я думаю), я просто не понимаю.xpath get last of specific previous-sibling

Мне нужно проанализировать большой XML-документ, чтобы получить определенный узел, определенный одним из значений его поднода. До сих пор это было легко. Но когда я пытаюсь разобраться с этим узлом относительно вверх, выбирая предшествовавших братьев и сестер его предка, используя предикат, я получаю список узлов, из которого я должен снова идти вниз.

В теоретике это таблица, состоящая из 5 столбцов и двух строк (в приведенном ниже примере). Я получаю только элемент id из одного поля и должен найти имя, указанное в первом поле строки. Первое поле всегда имеет тип «Ссылка» и имеет подназменное имя с текстом - это то, что нужно.

Другими словами, мне нужно перейти от любого узла с помощью <id>XXX_X</i> к следующей ячейке предшествующего собора с помощью элемента управления xsi:type='Label' и узла имени. От узла <id>MyItemId_1</> Мне нужно получить второго предшествующего брата, из узла <id>MyItemId_4</id> Мне нужно получить пятый предшествующий брат.

Это пример XML-часть:

<cell> 
    <control xsi:type="Label"> 
     <id>1234</id> 
     <name>MyOtherItemName</name> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>MyOtherItemId_0</id> 
     <name/> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>MyOtherItemId_1</id> 
     <name/> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyOtherItemId_2</id> 
     <name>552</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyOtherItemId_3</id> 
     <name>432</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyOtherItemId_4</id> 
     <name>33</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>1234</id> 
     <name>MyItemName</name> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>MyItemId_0</id> 
     <name/> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Label"> 
     <id>MyItemId_1</id> 
     <name/> 
     <message/> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyItemId_2</id> 
     <name>552</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyItemId_3</id> 
     <name>432</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 
<cell> 
    <control xsi:type="Button"> 
     <id>MyItemId_4</id> 
     <name>33</name> 
     <message/> 
     <type>Link</type> 
     <selected>false</selected> 
    </control> 
    <selected>false</selected> 
    <style>Odd</style> 
</cell> 

я получить деталь я должен получить этот XPath:

//cell[control[type='Link']]/control[type='Link' and selected='false' and id='MyItemId_3']/id 

Что выбирает идентификатор управления ячейки, а именно 4-й столбец во второй строке отображаемой таблицы.

С этого узла на Стараюсь движущемся к первой ячейке в строке следующий путь:

../../preceding-sibling::cell[control[@xsi:type='Label' and name[node()]]]/control[name[node()]]/name 

Это дает мне две правильные ячейки первого столбца таблицы.

<name>MyOtherItemName</name> 
* * * * * * * * * * 
<name>MyItemName</name> 

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

Я попытался это:

../../preceding-sibling::cell[control[@xsi:type='Label' and name[node()]]][1]/control[name[node()]]/name 

который является выбором предшествующего-родственным с предикатом точно родом братий и сестрами я ищу, но мне кажется, я не могу совместить этот предикат с [1] селектором , Вместо того, чтобы выбрать желаемый первый предшествующий родственный «MyItemName», он выбирает первого брата из всех предыдущих «MyOtherItemName».

Мне нужна помощь, надеюсь, что у кого-то есть ключ и может точно определить меня в правильном направлении.

Именно то, что я создал, чтобы получить эту работу копирования XML в http://www.bit-101.com/xpath/ и работать с каскадным xpathes на нем, чтобы имитировать то, что программное обеспечение должно сделать:

//cell[control[type='Link']]/control[type='Link' and selected='false' and id='MyItemId_3']/id/../../preceding-sibling::cell[control[@xsi:type='Label' and name[node()]]]/control[name[node()]]/name 
+0

Итак, вы пытаетесь выбрать 'MyItemName'? Как это первая ячейка в строке? Это не похоже на это. –

+0

Я потерял его где-то между 5 столбцами и первым полем типа Link. Как вы думаете, вы можете перефразировать свои требования без аналогий таблицы? –

+0

Согласитесь с сорок два. Часто бывает полезно показать, что вы пробовали, поэтому я благодарю вас за эту работу, но в этом случае то, что я пытаюсь, скрывает ваши первоначальные требования. Вы забыли сказать нам точно и точно, что * вы пытались сделать в первую очередь. –

ответ

11

Я не понимаю, в чем проблема точно, но предшествующие братья и сестры сортируются от самого узла к началу документа, то есть наоборот, чем в документе. Чтобы получить ближайший предыдущий брат, используйте preceding-sibling[1], чтобы получить самый дальний (т. Е. Первый в заказе документа), используйте preceding-sibling[last()].

+0

Это правильно, но как я могу использовать выбор первого брата только у тех, кто предшествует братьям и сестрам, с совпадением с предикатом? используя предыдущий-сиблинг [PREDICATE] [1] не работает - не возвращает ни одного узла –

+3

Используйте 'previous-sibling :: * [PREDICATE] [1]' (работает для меня). – choroba

+0

попробуйте с бит-101/xpath, это не сработает, если вы смешаете предикат с селектором. –

1

После прочтения вашего обновления, не будет этой работы:

//cell[control/id="MyItemId_4"]/preceding-sibling::cell[control[@xsi:type='Label'] and not(control/name='')][1] 

Я немного не уверен в узле имени: вы хотите, чтобы проверить наличие текста в узле имени или просто существование самого имени узла?

+0

это не работает, если я попробую его с http://www.bit-101.com/xpath/. просто ничего не выбирается. Первая часть, перед предыдущим братом, работает в этом примере. –

+0

Мне нужно протестировать, чтобы узел имени существовал и имел текст. –

+0

Просто попробовал в бит-101. Он работает для меня и выбирает ячейку с именем «MyOtherItemName» –

1

YourWebElement.FindElement (By.XPath ("previous-sibling :: * [1]"));

Здесь 1 указывает только родственного брата над выбранным узлом, а затем вы можете сделать рекурсию, чтобы получить всех предыдущих братьев и сестер снизу вверх.