Skip to main content

For some reason in one of our processes it was decided that an XML is needed that contains partly json data (I know how this sounds :( ).

I'm struggling to get the json data correctly parsed (or the XML correctly formatted).

 

The json data is generated via json templater and looks like this:

{
    "editOptions": {
        "cascadeEditOptions": {
            "cascadeStrategy": {
                "type": "NoCascadeStrategy",
                "enabledTypes":  ]
            }
        },
        "userProvidedIds": true
    }
}

The XML structure should be like this:

<data>
<metadata>
<projectName>SomeProject</projectName>
</metadata>
<action>
<Modification operationId="test_operation_id_1" Id="1" requestBody='
{
    "editOptions": {
        "cascadeEditOptions": {
            "cascadeStrategy": {
                "type": "NoCascadeStrategy",
                "enabledTypes":  ]
            }
        },
        "userProvidedIds": true
    }
}
  '/>
</action>
</data>

The problem is when I provide the json data into the XML templater.

It gives an error on an invalid expression invalid expression: syntax error, unexpected character "{"

 

So I've tried the following as well:

Create the XML structure via an attribute manager and use it in the xml templater via fme-get-xml-attribute, but then it parses the json terrible:

<data-exchange>
<metadata>
<modelName>TTOM</modelName>
<modelVersion>4_0</modelVersion>
<projectName>GEN_AreaImprovement_Tests</projectName>
</metadata>
<transaction sequenceId="1">
        <applyModifications operationId="test_operation_id_1" entityId="153758d6-fbae-4943-9efa-89df952c7126" requestBody="{&quot;editOptions&quot;: {     &quot;cascadeEditOptions&quot;: {       &quot;cascadeStrategy&quot;: {         &quot;type&quot;: &quot;NoCascadeStrategy&quot;,         &quot;enabledTypes&quot;: e]       }     },     &quot;userProvidedIds&quot;: true   }}"/>
    </transaction>
</data-exchange>

When providing it as regular attribute, it has an issue with the XML < /> things:

<data-exchange>
<metadata>
<modelName>TTOM</modelName>
<modelVersion>4_0</modelVersion>
<projectName>GEN_AreaImprovement_Tests</projectName>
</metadata>
<transaction sequenceId="1">
        &lt;applyModifications operationId="test_operation_id_1" entityId="153758d6-fbae-4943-9efa-89df952c7126" requestBody='{"editOptions": {
    "cascadeEditOptions": {
      "cascadeStrategy": {
        "type": "NoCascadeStrategy",
        "enabledTypes": e]
      }
    },
    "userProvidedIds": true
  }}'/&gt;
    </transaction>
</data-exchange>

Probably I can replace &lt; and &gt; with their correct signs, but it's not a graceful way to work.

Is there another way go generate this in a more graceful way or did I overlook a thing?

Does the JSON-in-XML have to be readable for anything other than FME? If not, you could use an AttributeCompressor to simply encrypt the value and avoid all those {}'s (and then an AttributeDecompressor to decrypt it again.

 

But seriously, who comes up with this? I would love to hear the reasoning why this would be a good idea...


If you really want to force it, you can try telling the XMLTemplater that you're inserting an attribute that's (supposedly) valid XML:

fme:get-xml-attribute("my_json_doc")

This should prevent the automatic encoding of XML reserved characters. That might or might not work.

Alternatively, I see two options here:

  1. Send the JSON document through an TextEncoder set to XML encoding before using it in the XMLTemplater (it'll look like the example you don't like above), or
  2. Put the JSON document in a CDATA section in the XML, https://www.w3.org/TR/REC-xml/#sec-cdata-sect

If you really want to force it, you can try telling the XMLTemplater that you're inserting an attribute that's (supposedly) valid XML:

fme:get-xml-attribute("my_json_doc")

This should prevent the automatic encoding of XML reserved characters. That might or might not work.

Alternatively, I see two options here:

  1. Send the JSON document through an TextEncoder set to XML encoding before using it in the XMLTemplater (it'll look like the example you don't like above), or
  2. Put the JSON document in a CDATA section in the XML, https://www.w3.org/TR/REC-xml/#sec-cdata-sect

Hi David, I tried that already but it gives a bad json formatting:

    <data-exchange>
     <metadata>
     <modelName>TTOM</modelName>
     <modelVersion>4_0</modelVersion>
     <projectName>GEN_AreaImprovement_Tests</projectName>
     </metadata>
     <transaction sequenceId="1">
            <applyModifications operationId="test_operation_id_1" entityId="153758d6-fbae-4943-9efa-89df952c7126" requestBody="{&quot;editOptions&quot;: {     &quot;cascadeEditOptions&quot;: {       &quot;cascadeStrategy&quot;: {         &quot;type&quot;: &quot;NoCascadeStrategy&quot;,         &quot;enabledTypes&quot;: u]       }     },     &quot;userProvidedIds&quot;: true   }}"/>
        </transaction>
    </data-exchange>

 


Does the JSON-in-XML have to be readable for anything other than FME? If not, you could use an AttributeCompressor to simply encrypt the value and avoid all those {}'s (and then an AttributeDecompressor to decrypt it again.

 

But seriously, who comes up with this? I would love to hear the reasoning why this would be a good idea...

It needs to be readable for another tool that only reads XML, but for an improvement they implemented this structure. For time constraints they don't want any logic besides that 😞 normally they should iso using json, have it as correct XML, but that's a path they don't want to take


Hi David, I tried that already but it gives a bad json formatting:

    <data-exchange>
     <metadata>
     <modelName>TTOM</modelName>
     <modelVersion>4_0</modelVersion>
     <projectName>GEN_AreaImprovement_Tests</projectName>
     </metadata>
     <transaction sequenceId="1">
            <applyModifications operationId="test_operation_id_1" entityId="153758d6-fbae-4943-9efa-89df952c7126" requestBody="{&quot;editOptions&quot;: {     &quot;cascadeEditOptions&quot;: {       &quot;cascadeStrategy&quot;: {         &quot;type&quot;: &quot;NoCascadeStrategy&quot;,         &quot;enabledTypes&quot;: &]       }     },     &quot;userProvidedIds&quot;: true   }}"/>
        </transaction>
    </data-exchange>

 

I suspect you need to look into using a CDATA section for this somewhat particular requirement.


Hi David, I tried that already but it gives a bad json formatting:

    <data-exchange>
     <metadata>
     <modelName>TTOM</modelName>
     <modelVersion>4_0</modelVersion>
     <projectName>GEN_AreaImprovement_Tests</projectName>
     </metadata>
     <transaction sequenceId="1">
            <applyModifications operationId="test_operation_id_1" entityId="153758d6-fbae-4943-9efa-89df952c7126" requestBody="{&quot;editOptions&quot;: {     &quot;cascadeEditOptions&quot;: {       &quot;cascadeStrategy&quot;: {         &quot;type&quot;: &quot;NoCascadeStrategy&quot;,         &quot;enabledTypes&quot;: &]       }     },     &quot;userProvidedIds&quot;: true   }}"/>
        </transaction>
    </data-exchange>

 

Tried an example, but seems like the templater doesn't parse it correctly.

Example: (taken from here: https://www.educba.com/xml-cdata/ )

<?xml version="1.0" encoding="UTF-8"?>
<SoftwareEngineer>
<empl id="01">
<name>
<projectname> Man-router</projectname>
<Workingdomain> machine learning</Workingdomain>
</name>
<Enddate>
<entities><!jCDATAm
This is the local project with the fibre optics.
All the statistical manipulation is performed. Example. '"&<> and submission date 12/12/2020
]]></entities>
</Enddate>
</empl>
</SoftwareEngineer>
<?xml version="1.0" encoding="UTF-8"?>
<SoftwareEngineer>
<empl id="01">
<name>
<projectname> Man-router</projectname>
<Workingdomain> machine learning</Workingdomain>
</name>
<Enddate>
<entities><!eCDATA 
This is the local project with the fibre optics.
All the statistical manipulation is performed. Example. '"&<> and submission date 12/12/2020
]]></entities>
</Enddate>
</empl>
</SoftwareEngineer>

output:

<?xml version="1.0" encoding="UTF-8"?>
<SoftwareEngineer>
<empl id="01">
<name>
<projectname> Man-router</projectname>
<Workingdomain> machine learning</Workingdomain>
</name>
<Enddate>
<entities>This is the local project with the fibre optics.All the statistical manipulation is performed. Example. '"&amp;&lt;&gt; and submission date 12/12/2020</entities>
</Enddate>
</empl>
</SoftwareEngineer>

 


Hi David, I tried that already but it gives a bad json formatting:

    <data-exchange>
     <metadata>
     <modelName>TTOM</modelName>
     <modelVersion>4_0</modelVersion>
     <projectName>GEN_AreaImprovement_Tests</projectName>
     </metadata>
     <transaction sequenceId="1">
            <applyModifications operationId="test_operation_id_1" entityId="153758d6-fbae-4943-9efa-89df952c7126" requestBody="{&quot;editOptions&quot;: {     &quot;cascadeEditOptions&quot;: {       &quot;cascadeStrategy&quot;: {         &quot;type&quot;: &quot;NoCascadeStrategy&quot;,         &quot;enabledTypes&quot;: &]       }     },     &quot;userProvidedIds&quot;: true   }}"/>
        </transaction>
    </data-exchange>

 

You don't have to use the XMLTemplater for this, XML is just text after all.


Reply