Integration

Get Involved. Join the Conversation.

Topic

    Ewood
    Get child text from an xml element in a mappingAnswered
    Topic posted November 14, 2019 by Ewood Red Ribbon: 250+ Points, tagged Mapping 
    26 Views, 9 Comments
    Title:
    Get child text from an xml element in a mapping
    Content:

    Implementing the suggestion in this topic - Include mapped output as the value of another output..., I need to get the text content of an XML node returned from a REST Adapter invoke so I can encode it to Base64.  I tried just passing the node to the encodeBase64 function, but it encoded the text representation of the node itself (i.e. element name, attributes, etc...) rather than the text content of the node.  It seems that the way to do this is with a for-each and then get-content-as-string, but I am unable to add a for-each  as the input to the encode function.  I thought to assign the value to a variable, but I can't use an XSLT expression in variables.  It seems I could just map the node directly to the input of the function, but the node type is any, rather than string, even though it has a type of string in the sample file I used to define the response for the REST Adapter.  I'm sure there is a way to do this.  What am I missing?

    Best Comment

    Hemanth Lakkaraju

    The actual xml has multiple namespaces but your expression has single namespace for entire xpath and it is expected to fail.

    One way is to use local-name() like - $Response/*[local-name()='Envelope']/*[local-name()='Body']/....

    Comment

     

    • Hemanth Lakkaraju

      I tried just passing the node to the encodeBase64 function, but it encoded the text representation of the node itself (i.e. element name, attributes, etc...) rather than the text content of the node.

      A hint of xml and what you passed, your expectation and actual result will help us understand your problem and provide solution. I did not fully get the next part of what you mentioned on what are you trying here. Can you explain the issue you have with an example?

    • Ewood

      The XML returned from the service looks like:

      <soapenv:Envelope xmlns="http://xmlns.oracle.com/cloud/adapter/nxsd/surrogate/response/SaveSalesOrder/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://xmlns.oracle.com/cloud/adapter/nxsd/surrogate/response/SaveSalesOrder/" xmlns:wss="http://www.adonix.com/WSS" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
         <soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <wss:saveResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
               <saveReturn xsi:type="wss:CAdxResultXml">
                  <messages>
                     <type>2</type>
                     <message>This reference already exists for this customer!</message>
                  </messages>
                  <messages>
                     <type>2</type>
                     <message>Authorized credit level reached</message>
                  </messages>
                  <messages>
                     <type>2</type>
                     <message>Authorized credit level reached        7000000 USD</message>
                  </messages>
                  <resultXml xsi:type="xsd:string">
                     {"SOH0_1":{"SALFCY":"015","SOHNUM":"SO004341"}}

      </resultXml>
                  <status xsi:type="xsd:int">1</status>
               </saveReturn>
            </wss:saveResponse>
         </soapenv:Body>
      </soapenv:Envelope>

      This is the same XML snippet that I used to configure the REST Adapter response.  My expectation is that I could map to a stage file write using the opaque schema xsd with 

      <xsl:value-of select = 'oraext:encodeBase64($SaveSalesOrder/nsmpr9:executeResponse/nsmpr3:Envelope/nsmpr3:Body/nsmpr3:saveResponse/nsmpr3:saveReturn/nsmpr3:resultXml)'>

      But this appears to base64Encode the instance id, e.g.

      oracle.xml.parser.v2.XMLNodeList@54c016a1

      I also tried

      <xsl:value-of select='oraext:encodeBase64(oraext:get-content-as-string($SaveSalesOrder/nsmpr2:executeResponse/nsmpr5:Envelope/nsmpr5:Body/nsmpr5:saveResponse/nsmpr5:saveReturn/nsmpr5:resultXml))' />

      but it encoded the string representation of the entire XML element, e.g. 

      <ns1:resultXml type="type562" xmlns:ns1="http://xmlns.oracle.com/cloud/adapter/nxsd/surrogate/response/SaveSalesOrder/">This is a test</ns1:resultXml>

      I just want it to encode the text content of the resultXml node, in my example, the JSON string

       {"SOH0_1":{"SALFCY":"015","SOHNUM":"SO004341"}}

    • Hemanth Lakkaraju

      The rest sample xml configuration supports only no namespace or single namespace but the sample you show has multiple namespaces, not sure how would it work!

      Regarding the text content, can you try using xsl:copy-of instead of xsl:value-of like below

      <xsl:copy-of select='oraext:encodeBase64(oraext:get-content-as-string($SaveSalesOrder/nsmpr2:executeResponse/nsmpr5:Envelope/nsmpr5:Body/nsmpr5:saveResponse/nsmpr5:saveReturn/nsmpr5:resultXml))' />

      • Ewood

        I removed namespaces in the sample I used.  I don't understand how copy-of will address the issue which is that the mapped value of the node is not the node contents, but rather some representation of the node itself.  I'll get the XSD and post it here so you can see that.  Maybe the problem is how the schema was created from my sample.

        • Ewood

          I modified my sample to remove the CDATA thinking that might cause the problem.  It did change the type of resultXml to string, but I am still not able to access the string value.  If I try to log the value, i get an error "faultName: {{http://schemas.xmlsoap.org/ws/2003/03/business-process/}selectionFailure} messageType: {{http://schemas.oracle.com/bpel/extension}RuntimeFaultMessage} parts: {{ summary=<summary>The &lt;from> value is invalid. Xpath expression associated with &lt;from> in copy assign activity is invalid. There is an user error that results in missing element value(s) in the xpath query. Please review the payload and modeling to ensure that all elements defined in the &lt;from> xpath query have valid non-null values . </summary> ,activity=<activity>540008-BpAss38-BpSeq33.60-3</activity> ,query=<query>$messagecontext_161.parameters/../nsmpr9:executeResponse/nsmpr3:Envelope/nsmpr3:Body/nsmpr3:saveResponse/nsmpr3:saveReturn/nsmpr3:resultXml</query> ,lineNumber=<lineNumber>1618</lineNumber>}"  If I don't log the value, it fails the condition which checks for resultXml to not be nil.  I have tried making the condition count(resultXml > 0) and that fails as well.

          • Hemanth Lakkaraju

            The actual xml has multiple namespaces but your expression has single namespace for entire xpath and it is expected to fail.

            One way is to use local-name() like - $Response/*[local-name()='Envelope']/*[local-name()='Body']/....

            • Ewood

              That makes sense.  Given that you cannot have multiple namespaces in an XML sample and I can't change the output to not have namespaces, this would seem to be the only way to make this work?

              • Hemanth Lakkaraju

                Hopefully Yes! And there is one other way you can try -

                Get the REST response in raw format - This will be written to a stage file.

                Create multiple schemas per namespaces, archive them and use it in stage read and see if you are able to read the response.

                • Ewood

                  The XPath worked and was reasonably straightforward, so I chose that one.  Thanks.