Converting a variable into JSON to XML in APIGEE

Not applicable

I want to convert a JSON header variable into XML variable.And then later insert that XML variable into another XML message sent as request to a service provider.

But I am facing issues while doing so.

The approach I am trying is,

1)I am saving a header variable which is in json format into some other variable.

2)And referring that variable in JSON to XML conversion.

<Source>In_JSON_Var</Source> <OutputVariable>Out_XML_Var</OutputVariable>

Here XML is getting appended with XML version tag.

<?xml version="1.0" encoding="UTF-8"?><Fruit>Orange</Fruit>

3)I am inserting an XSLT after this to remove the root XML element.But XSLT fails with below reason

"java.lang.String cannot be cast to com.apigee.flow.message.Message"

   <Source>Out_XML_Var</Source>
    <ResourceURL>xsl://RemoteXMLRoot.xsl</ResourceURL>
    <Parameters ignoreUnresolvedVariables="true"/>
    <OutputVariable>Out_XML_Var_NoRoot</OutputVariable>

Please help me with anyother better approach.

Solved Solved
0 6 650
1 ACCEPTED SOLUTION

Yes, the source of the problem here is that the XSL Policy in Apigee Edge always takes a Message as input. A string is not suitable. Your Out_XML_Var is a string, not a message.

You can use an AssignMessage policy to wrap a message around a string, like this:

<AssignMessage name='AM-temp'>
  <DisplayName>AM-temp</DisplayName>
  <Description>wrap a message around a string</Description>
  <AssignTo createNew='true' transport='http' type='request'>wrapped</AssignTo>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <Set>
    <Payload contentType='application/xml'
             variablePrefix='%' variableSuffix='#'>%Out_XML_Var#</Payload>
    <StatusCode>200</StatusCode>
    <ReasonPhrase>OK</ReasonPhrase>
  </Set>
</AssignMessage>

...and this will then be suitable for use as input to an XSL policy.

You can then "remove" the Root element. But keep in mind, in the general case, you need a root element. What I mean is, this json:

{
  "name1" : "Value1",
  "name2" : "Value2"
}

...when passed through the XMLToJSON policy, gets converted into this XML:

<Root>
  <name1>Value1</name1>
  <name2>Value2</name2>
</Root>

But simply "removing" the root produces a non-well-formed XML document. In other words, this is not a well-formed document:

  <name1>Value1</name1>
  <name2>Value2</name2>

But in the case that your JSON has a single element, then "removing" the root element will result in a valid XML document.

One more suggestion: you're editing bits of XML. This custom policy may be helpful:

https://github.com/DinoChiesa/ApigeeEdge-Java-Add-Xml-Node

It can remove nodes in an XML doc (including nodes that are elements), insert nodes (including elements), or replace nodes (including elements) . And there's no need to write XSLT, though you do have to write an XPath!

View solution in original post

6 REPLIES 6

Hello RK4,

You might have to extract the JSON object from the header and assign it to some message object (by using AssignMessage policy):

<AssignMessage async="false" continueOnError="false" enabled="true" name="AssignJSONObjectInMessageObject">
    <Set>    
        <Payload contentType="application/json">{In_JSON_Var}</Payload>      
    </Set>
    <AssignTo createNew="true" transport="http" type="request">sample_request<AssignTo>
</AssignMessage>

And, then refer request object in JSON to XML conversion.

<Source>sample_request.content</Source><OutputVariable>Out_XML_Var</OutputVariable>

Also, at the time of JSON to XML conversion the content-type header should have value "application/json".

Thanks

Anshul Agarwal

XML2JSON or JSON2XML works only on variables of type 'Message', so you need a Message variable - to create a message variable - you can use AssignMessage policy,

Now you can use in your JSON2XML policy

<JSONToXML name="jsontoxml">
    <Source>json_message</Source>
    <OutputVariable>xml_response</OutputVariable>
</JSONToXML>

'xml_response.content' will have the transformed XML

Right, the source is just 'sample_request'

Yes, the source of the problem here is that the XSL Policy in Apigee Edge always takes a Message as input. A string is not suitable. Your Out_XML_Var is a string, not a message.

You can use an AssignMessage policy to wrap a message around a string, like this:

<AssignMessage name='AM-temp'>
  <DisplayName>AM-temp</DisplayName>
  <Description>wrap a message around a string</Description>
  <AssignTo createNew='true' transport='http' type='request'>wrapped</AssignTo>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <Set>
    <Payload contentType='application/xml'
             variablePrefix='%' variableSuffix='#'>%Out_XML_Var#</Payload>
    <StatusCode>200</StatusCode>
    <ReasonPhrase>OK</ReasonPhrase>
  </Set>
</AssignMessage>

...and this will then be suitable for use as input to an XSL policy.

You can then "remove" the Root element. But keep in mind, in the general case, you need a root element. What I mean is, this json:

{
  "name1" : "Value1",
  "name2" : "Value2"
}

...when passed through the XMLToJSON policy, gets converted into this XML:

<Root>
  <name1>Value1</name1>
  <name2>Value2</name2>
</Root>

But simply "removing" the root produces a non-well-formed XML document. In other words, this is not a well-formed document:

  <name1>Value1</name1>
  <name2>Value2</name2>

But in the case that your JSON has a single element, then "removing" the root element will result in a valid XML document.

One more suggestion: you're editing bits of XML. This custom policy may be helpful:

https://github.com/DinoChiesa/ApigeeEdge-Java-Add-Xml-Node

It can remove nodes in an XML doc (including nodes that are elements), insert nodes (including elements), or replace nodes (including elements) . And there's no need to write XSLT, though you do have to write an XPath!

Thankyou @Dino

So,could you please tell me how I can include the result(below) in another xml which is already existing?

 <name1>Value1</name1>
  <name2>Value2</name2>

For Eg:

<Test>
<Result>
    <name1>Value1</name1>
    <name2>Value2</name2>
</Result>
</Test>

Thankyou @Dino

This helps..I will try out.