How to use Extract Variable to fetch from the following XML payload with namespaces

I want to fetch the value of the <baseResponseReport> tag from the following xml payload using Extract Variable but I am unable to do because of the name spaces in the xml paylaod.

Please  guide me how to use the ExtractVariables policy in the following payload for fetching the value of the <baseResponseReport> tag.

 

 
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <ProcessCommercialRequestResponse xmlns="http://tempuri.org/">
      <ProcessCommercialRequestResult xmlns:a="http://schemas.datacontract.org/2004/07/Nettpositive.BureauOne.BusinessObjects.Commercial" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <a:CommercialResponse>
          <a:ExistingReferenceNumber>0</a:ExistingReferenceNumber>
          <a:FailureMessage i:nil="true"/>
          <a:ListErrorCodes i:nil="true" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
          <a:ListErrorDetails i:nil="true" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
          <a:ReferenceNumber>16068829</a:ReferenceNumber>
          <a:ResponseStatus>Finished</a:ResponseStatus>
          <a:ResponseTime>2021-09-06T11:57:17.9429652+05:30</a:ResponseTime>
          <a:ResponseType i:nil="true"/>
          <a:ResponseXml>
            <?xml version="1.0" encoding="utf-16"?>
            <baseResponseReport>
              <reportHeaderRec>
                <daysPasswordToExpire />
                <reportOrderNumber>W-21717602</reportOrderNumber>
                <reportOrderDate>2021-09-06</reportOrderDate>
                <reportOrderedBy>BP03090001_CMMUATC2C10</reportOrderedBy>
                <memberDetails>ICICI</memberDetails>
                <applicationReferenceNumber>20000005350</applicationReferenceNumber>
                <inquiryPurpose>Unsecured business loan</inquiryPurpose>
              </reportHeaderRec>
              <enquiryInformationRec>
                <borrowerName>Sirohi Electronics</borrowerName>
                <pan>ABKPS0109F</pan>
                <cin />
                <tin />
                <crn />
                <addressCount>1</addressCount>
                <addressVec>
                  <address>
                    <addressLine>, RZE-4, Mahavir Enclave, Palam Dabri Road, South West Delhi, Near Sulabh International</addressLine>
                    <city>WESTDELHI</city>
                    <state>NEW DELHI</state>
                    <pinCode>110045</pinCode>
                  </address>
                </addressVec>
              </enquiryInformationRec>
            </baseResponseReport>
          </a:ResponseXml>
          <a:TimeOutStatus>Hit</a:TimeOutStatus>
          <a:bureauId>7</a:bureauId>
        </a:CommercialResponse>
      </ProcessCommercialRequestResult>
    </ProcessCommercialRequestResponse>
  </s:Body>
</s:Envelope>

 

Solved Solved
0 8 609
1 ACCEPTED SOLUTION

Himanshu

The example payload you provided is not "Well formed XML".  It has a stray XML declaration inserted in the middle of the document.  While it might be easy for humans like us to see that we can simply ignore that declaration, XML processing libraries are not so flexible and intuitive.  They will reject that document as not well-formed, and will not process it further. Apigee is built on such libraries. Therefore if you have THAT EXACT payload, then you cannot process it as XML, either with ExtractVariables or XSLT, or anything else that treats that payload as XML. It won't work. 

If I had to guess I would say that message payload has been constructed, by injecting the baseResponseReport element (and all its children) into an XML document template. The system that constructed the payload needs to be changed, so as not to introduce the XML declaration as well, when inserting that element. 

You _could_ configure Apigee to search the message payload and remove stray XML declarations thatr appear on any line after the first, but that feels like a fragile solution, and also fraught with future risk.  In a well-designed and reliable network, the system that generates the document should generate well-formed XML.  The right way to address the problem is at the source. 

AFTER you address that problem then you can use ExtractVariables or XSLT easily. 

BTW, you do not need to use XSLT to remove namespaces if all you want is to extract the nodeset.  ExtractVariables is namespace-aware.  The policy to do what you want would be something like this: 

 

<ExtractVariables name='EV-GetBaseReport'>
  <Source>response</Source>
  <XMLPayload>
    <Namespaces>
      <Namespace
          prefix='s'>http://schemas.xmlsoap.org/soap/envelope/</Namespace>
      <Namespace
          prefix='t'>http://tempuri.org/</Namespace>
      <Namespace
          prefix='a'>http://schemas.datacontract.org/2004/07/Nettpositive.BureauOne.BusinessObjects.Commercial</Namespace>
    </Namespaces>
    <Variable name='baseReport' type='nodeset'>
      <XPath>/s:Envelope/s:Body/t:ProcessCommercialRequestResponse/t:ProcessCommercialRequestResult/a:CommercialResponse/a:ResponseXml/t:baseResponseReport</XPath>
    </Variable>
  </XMLPayload>
</ExtractVariables>

 

I just tested this; it worked for me.

 

View solution in original post

8 REPLIES 8

What do you mean by fetching the value of baseResponseReport? It doesn't have a value, it's a complex type

 

 I have to fetch the entire content in the <baseResponseReport> tag

So then is it that you want to extract the value or is it you actually want to do a transformation?

What is your expected output?

@dknezic 

I want the entire content in between from this

<baseResponseReport>.......

</baseResponseReport>

 

 

 

 

You could use the extract variables with the nodeset type.

Or you could use an xslt policy to copy the baseResponseReport element - you would need to include the default namespace

 

However, because of the <?xml declaration on line 15, your payload isnt compatible with the policies

Yes , because of that line 15 only I am facing issues in using XSLT transformation for removing namespaces and then using the Extract Variable Policy.

How will I use the extract variable with type nodeset .

Can you please provide me the sample code for the same.

As mentioned, you cannot use either policy with your payload as it's not valid well-formed XML.

Himanshu

The example payload you provided is not "Well formed XML".  It has a stray XML declaration inserted in the middle of the document.  While it might be easy for humans like us to see that we can simply ignore that declaration, XML processing libraries are not so flexible and intuitive.  They will reject that document as not well-formed, and will not process it further. Apigee is built on such libraries. Therefore if you have THAT EXACT payload, then you cannot process it as XML, either with ExtractVariables or XSLT, or anything else that treats that payload as XML. It won't work. 

If I had to guess I would say that message payload has been constructed, by injecting the baseResponseReport element (and all its children) into an XML document template. The system that constructed the payload needs to be changed, so as not to introduce the XML declaration as well, when inserting that element. 

You _could_ configure Apigee to search the message payload and remove stray XML declarations thatr appear on any line after the first, but that feels like a fragile solution, and also fraught with future risk.  In a well-designed and reliable network, the system that generates the document should generate well-formed XML.  The right way to address the problem is at the source. 

AFTER you address that problem then you can use ExtractVariables or XSLT easily. 

BTW, you do not need to use XSLT to remove namespaces if all you want is to extract the nodeset.  ExtractVariables is namespace-aware.  The policy to do what you want would be something like this: 

 

<ExtractVariables name='EV-GetBaseReport'>
  <Source>response</Source>
  <XMLPayload>
    <Namespaces>
      <Namespace
          prefix='s'>http://schemas.xmlsoap.org/soap/envelope/</Namespace>
      <Namespace
          prefix='t'>http://tempuri.org/</Namespace>
      <Namespace
          prefix='a'>http://schemas.datacontract.org/2004/07/Nettpositive.BureauOne.BusinessObjects.Commercial</Namespace>
    </Namespaces>
    <Variable name='baseReport' type='nodeset'>
      <XPath>/s:Envelope/s:Body/t:ProcessCommercialRequestResponse/t:ProcessCommercialRequestResult/a:CommercialResponse/a:ResponseXml/t:baseResponseReport</XPath>
    </Variable>
  </XMLPayload>
</ExtractVariables>

 

I just tested this; it worked for me.