Using variables containing XML in XSLT policy

Not applicable

I tried the steps given here for a variable which is containing XML itself.

I want to insert this XML into another XML.

I tried as below,

1)Passed the variable as parameter into XSLT

OutTestXML contains <Name>Test1</Name>

 <Source>request</Source>
    <Parameters ignoreUnresolvedVariables="false">
        <Parameter name="TestXML" ref="OutTestXML"/>
    </Parameters>
    <ResourceURL>xsl://InsertXML.xsl</ResourceURL>
    <OutputVariable>XSLTOutput</OutputVariable>

2)In XSLT gave as below,

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml"/>
    <xsl:param name="TestXML" select="''"/>
    <xsl:template match="/">
        <TestDetails>
            <Id>1</Id>
            <xsl:copy-of  select="$TestXML"/>
        </TestDetails>
    </xsl:template>
</xsl:stylesheet>

3)I tried the same XSLT with even xsl:value-of

4)But in both 2nd and 3rd methods,its showing result with "ampersand lt" and "ampersand gt" replacing xml tags.

Result

(I have replaced the Ampersand symbol with word in the Result just to show how the result looks like ,because I was not able to paste the & as it was converting to < and > here.)

<?xml version="1.0" encoding="UTF-8"?><TestDetails><Id>1</Id>"ampersand lt"?xml version="1.0" encoding="UTF-8"?ampersand gt"ampersand lt"Name"ampersand gt"1"\ampersand lt"Name"ampersand gt"</TestDetails>

Please let me know how to avoid getting this "ampersand lt" and "ampersand gt" and how to get the correct XML tags <,> .

Also note that xml version is getting added in that XML variable in its previous step when I tried to do JSON to XML conversion.

So,I have to pick the <Name> node alone from the variable.Please let me know how to do this.

Solved Solved
0 4 2,391
1 ACCEPTED SOLUTION

I want to insert this XML into another XML.

I can think of 3 ways to accomplish this. with AssignMessage, with XSL passing the XML as a param, or you can use a custom policy in Edge.

1. XSL

The XSL policy runs an XSL transform. You can configure the policy to accept inbound parameters. One of those params might be a string, containing XML. You can then instantiate a document within the XSL and access the nodes in the document. This instantiation step with a saxon:parse() function is the part you were missing.

Configure the policy like this:

<XSL name='XSL-Mashup'>
  <DisplayName>XSL-Mashup</DisplayName>
  <Source>request</Source>
  <OutputVariable>output_content</OutputVariable>
  <ResourceURL>xsl://mashup.xsl</ResourceURL>
  <Parameters ignoreUnresolvedVariables='true'>
    <Parameter name='docstring' ref='variable-containing-xml-string'/>
  </Parameters>
</XSL>

Then, the XSL looks like this:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:saxon="http://saxon.sf.net/"
                exclude-result-prefixes="saxon fhir" >

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="docstring" select="''"/>
  <xsl:variable name="xmldoc" select="saxon:parse($docstring)"/>

  <xsl:template match="/">
    <Output>
      <xsl:copy-of select="$xmldoc/Root/element"/>
    </Output>
  </xsl:template>

</xsl:stylesheet>

2. AssignMessage

This works only if the source XML message, the thing into which you are inserting other content - is fixed, and can be coded into an AssignMessage policy in parts. It would look like this:

<AssignMessage name='AM-temp1'>
  <DisplayName>AM-temp1</DisplayName>
  <Description>assign a temporary message</Description>
  <AssignTo createNew='true' transport='http' type='request'>outputMessage</AssignTo>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <Set>
    <Payload contentType='application/xml'>
      <TestDetails>
        <Id>1</Id>
        {OutTestXML}
      </TestDetails>
    </Payload>
    <StatusCode>200</StatusCode>
    <ReasonPhrase>OK</ReasonPhrase>
  </Set>
</AssignMessage>

And the output XML will be available in a variable called "outputMessage.content"

3. Custom Policy

There is a custom policy that you can use in any Apigee Edge, available here. It allows you to insert XML nodes without fiddling with XSL. Here is an example of the use of this custom policy:

<JavaCallout name='InsertXmlNode-1'>
  <Properties>
    <Property name='source'>baseMessage</Property>
    <Property name='output-variable'>transformedContent</Property>
    <Property name='new-node-type'>element</Property>
    <Property name='new-node-text'>{OutTestXML}</Property>
    <Property name='xpath'>/TestDetails/Id</Property>
    <Property name='action'>append</Property>
  </Properties>
  <ClassName>com.dinochiesa.edgecallouts.EditXmlNode</ClassName>
  <ResourceURL>java://edge-custom-edit-xml-node.jar</ResourceURL>
</JavaCallout>

Assuming that OutTestXML contains <Name>Test1</Name> , and baseMessage contains <TestDetails><Id>1</Id></TestDetails> , then... the resulting message will look like this:

  <TestDetails>
    <Id>1</Id>
    <Name>Test1<Name>
  </TestDetails>

...and it will be placed into variable "transformedContent"

View solution in original post

4 REPLIES 4

I want to insert this XML into another XML.

I can think of 3 ways to accomplish this. with AssignMessage, with XSL passing the XML as a param, or you can use a custom policy in Edge.

1. XSL

The XSL policy runs an XSL transform. You can configure the policy to accept inbound parameters. One of those params might be a string, containing XML. You can then instantiate a document within the XSL and access the nodes in the document. This instantiation step with a saxon:parse() function is the part you were missing.

Configure the policy like this:

<XSL name='XSL-Mashup'>
  <DisplayName>XSL-Mashup</DisplayName>
  <Source>request</Source>
  <OutputVariable>output_content</OutputVariable>
  <ResourceURL>xsl://mashup.xsl</ResourceURL>
  <Parameters ignoreUnresolvedVariables='true'>
    <Parameter name='docstring' ref='variable-containing-xml-string'/>
  </Parameters>
</XSL>

Then, the XSL looks like this:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:saxon="http://saxon.sf.net/"
                exclude-result-prefixes="saxon fhir" >

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="docstring" select="''"/>
  <xsl:variable name="xmldoc" select="saxon:parse($docstring)"/>

  <xsl:template match="/">
    <Output>
      <xsl:copy-of select="$xmldoc/Root/element"/>
    </Output>
  </xsl:template>

</xsl:stylesheet>

2. AssignMessage

This works only if the source XML message, the thing into which you are inserting other content - is fixed, and can be coded into an AssignMessage policy in parts. It would look like this:

<AssignMessage name='AM-temp1'>
  <DisplayName>AM-temp1</DisplayName>
  <Description>assign a temporary message</Description>
  <AssignTo createNew='true' transport='http' type='request'>outputMessage</AssignTo>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <Set>
    <Payload contentType='application/xml'>
      <TestDetails>
        <Id>1</Id>
        {OutTestXML}
      </TestDetails>
    </Payload>
    <StatusCode>200</StatusCode>
    <ReasonPhrase>OK</ReasonPhrase>
  </Set>
</AssignMessage>

And the output XML will be available in a variable called "outputMessage.content"

3. Custom Policy

There is a custom policy that you can use in any Apigee Edge, available here. It allows you to insert XML nodes without fiddling with XSL. Here is an example of the use of this custom policy:

<JavaCallout name='InsertXmlNode-1'>
  <Properties>
    <Property name='source'>baseMessage</Property>
    <Property name='output-variable'>transformedContent</Property>
    <Property name='new-node-type'>element</Property>
    <Property name='new-node-text'>{OutTestXML}</Property>
    <Property name='xpath'>/TestDetails/Id</Property>
    <Property name='action'>append</Property>
  </Properties>
  <ClassName>com.dinochiesa.edgecallouts.EditXmlNode</ClassName>
  <ResourceURL>java://edge-custom-edit-xml-node.jar</ResourceURL>
</JavaCallout>

Assuming that OutTestXML contains <Name>Test1</Name> , and baseMessage contains <TestDetails><Id>1</Id></TestDetails> , then... the resulting message will look like this:

  <TestDetails>
    <Id>1</Id>
    <Name>Test1<Name>
  </TestDetails>

...and it will be placed into variable "transformedContent"

Thankyou @Dino

I tried with Javascript for building XML and that also worked.But Assign Message seems to be good approach.

Hi,

My requirement is similar to the issue you are addressing but, I need to add json request into one of the xml elements. I am able to add to the element but, the json request is having special characters &#xD; .

Please help me to resolve this.

Hi 

Can you ask a new question please?