2012-02-06 10 views
6

Oto coś naprawdę prostego (przynajmniej domyślam się), po prostu nie mam pojęcia.xpath uzyskuje ostatnie z określonych wcześniejszych rodzeństwa

Muszę parsować duży dokument XML, aby uzyskać określony węzeł, identyfikowany przez jedną z jego wartości podwęzłów. To łatwe do tej pory. Ale kiedy próbuję poczytać dalej od tego węzła stosunkowo w górę, wybierając poprzednie rodzeństwo jego przodka za pomocą predykatu otrzymuję listę węzłów, od tego muszę iść znowu w dół.

W Theorie, czyli w tabeli z 5 kolumnami i dwoma wierszami (w pokazanym przykładzie poniżej). Dostaję tylko element id jednego pola i muszę znaleźć nazwę podaną w pierwszym polu wiersza. Pierwsze pole jest zawsze typu "Link" i ma podwęzeł nazwy z tekstem - który jest tym, co można uzyskać.

Innymi słowy, muszę przenieść z dowolnego węzła z <id>XXX_X</i> do następnej komórki poprzedniego rodzica za pomocą kontroli xsi:type='Label' i węzła nazwy. Z węzła <id>MyItemId_1</> muszę uzyskać drugie poprzednie-rodzeństwo, z węzła <id>MyItemId_4</id> Muszę uzyskać piątego poprzedniego-rodzeństwo.

Jest to kawałek próbki 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> 

zrobić uzyskać pozycję Muszę z tym XPath:

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

To wybiera identyfikator kontroli celi, a mianowicie 4. kolumna w drugim wierszu renderowanej tabeli.

Od tego węzła na I spróbuj przenieść do pierwszej komórki w wierszu, wykonując tę ​​ścieżkę:

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

To daje mi dwóch prawidłowych komórek w pierwszej kolumnie tabeli.

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

Teraz łamie mi plecy, ponieważ nie mogę go odzyskać po ostatnim z dwóch wybranych.

Próbowałem to:

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

który jest wybór poprzedzający-rodzeństwo z orzecznika do dokładnie tego rodzaju rodzeństwa szukam, ale wydaje się, że nie może łączyć tego predykatu z [1] selektora . Zamiast wybierać pożądane pierwsze wcześniejsze rodzeństwo "MyItemName", wybiera pierwsze rodzeństwo z wszystkich poprzednich "MyOtherItemName".

Potrzebuję pomocy, mam nadzieję, że ktoś tutaj ma wskazówkę i może wskazać mi właściwy kierunek.

Dokładnie to skonfigurować, aby ta praca jest kopiowanie xml do http://www.bit-101.com/xpath/ i pracy z łączonych xpathes na nim symulować co program powinien:

//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

Próbujesz wybrać opcję "MójNazwa"? Jak to jest pierwsza komórka w rzędzie? Na pewno nie wygląda na to. –

+0

Zgubiłem go gdzieś pomiędzy tabelą 5 kolumn a pierwszym polem typu Link. Czy myślisz, że możesz powtórzyć swoje wymagania bez analogii ze stołem? –

+0

Zgadzam się z @ czterdzieści dwa. Często dobrze jest pokazać, co wypróbowałeś, więc dziękuję ci za tę pracę, ale w tym przypadku to, co próbowałem, zasłania twoje pierwotne wymagania. Zapomniałeś powiedzieć dokładnie i dokładnie * co * próbujesz zrobić w pierwszej kolejności. –

Odpowiedz

11

Nie rozumiem w czym problem dokładnie jest, ale poprzednie rodzeństwo jest sortowane od samego węzła w kierunku początku dokumentu, tj. odwrotnie niż w dokumencie. Aby uzyskać najbliższą poprzednią siostrę, użyj preceding-sibling[1], aby uzyskać najdalszą (tj. Pierwszą w kolejności dokumentu), użyj preceding-sibling[last()].

+0

To prawda, ale w jaki sposób mogę użyć wyboru pierwszego rodzeństwa tylko z poprzednich rodzeństwa, które pasuje do predykatu? używanie poprzedniego-siblinga [PREDICATE] [1] nie działa - nie zwraca węzła –

+3

Użyj 'previous-sibling :: * [PREDICATE] [1]' (działa dla mnie). – choroba

+0

spróbuj z bit-101/xpath, to nie zadziała, jeśli mieszasz predykat z selektorem. –

1

Po przeczytaniu aktualizację, nie będzie działać:

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

Jestem trochę pewności co do węzła nazwa: chcesz przetestować dla istnienia tekstu w węźle nazwa lub tylko istnienia samego węzła nazwy?

+0

to nie działa, jeśli próbuję go z http://www.bit-101.com/xpath/. po prostu nic nie zostaje wybrane. Pierwsza część, przed poprzednim-rodzeństwem działa w tym przykładzie. –

+0

Muszę przetestować, czy węzeł nazwy istnieje i czy mam tekst. –

+0

Właśnie wypróbowałem to w bit-101. Działa to dla mnie i wybiera komórkę o nazwie "MyOtherItemName" –

1

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

Tutaj 1 wskazuje tylko rodzeństwo powyżej wybranego węzła, a następnie można wykonać rekursję, aby uzyskać wszystkie poprzednie rodzeństwo od dołu do góry.

Powiązane problemy