X-PATH to retrive the base64 encoded does not work with Extract Policy

This is the request

<s:Envelope xmlns:s="requirednamespace" xmlns:a="requiredanamespaceg">
  <s:Header>
    … Required header information goes here
  </s:Header>
  <s:Body xmlns:xsi="bodynamespacehere" xmlns:xsd="xsdnamespcacehere">
    <BusinessRequest xmlns="requiredNamespace">
      <Bus2Element> Someinfo</Bus2Element>
      <Process>SomeInfo1</ Process>
      <UID>abcdef6789-8bed-3456-b788-aA6cf</UID>
      <Time>YYYY/MM/DD</TimeStamp>
      <Other>SomeInfo2</Other>
      <Base64Payload>==Base64encodedinfo =</ Base64Payload>
      < Bus3Element >Aex888</ Bus3Element >
    </BusinessRequest >
  </s:Body>
</s:Envelope>

Above listed SOAP message simulaytes request.

We need to retrieve content of <Base64Payload> which has Base64 encoded content which will later be decoded to String (using Script)

The XPATH I have written in Extract Policy is

/s:Envelope/s:Body/BusinessRequest/Base64Payload/text() 

(After defining the Namespace)

This works fine with https://www.freeformatter.com/xpath-tester.html

This retrieves the full content of Base64encoded value present in this element and shows in the output to indicate XPATH is correct.

This is the same XPATH I am using in the Extract policy.

But when I try retrieving the information from Extract policy then neither it’s displayed in trace with Extract policy or even when I try extract this to script, it prints null because it fails retrieving information from Extract policy

var basePayload = context.getVariable("basepayload");

print(" base payload: " + basePayload);

Its prints null.

Even tried

/s:Envelope/s:Body/BusinessRequest/Bus3Element

which does not work with Extract Policy only.

Any suggestions?

Solved Solved
1 3 897
2 ACCEPTED SOLUTIONS

You have a namespace problem, at least. You may also have a problem with the XML being not valid, though maybe that is just from a cut-and-paste error.

I fixed those two things and ran a test and it worked for me.

Here's the payload I sent. Notice the soap namespace is valid, and I inserted a contrived namespace for BusinessRequest, and finally the TimeStamp element name is matched properly.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="requiredanamespaceg">
  <s:Header>
    ...Required header information goes here...
  </s:Header>
  <s:Body>
    <BusinessRequest xmlns="urn:E27C2EC3-20B8-4727-8CF3-8C821F9CAD6B">
      <Bus2Element>Someinfo</Bus2Element>
      <Process>SomeInfo1</Process>
      <UID>abcdef6789-8bed-3456-b788-aA6cf</UID>
      <TimeStamp>YYYY/MM/DD</TimeStamp>
      <Other>SomeInfo2</Other>
      <Base64Payload>==Base64encodedinfo=</Base64Payload>
      <Bus3Element>Aex888</Bus3Element>
    </BusinessRequest >
  </s:Body>
</s:Envelope>

And here is the ExtractVariables policy I used:

<ExtractVariables name='EV-1'>
  <Source>message</Source>
  <VariablePrefix>extracted</VariablePrefix>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <XMLPayload>
    <Namespaces>
      <Namespace prefix='s'>http://schemas.xmlsoap.org/soap/envelope/</Namespace>
      <Namespace prefix='u'>urn:E27C2EC3-20B8-4727-8CF3-8C821F9CAD6B</Namespace>
    </Namespaces>
    <Variable name='encoded_payload' type='string'>
      <XPath>/s:Envelope/s:Body/u:BusinessRequest/u:Base64Payload/text()</XPath>
    </Variable>
  </XMLPayload>
</ExtractVariables>

The result is stored in an environment variable: extracted.encoded_payload .

Now let's talk about why it works. You see there are two namespaces declared in the EV policy. One for soap, and one for the BusinessRequest.

The BusinessRequest element is defined within an XML namespace. The element name in the original payload doesn't use a prefix, so it's an implied namespace, but it's still a namespace. It may be somewhat confusing, but that is how XML namespaces work. When using xpath to refer to an element or nodeset within the document, you need to explicitly specify the namespaces.

A key point: the prefix used in the xpath is irrelevant. What is relevant is the namespace uri to which the prefix refers. In our case here, s refers to the soap namespace, which is http://schemas.xmlsoap.org/soap/envelope/ , and yes, the trailing slash is important. u refers to urn:E27C2EC3-20B8-4727-8CF3-8C821F9CAD6B , but that string can be anything, as long as it is the same in the policy configuration and in the original XML document. The prefix DOES NOT have to be the same across the xml document and the xpath, and in fact the XML document may not even use a prefix, as we have seen.

Regarding prefixes, I could just as easily have configured the policy like this:

<ExtractVariables name='EV-1'>
  <Source>message</Source>
  <VariablePrefix>extracted</VariablePrefix>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <XMLPayload>
    <Namespaces>
      <Namespace prefix='mysoapprefix'>http://schemas.xmlsoap.org/soap/envelope/</Namespace>
      <Namespace prefix='prefix2'>urn:E27C2EC3-20B8-4727-8CF3-8C821F9CAD6B</Namespace>
    </Namespaces>
    <Variable name='encoded_payload' type='string'>
      <XPath>/mysoapprefix:Envelope/mysoapprefix:Body/prefix2:BusinessRequest/prefix2:Base64Payload/text()</XPath>
    </Variable>
  </XMLPayload>
</ExtractVariables>

The prefix strings don't matter. They just point to the actual namespaces. I generally use short prefixes in XML documents only because it's easier on my eyes.

Also, one other note, completely irrelevant to the question here, but maybe worth pointing out. The document you passed in had a couple of namespaces that were not used. they used prefixes of xsi and xsd. Commonly those prefixes are used to refer to the namespaces for http://www.w3.org/2001/XMLSchema-instance and http://www.w3.org/2001/XMLSchema

See here: https://stackoverflow.com/a/9533085/48082

But, since the document has no use of either xsi or xsd, then those prefix declarations are irrelevant. So you can omit them. In other words, the following two documents are equivalent:

<root xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
      xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
  <a>foo</a>
</root>     
<root>
  <a>foo</a>
</root> 

View solution in original post

3 REPLIES 3

You have a namespace problem, at least. You may also have a problem with the XML being not valid, though maybe that is just from a cut-and-paste error.

I fixed those two things and ran a test and it worked for me.

Here's the payload I sent. Notice the soap namespace is valid, and I inserted a contrived namespace for BusinessRequest, and finally the TimeStamp element name is matched properly.

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="requiredanamespaceg">
  <s:Header>
    ...Required header information goes here...
  </s:Header>
  <s:Body>
    <BusinessRequest xmlns="urn:E27C2EC3-20B8-4727-8CF3-8C821F9CAD6B">
      <Bus2Element>Someinfo</Bus2Element>
      <Process>SomeInfo1</Process>
      <UID>abcdef6789-8bed-3456-b788-aA6cf</UID>
      <TimeStamp>YYYY/MM/DD</TimeStamp>
      <Other>SomeInfo2</Other>
      <Base64Payload>==Base64encodedinfo=</Base64Payload>
      <Bus3Element>Aex888</Bus3Element>
    </BusinessRequest >
  </s:Body>
</s:Envelope>

And here is the ExtractVariables policy I used:

<ExtractVariables name='EV-1'>
  <Source>message</Source>
  <VariablePrefix>extracted</VariablePrefix>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <XMLPayload>
    <Namespaces>
      <Namespace prefix='s'>http://schemas.xmlsoap.org/soap/envelope/</Namespace>
      <Namespace prefix='u'>urn:E27C2EC3-20B8-4727-8CF3-8C821F9CAD6B</Namespace>
    </Namespaces>
    <Variable name='encoded_payload' type='string'>
      <XPath>/s:Envelope/s:Body/u:BusinessRequest/u:Base64Payload/text()</XPath>
    </Variable>
  </XMLPayload>
</ExtractVariables>

The result is stored in an environment variable: extracted.encoded_payload .

Now let's talk about why it works. You see there are two namespaces declared in the EV policy. One for soap, and one for the BusinessRequest.

The BusinessRequest element is defined within an XML namespace. The element name in the original payload doesn't use a prefix, so it's an implied namespace, but it's still a namespace. It may be somewhat confusing, but that is how XML namespaces work. When using xpath to refer to an element or nodeset within the document, you need to explicitly specify the namespaces.

A key point: the prefix used in the xpath is irrelevant. What is relevant is the namespace uri to which the prefix refers. In our case here, s refers to the soap namespace, which is http://schemas.xmlsoap.org/soap/envelope/ , and yes, the trailing slash is important. u refers to urn:E27C2EC3-20B8-4727-8CF3-8C821F9CAD6B , but that string can be anything, as long as it is the same in the policy configuration and in the original XML document. The prefix DOES NOT have to be the same across the xml document and the xpath, and in fact the XML document may not even use a prefix, as we have seen.

Regarding prefixes, I could just as easily have configured the policy like this:

<ExtractVariables name='EV-1'>
  <Source>message</Source>
  <VariablePrefix>extracted</VariablePrefix>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <XMLPayload>
    <Namespaces>
      <Namespace prefix='mysoapprefix'>http://schemas.xmlsoap.org/soap/envelope/</Namespace>
      <Namespace prefix='prefix2'>urn:E27C2EC3-20B8-4727-8CF3-8C821F9CAD6B</Namespace>
    </Namespaces>
    <Variable name='encoded_payload' type='string'>
      <XPath>/mysoapprefix:Envelope/mysoapprefix:Body/prefix2:BusinessRequest/prefix2:Base64Payload/text()</XPath>
    </Variable>
  </XMLPayload>
</ExtractVariables>

The prefix strings don't matter. They just point to the actual namespaces. I generally use short prefixes in XML documents only because it's easier on my eyes.

Also, one other note, completely irrelevant to the question here, but maybe worth pointing out. The document you passed in had a couple of namespaces that were not used. they used prefixes of xsi and xsd. Commonly those prefixes are used to refer to the namespaces for http://www.w3.org/2001/XMLSchema-instance and http://www.w3.org/2001/XMLSchema

See here: https://stackoverflow.com/a/9533085/48082

But, since the document has no use of either xsi or xsd, then those prefix declarations are irrelevant. So you can omit them. In other words, the following two documents are equivalent:

<root xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
      xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
  <a>foo</a>
</root>     
<root>
  <a>foo</a>
</root> 

@Dino Thanks for catching that the implied namespace was missing in my XPath