Link to home
Start Free TrialLog in
Avatar of Pradeep0308
Pradeep0308Flag for India

asked on

Xpath Assistance

Hi,

I have a SOAP response received as below:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Body>
            <s:Fault>
                  <faultcode>s:Server</faultcode>
                  <faultstring>Fatura ID sistemde mevcut</faultstring>
                  <detail>
                        <ProcessingFault xmlns="http:/abcde.com/eInvoice/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                              <Code>3012</Code>
                              <Message>ABCDE</Message>
                        </ProcessingFault>
                  </detail>
            </s:Fault>
      </s:Body>
</s:Envelope>

I want to check the existence of the element Code or Message using string-length and if it is greater than zero. How can I achieve that using the Xpath.

Regards
Pradeep
ASKER CERTIFIED SOLUTION
Avatar of Gertone (Geert Bormans)
Gertone (Geert Bormans)
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
XPath 1.0 if you can't use a namespace manager
//*[local-name() = 'Code'][normalize-space(.)] | //*[local-name() = 'Message'][normalize-space(.)]
Note that a node-set in a boolean expression returns false() when empty,
so in an XSLT you would do
<xsl:if test="//*[local-name() = 'Code'][normalize-space(.)] | //*[local-name() = 'Message'][normalize-space(.)] ">...
And XPath1.0 and you would be able to use a namespace manager

//abc:Code[normalize-space(.)] | //abc:Message[normalize-space(.)]

just make sure you bind prefix abc: to this namespace in the namespacemanager "http:/abcde.com/eInvoice/"
Avatar of Pradeep0308

ASKER

Hi Geert,

I can use Xpath 2.0 If you are suggesting not to use string-length than how should I check the existence of either of these two elements and then do a certain step?

Regards
Pradeep
By string casting
//*:Code[string(.)]
or
//*:Code[normalize-space(.)]

both string() and normalize-space() cast the node to string
the [] requires a boolean expression inside
casting a string to a boolean expression returns true() if the string length is > 0

//*:Code[string(.)]
will only return true() if there is a Code element in the envelope that has a stringvalue other than the empty string
Thanks Geert. Will this return true() or only true?
//*:Code[string(.)]
will return the node-set of all the *:Code elements that have non zero content

If you use //*:Code[string(.)] in a test (anywhere Xpath expects a boolean expression, example: inside the test attribute of an if statement in XSLT, inside an if() or inside the predicate [], ...)
then it will return an xs:boolean
true() when the node-set is not empty
false() when the node-set is empty

that is because of the casting rules from node-set to boolean
ok so what happens if I do CodeTest=//*:Code[string(.)]

Will CodeTest have the value as xs:boolean i.e. true()?
no, it will contain the nodeset
but you can force the boolean cast
 CodeTest=boolean(//*:Code[string(.)])

be carefull not to cast to boolean prematurely
if you have this
CodeTest=//*:Code[string(.)]
and you remember that Codetest is a nodeset, not a boolean,
it will cast to boolean more efficiently when you use it in a test
Thanks Geert. Do you provide any freelance consulting on XML and related technologies? Like Xpath and XSLT?

Regards
Pradeep
Hi Pradeep,
Yes I do, I am a full time XML/XSLT freelance consultant.
If you want to contact me, you can push the "hire me" button or find my email adress on my profile page