6

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.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
Spaniard89
  • 2,359
  • 4
  • 34
  • 55

1 Answers1

7

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)
Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • @Kishorepandey The above should work with any parser - I meant that if you DID set up a Namespace manager, then you would be able to alias the namespaces and then access the element in a more 'friendly' manner, i.e. `/soapenv:Envelope/soapenv:Header/wsa:ReplyTo/wsa:ReferenceParameters/axis2:ServiceGroupId/text()` – StuartLC Sep 11 '12 at 09:32
  • @nonnb Can you please give me an example that would read my xml file and would perform the xpath expression and display the result? As I tried the expression you posted above and it seems to not be working. I would be glad if you could help me in this! – Spaniard89 Sep 12 '12 at 07:45
  • @nonnb Hi mate, I tried running your code and it works awesome. But the problem is I get the parsing output as urn:uuid:99A029EBBC70DBEB221347349722532 and i just want the phase after uuid: and I don't need urn:uuid: What can I do to resolve it? – Spaniard89 Sep 12 '12 at 09:02
  • @Kishorepandey Updated with a substring to scrape off the prefix, assuming that it is constant. – StuartLC Sep 12 '12 at 09:18
  • @nonnb How would i include this in the without namespace example of yours above in the xpath.compile()? and yes it is a constant. – Spaniard89 Sep 12 '12 at 09:22
  • @Kishorepandey - just replace the string in `xpath.compile("***paste here***")` – StuartLC Sep 12 '12 at 09:24