Operations Orchestration Practitioners Forum
Showing results for 
Search instead for 
Do you mean 

How to manage XML namespaces (xmlns) in XPath result filter?

Occasional Contributor

How to manage XML namespaces (xmlns) in XPath result filter?

Hello,

I'm using XPath result filter to obtain an attribute value from a returned XML document. The trouble is that the returned document contains definition of the default namespace (xmlns attribute in the root element). According to XPath spec, unprefixed names are in 'no namespace'; to reference elements from a defined namespace, the namespace must be registered first and then use the namespace prefix when referencing the namespaced elements.

 

I'm trying to reference this attribute in the attached XML: /server/image/@id

 

However, this XPath does not work (unsurprisingly, as I did not register the namespace ""http://docs.openstack.org/compute/api/v1.1").

 

The only workaround I found out so far is to use this XPath instead: /server/*[name()='image']/@id

 

I don't like the workaround and would rather use the clean solution - register the namespace; but how to do it in OO?

 

Thanks,

Petr Panuska

3 REPLIES
Highlighted
Advisor

Re: How to manage XML namespaces (xmlns) in XPath result filter?

I couldnt find an easy solution to your request. 

 

It is possible to use Java via JavaScript (since OO uses Rhino) to use the Java XPath capabilities. 

 

You can create a scriptlet with two inputs "xmlInput", "xpathExpr". And then give it this code:

function stringToBytes(str){
var ch, st, re = [];
for(var i = 0; i < str.length; i++){
ch = str.charCodeAt(i);
st = [];
do{
st.push( ch & 0xFF );
ch = ch >> 8;
}
while(ch);
re = re.concat(st.reverse());
}
return re;
}

var dbFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
var dBuilder = dbFactory.newDocumentBuilder();
var doc = dBuilder.parse(new java.io.ByteArrayInputStream(stringToBytes(xmlInput)));
var xPathfactory = javax.xml.xpath.XPathFactory.newInstance();
var xpath = xPathfactory.newXPath();

scriptletResponse = "success";
scriptletResult = xpath.evaluate(xpathExpr, doc);

 

 

We will look at improving this in a future version of OO.

 

HTH,

Emil

 

HP Software OO RnD, Community Assistance Team, https://hpln.hp.com/group/operations-orchestration
Regular Visitor

Re: How to manage XML namespaces (xmlns) in XPath result filter?

Last post from HPE: "We will look at improving this in a future version of OO."

It has been close to two years since this statement; since I can hardly remember EVER seeing XPATH used in production without namespaces, I wonder why this wasn't baked in from the beginning?

In the current (10.50) CP "Base [1.6.2]", I still don't see any way to specify one or more namespaces in the "XPath Query" flow.

For example, I'm trying to process the output of the SiteScope API getHostsMap which produces XML of the form:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <ns1:getHostsMapResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://configuration.api.sitescope.mercury.com">
         <getHostsMapReturn href="#id0"/>
      </ns1:getHostsMapResponse>
      <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Map" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://xml.apache.org/xml-soap">
         <item>
            <key xsi:type="soapenc:string">monitoredhostname.ourcompany.com</key>
            <value href="#id1"/>
         </item>
      </multiRef>
      <multiRef id="id7" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:Map" xmlns:ns3="http://xml.apache.org/xml-soap" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
         <item>
            <key xsi:type="soapenc:string">TotalMonitorReferences</key>
            <value xsi:type="soapenc:string">11</value>
         </item>
      </multiRef>
      </multiRef>
   </soapenv:Body>
</soapenv:Envelope>

When the namespaces are defined, the XPath for the desired results is:

/soapenv:Envelope/soapenv:Body/multiRef[@xsi:type='ns2:Map']/item[key]

But I've been unable so far to parse out the host names using just native flows. I would prefer to do it without having to dive down into Java, but I'm not seeing anything.

Occasional Advisor

Re: How to manage XML namespaces (xmlns) in XPath result filter?

Hello,

"XPath Query" operation supports XML namespaces, but it has a different behavior when working with namespace-prefixed-attributes, like xsi:type.

You can use predicates for selecting the type attribute with ns2:Map value:

/soapenv:Envelope/soapenv:Body/multiRef[@*[local-name()='type' and .='ns2:Map']]/item[key]

Note that you have a duplicate </multiRef> tag in the document document, it will throw a validation error.

Hope it helps,

Ligia