ChatGPT解决这个技术问题 Extra ChatGPT

XPath find if node exists

Using a XPath query how do you find if a node (tag) exists at all?

For example if I needed to make sure a website page has the correct basic structure like /html/body and /html/head/title.

Maybe it's better to use XML Schema with obligatory elements indication? So check that a document uses it or not.

P
Patrick McDonald
<xsl:if test="xpath-expression">...</xsl:if>

so for example

<xsl:if test="/html/body">body node exists</xsl:if>
<xsl:if test="not(/html/body)">body node missing</xsl:if>

@SearchForKnowledge, you should probably ask that as a new question at SO, but as a quick guide: html/body and not(html/body/node()) (i.e., just test if it exists and it does not contain any child nodes, or text nodes).
A
Abel

Try the following expression: boolean(path-to-node)


This is exactly what I needed when using XPath in Python with lxml.
This worked a treat when constructing Rule Conditions and Rule Actions within InfoPath 2010.
This is the correct answer in the sense that this is actually an XPath query, unlike most of the other answers.
P
Patrick McDonald

Patrick is correct, both in the use of the xsl:if, and in the syntax for checking for the existence of a node. However, as Patrick's response implies, there is no xsl equivalent to if-then-else, so if you are looking for something more like an if-then-else, you're normally better off using xsl:choose and xsl:otherwise. So, Patrick's example syntax will work, but this is an alternative:

<xsl:choose>
 <xsl:when test="/html/body">body node exists</xsl:when>
 <xsl:otherwise>body node missing</xsl:otherwise>
</xsl:choose>

+1 for noting if-then-else, also what about if-else if-else? In davenpcj's answer can I place test="somexpath" in the 2nd when to make it if-else if-else?
@Abhishek Yes, you can put more xsl:when with other conditions and have a multi-branch statement. Think of it more like a SELECT than an if-then-else, with xsl:otherwise as the default:.
This is awesome but what if I wanted to check if it exists OR empty?
d
davenpcj

Might be better to use a choice, don't have to type (or possibly mistype) your expressions more than once, and allows you to follow additional different behaviors.

I very often use count(/html/body) = 0, as the specific number of nodes is more interesting than the set. For example... when there is unexpectedly more than 1 node that matches your expression.

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

As indicated in the code above, more xsl:when clauses can be added to change the behavior and handle multiple conditions in different ways.
count(/html/body) = 0 genius ! :D I use it as /html[count(/body)=0]/someNode for selecting someNode when /body (or whatever) is missing
@clickstefan, /html[count(/body)=0] will never select anything, there cannot be two root nodes in XML. Maybe you meant /html[count(body)=0], which would be the same as /html[not(body)], or /html[not(exists(body))].
@Abel yes, /html[count(//body)=0] or how you said, shameful but yes I didn't give a proper example
b
bcolfer

I work in Ruby and using Nokogiri I fetch the element and look to see if the result is nil.

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?

u
user324898

A variation when using xpath in Java using count():

int numberofbodies = Integer.parseInt((String) xPath.evaluate("count(/html/body)", doc));
if( numberofbodies==0) {
    // body node missing
}