62

Below is my element hierarchy. How to check (using XPath) that AttachedXml element is present under CreditReport of Primary Consumer

<Consumers xmlns="http://xml.mycompany.com/XMLSchema">
       <Consumer subjectIdentifier="Primary">
          <DataSources>
               <Credit>
                   <CreditReport>
                      <AttachedXml><![CDATA[ blah blah]]>
Sarah Trees
  • 822
  • 12
  • 28
Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327

6 Answers6

96

Use the boolean() XPath function

The boolean function converts its argument to a boolean as follows:

  • a number is true if and only if it is neither positive or negative zero nor NaN

  • a node-set is true if and only if it is non-empty

  • a string is true if and only if its length is non-zero

  • an object of a type other than the four basic types is converted to a boolean in a way that is dependent on that type

If there is an AttachedXml in the CreditReport of primary Consumer, then it will return true().

boolean(/mc:Consumers
          /mc:Consumer[@subjectIdentifier='Primary']
            //mc:CreditReport/mc:AttachedXml)
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
  • this is also returning true if AttachedXml is NOT PRESENT...what am I missing? – Aravind Yarram Apr 18 '11 at 14:56
  • It shouldn't. If it is returning `true()`, then the XPath is matching and selecting something. It should return `false()` if nothing is selected. – Mads Hansen Apr 18 '11 at 15:20
  • even worse: you will get false() if the node does not exist, but also if the node content evaluates to boolean false! – Enrice Aug 26 '23 at 07:28
6

The Saxon documentation, though a little unclear, seems to suggest that the JAXP XPath API will return false when evaluating an XPath expression if no matching nodes are found.

This IBM article mentions a return value of null when no nodes are matched.

You might need to play around with the return types a bit based on this API, but the basic idea is that you just run a normal XPath and check whether the result is a node / false / null / etc.

XPathFactory xpathFactory = XPathFactory.newInstance(NamespaceConstant.OBJECT_MODEL_SAXON);
XPath xpath = xpathFactory.newXPath();
XPathExpression expr = xpath.compile("/Consumers/Consumer/DataSources/Credit/CreditReport/AttachedXml");
Object result = expr.evaluate(doc, XPathConstants.NODE);

if ( result == null ) {
    // do something
}
Jon Gauthier
  • 25,202
  • 6
  • 63
  • 69
6

Use:

boolean(/*/*[@subjectIdentifier="Primary"]/*/*/*/*
                           [name()='AttachedXml' 
                          and 
                            namespace-uri()='http://xml.mycompany.com/XMLSchema'
                           ]
       )
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
4

Normally when you try to select a node using xpath your xpath-engine will return null or equivalent if the node doesn't exists.

xpath: "/Consumers/Consumer/DataSources/Credit/CreditReport/AttachedXml"

If your using xsl check out this question for an answer:

xpath find if node exists

Community
  • 1
  • 1
Simon Stender Boisen
  • 3,413
  • 20
  • 23
-1

If boolean() is not available (the tool I'm using does not) one way to achieve it is:

//SELECT[@id='xpto']/OPTION[not(not(@selected))]

In this case, within the /OPTION, one of the options is the selected one. The "selected" does not have a value... it just exists, while the other OPTION do not have "selected". This achieves the objective.

Boris Stitnicky
  • 12,444
  • 5
  • 57
  • 74
x_kiter
  • 23
  • 4
-1

take look at my example

<tocheading language="EN"> 
     <subj-group> 
         <subject>Editors Choice</subject> 
         <subject>creative common</subject> 
     </subj-group> 
</tocheading> 

now how to check if creative common is exist

tocheading/subj-group/subject/text() = 'creative common'

hope this help you

Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92