javaxmlsoapxpathsoapheader

Extracting a term from SOAP header


I would like to extract an element called ServiceGroupID from the SOAP header, which specifies the session of the transaction. I would need this so that I could direct the request to the same server using SOAP session. My XML is as follow:

<?xml version="1.0" encoding="http://schemas.xmlsoap.org/soap/envelope/" standalone="no"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:ReplyTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/none</wsa:Address>
<wsa:ReferenceParameters>
<axis2:ServiceGroupId xmlns:axis2="http://ws.apache.org/namespaces/axis2">urn:uuid:99A029EBBC70DBEB221347349722532</axis2:ServiceGroupId>
</wsa:ReferenceParameters>
</wsa:ReplyTo>
<wsa:MessageID>urn:uuid:99A029EBBC70DBEB221347349722564</wsa:MessageID>
<wsa:Action>Perform some action</wsa:Action>
<wsa:RelatesTo>urn:uuid:63AD67826AA44DAE8C1347349721356</wsa:RelatesTo>
</soapenv:Header>

I would like to know how I could extract the Session GroupId from the above XML using Xpath.


Solution

  • You haven't specified a technology, so assuming that you haven't set up the equivalent of a .NET NameSpace manager or similar, you can use namespace agnostic Xpath as follows:

    /*[local-name()='Envelope']/*[local-name()='Header']
          /*[local-name()='ReplyTo']/*[local-name()='ReferenceParameters']
          /*[local-name()='ServiceGroupId']/text()
    

    Edit Updated for Java

    Without namespace aliases

    XPathFactory factory = XPathFactory.newInstance();
    XPath xpath = factory.newXPath();
    XPathExpression expression = xpath.compile("/*[local-name()='Envelope']/*[local-name()='Header']/*[local-name()='ReplyTo']/*[local-name()='ReferenceParameters']/*[local-name()='ServiceGroupId']/text()");
    System.out.println(expression.evaluate(myXml));
    

    With NamespaceContext

    NamespaceContext context = new NamespaceContextMap(
        "soapenv", "http://schemas.xmlsoap.org/soap/envelope/", 
        "wsa", "http://www.w3.org/2005/08/addressing",
        "axis2", "http://ws.apache.org/namespaces/axis2");
    XPathFactory factory = XPathFactory.newInstance();
    XPath xpath = factory.newXPath();
    xpath.setNamespaceContext(context);
    XPathExpression expression = xpath.compile("/soapenv:Envelope/soapenv:Header/wsa:ReplyTo/wsa:ReferenceParameters/axis2:Serv‌​iceGroupId/text()");
    System.out.println(expression.evaluate(myXml));
    

    local-name() gives the tag name of the element agnostic of its namespace. Also, the encoding in your above xml document doesn't look right.

    Edit

    Assuming that urn:uuid: is a constant, the following XPath will strip off the first 9 characters of the result (use with either of the above XPath). If urn:uuid isn't constant, then you'll need to tokenize / split etc, which is beyond my skills.

    substring(string(/*[local-name()='Envelope']/*[local-name()='Header']
                     /*[local-name()='ReplyTo']/*[local-name()='ReferenceParameters']
                     /*[local-name()='ServiceGroupId']/text()), 10)