XPath: jak wybrać elementy na podstawie ich wartości?

221

Jestem nowy w używaniu XPath i może to być podstawowe pytanie. Prosimy o wyrozumiałość i pomoc w rozwiązaniu problemu. Mam plik XML taki jak ten:

<RootNode>
  <FirstChild>
    <Element attribute1="abc" attribute2="xyz">Data</Element>
  <FirstChild>
</RootNode>

Mogę sprawdzić obecność <Element>tagu za pomocą:

// Element [@ atrybut1 = „abc” i @ atrybut2 = „xyz”]

Teraz chcę również sprawdzić wartość tagu dla ciągu "Data". Aby to osiągnąć, kazano mi użyć:

// Element [@ atrybut1 = „abc” i @ atrybut2 = „xyz” i dane]

Kiedy używam późniejszego wyrażenia, pojawia się następujący błąd:

Komunikat o niepowodzeniu asercji: Brak pasujących węzłów //Element[@attribute1="abc" and @attribute2="xyz" and Data]

Prosimy o udzielenie porady, czy użyte wyrażenie XPath jest prawidłowe. Jeśli nie, jakie będzie prawidłowe wyrażenie XPath?

vcosk
źródło

Odpowiedzi:

329

Warunek poniżej:

//Element[@attribute1="abc" and @attribute2="xyz" and Data]

sprawdza istnienie elementu Dane w elemencie, a nie dane o wartości elementu.

Zamiast tego możesz użyć

//Element[@attribute1="abc" and @attribute2="xyz" and text()="Data"]
Użytkownik SO
źródło
25
//Element[@attribute1="abc" and @attribute2="xyz" and .="Data"]

Powodem, dla którego dodaję tę odpowiedź jest, że chcę, aby wyjaśnić związek .i text().

Pierwszą rzeczą jest to [], że podczas używania istnieją tylko dwa typy danych:

  1. [number] aby wybrać węzeł z zestawu węzłów
  2. [bool] aby odfiltrować zestaw węzłów z zestawu węzłów

W tym przypadku wartość jest obliczana na wartość logiczną według funkcji boolean()i obowiązuje reguła:

Filtry są zawsze oceniane pod względem kontekstu.

Kiedy trzeba porównać text()lub .z łańcuchem "Data", najpierw używa string()funkcji, aby przekształcić je w typ łańcucha, a następnie otrzymuje wynik logiczny.

Istnieją dwie ważne zasady dotyczące string():

  1. string()Przekształca zbiór węzłów na sznurku przez zwrócenie ciągu znaków pierwszego węzła w zestaw węzłów, które w niektórych przypadkach mogą przynieść nieoczekiwane efekty.

    text()jest ścieżką względną, która zwraca zestaw węzłów, zawiera wszystkie węzły tekstowe bieżącego węzła (węzła kontekstu), podobnie jak ["Data"]. Gdy zostanie oszacowany przez string(["Data"]), zwróci pierwszy węzeł zestawu węzłów, więc „Dane” otrzymasz tylko wtedy, gdy w zestawie węzłów jest tylko jeden węzeł tekstowy.

  2. Jeśli chcesz, aby string()funkcja konkatenowała cały tekst potomny, musisz przekazać pojedynczy węzeł zamiast zestawu węzłów.

    Na przykład otrzymujemy zestaw węzłów ['a', 'b'], możesz przekazać do niego węzeł nadrzędny string(parent), to zwróci 'ab', a string(.)w twoim przypadku zwróci połączony ciąg "Data".

Oba sposoby uzyskają ten sam wynik tylko wtedy, gdy istnieje węzeł tekstowy.

宏杰 李
źródło