xmlnamespacesxqueryxml-namespacesxquery-3.0

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.


Solution

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