xpath znajdź, jeśli węzeł istnieje

201

Używając zapytania xpath, jak sprawdzić, czy w ogóle istnieje węzeł (znacznik)?

Na przykład, jeśli muszę upewnić się, że strona internetowa ma poprawną podstawową strukturę, taką jak / html / body i / html / head / title

EddyR
źródło
Może lepiej jest użyć schematu XML ze wskazaniem elementów obowiązkowych? Sprawdź, czy dokument go używa, czy nie.
abatishchev

Odpowiedzi:

321
<xsl:if test="xpath-expression">...</xsl:if>

więc na przykład

<xsl:if test="/html/body">body node exists</xsl:if>
<xsl:if test="not(/html/body)">body node missing</xsl:if>
Patrick McDonald
źródło
41
Zaskoczony tak wysoką oceną, biorąc pod uwagę, że pytanie w ogóle nie określa użycia XSLT.
tjmoore
To jest niesamowite, ale co jeśli chcę sprawdzić, czy istnieje LUB jest puste?
SearchForKnowledge
3
@SearchForKnowledge, powinieneś prawdopodobnie zadać to pytanie jako nowe pytanie w SO, ale jako szybki przewodnik: html/body and not(html/body/node())(tj. Po prostu sprawdź, czy istnieje i nie zawiera żadnych węzłów podrzędnych ani węzłów tekstowych).
Abel,
71

Wypróbuj następujące wyrażenie: boolean(path-to-node)

Anneley
źródło
3
Właśnie tego potrzebowałem, używając XPath w Pythonie z lxml.
Iain Samuel McLean Starszy
1
Przydało się
3
To poprawna odpowiedź w tym sensie, że w rzeczywistości jest to zapytanie XPath, w przeciwieństwie do większości innych odpowiedzi.
Paul Etherton
48

Patrick ma rację, zarówno w użyciu xsl:if, jak i w składni do sprawdzania istnienia węzła. Jednak, jak sugeruje odpowiedź Patryka, nie ma żadnego odpowiednika xsl dla „jeśli-to-inaczej”, więc jeśli szukasz czegoś bardziej podobnego do „jeśli-to-inaczej”, zwykle lepiej jest użyć xsl:choosei xsl:otherwise. Tak więc przykładowa składnia Patricka będzie działać, ale jest to alternatywa:

<xsl:choose>
 <xsl:when test="/html/body">body node exists</xsl:when>
 <xsl:otherwise>body node missing</xsl:otherwise>
</xsl:choose>
gkrogers
źródło
+1 za zauważenie if-then-else, a co z tego if-else if-else? Czy w odpowiedzi davenpcj mogę umieścić test="somexpath"na drugim miejscu, kiedy to zrobić if-else if-else?
AabinGunz,
3
@Abhishek Tak, możesz umieścić więcej xsl: w przypadku innych warunków i mieć instrukcję wielobranżową. Pomyśl o tym bardziej jak o WYBORZE niż o tym, jeśli-a-jeszcze, z xsl: w przeciwnym razie jako domyślną :.
davenpcj
To jest niesamowite, ale co jeśli chcę sprawdzić, czy istnieje LUB jest puste?
SearchForKnowledge
13

Być może lepiej będzie skorzystać z wyboru, nie musisz wpisywać (lub być może pomylić) swoich wyrażeń więcej niż jeden raz i pozwala ci śledzić dodatkowe różne zachowania.

Bardzo często używam count(/html/body) = 0, ponieważ konkretna liczba węzłów jest bardziej interesująca niż zestaw. Na przykład ... gdy nieoczekiwanie jest więcej niż 1 węzeł pasujący do Twojego wyrażenia.

<xsl:choose>
    <xsl:when test="/html/body">
         <!-- Found the node(s) -->
    </xsl:when>
    <!-- more xsl:when here, if needed -->
    <xsl:otherwise>
         <!-- No node exists -->
    </xsl:otherwise>
</xsl:choose>
davenpcj
źródło
Jak wskazano w powyższym kodzie, więcej xsl: when można dodać klauzule, aby zmienić zachowanie i obsługiwać wiele warunków na różne sposoby.
davenpcj
count(/html/body) = 0 geniusz! : DI używam go /html[count(/body)=0]/someNodedo wybierania, someNodekiedy /body(lub cokolwiek) brakuje
Stefan Rogin
1
@clickstefan, /html[count(/body)=0]nigdy niczego nie wybierze, w XML nie mogą znajdować się dwa węzły główne. Może miałeś na myśli /html[count(body)=0], co byłoby takie samo jak /html[not(body)]lub /html[not(exists(body))].
Abel
@Abel tak, / html [count (// body) = 0] lub jak to powiedziałeś, haniebne, ale tak nie podałem właściwego przykładu
Stefan Rogin
4

Pracuję w Ruby i za pomocą Nokogiri pobieram element i sprawdzam, czy wynik jest zerowy.

require 'nokogiri'

url = "http://somthing.com/resource"

resp = Nokogiri::XML(open(url))

first_name = resp.xpath("/movies/actors/actor[1]/first-name")

puts "first-name not found" if first_name.nil?
Bcolfer
źródło
3

Odmiana przy użyciu xpath w Javie przy użyciu count ():

int numberofbodies = Integer.parseInt((String) xPath.evaluate("count(/html/body)", doc));
if( numberofbodies==0) {
    // body node missing
}
użytkownik324898
źródło