简体   繁体   中英

How to return last node having namespace in it using Xquery

I have this file, which have namespaces in it, I am trying to write a Xquery which will return, the last node having the namespace, but unabe to find the logic to return the namespace node(PS: I am new to Xquery)

XML File -

<XML>
  <SOAPMessage>
    <soapenv:Envelope   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Body>
        <postRequestResponse    xmlns="http://company.com">
          <postRequestReturn>
            <OnlineBRE  xmlns="">
              <Proccode>NUM</Proccode>
            </OnlineBRE>
          </postRequestReturn>
        </postRequestResponse>
      </soapenv:Body>
    </soapenv:Envelope>
  </SOAPMessage>
</XML>

  

I have tried a query to return node with exact string value, but that didn't work.

You can look for all elements in the document //* and test whether there is a namespace-uri() in a predicate filter, then select the last() element that has a namespace-uri() .

let $doc := 
  <XML>
    <bk:BOOK xmlns:bk="urn:example.microsoft.com:BookInfo" xmlns:money="urn:Finance:Money">
      <bk:TITLE>value1</bk:TITLE>
      <ONLINEBRE />
      <bk:PRICE money:currency="US Dollar">22.95</bk:PRICE>
    </bk:BOOK>
  </XML>
return ($doc//*[namespace-uri()])[last()]

Based on your comments on the Mads Hansen's answer I came up with this:

declare namespace array = "http://www.w3.org/2005/xpath-functions/array";

declare function local:ns-changed ($current as element(), $last-ns, $last-element) {
  $current/element() ! (
    let $child-ns := namespace-uri-from-QName(node-name(.))
    return
      if ( $child-ns = $last-ns )
      then local:ns-changed(., $last-ns, $last-element)
      else local:ns-changed(., $child-ns, .)
  ),
  $last-element
};

let $root :=
<XML>
  <SOAPMessage>
    <soapenv:Envelope   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Body>
        <postRequestResponse    xmlns="http://company.com">
          <postRequestReturn>
            <OnlineBRE  xmlns="">
              <Proccode>NUM</Proccode>
            </OnlineBRE>
          </postRequestReturn>
        </postRequestResponse>
      </soapenv:Body>
    </soapenv:Envelope>
  </SOAPMessage>
</XML>

let $initial-ns := namespace-uri-from-QName(node-name($root))
let $wanted := head(local:ns-changed($root, $initial-ns, $root))

return $wanted

I may not be pretty and inefficient and also only tested on your provided input, but it does what you want.

Here you can see it in action https://xqueryfiddle.liberty-development.net/3Nzd8c9/1

Currently it returns the last element where the namespace changed. To return the node-name or the value or something else modify the last line.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM