Sunday, November 08, 2015

JSON to XML translation using Generic XML Format - Numeric XML Tags

Recently I came across a scenario where JSON to XML native builder format available in Oracle SOA Suite 12c produced Invalid XML with there Schema.

Every JSON Document can be represented by a generic XML where the JSON keys and values both can be represented as values of some XML tag. This would certainly avoid cases resulting in JSON to XML translation of Invalid XML when a json key is a numeric string and would result in numeric XML tag.

So to avoid those cases, I leveraged a java library to convert JSON to XML for which takes JSON input and gives generic XML output. Though this functionality can be achieved by various languages apart from java, the basic idea was to represent any JSON document with a generic XML structure. Here is an example.

{
"glossary": {
"4564": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"7001": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"4523": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}


OUTPUT

<json xmlns="http://json.to.xml.for.osb">

<object>

<field name="glossary">

<object>

<field name="4564">

<string value="example glossary"/>

</field>

<field name="GlossDiv">

<object>

<field name="title">

<string value="S"/>

</field>

<field name="GlossList">

<object>

<field name="GlossEntry">

<object>

<field name="ID">

<string value="SGML"/>

</field>

<field name="SortAs">

<string value="SGML"/>

</field>

<field name="GlossTerm">

<string value="Standard Generalized Markup Language"/>

</field>

<field name="7001">

<string value="SGML"/>

</field>

<field name="Abbrev">

<string value="ISO 8879:1986"/>

</field>

<field name="GlossDef">

<object>

<field name="para">

<string value="A meta-markup language, used to create markup languages such as DocBook."/>

</field>

<field name="4523">

<array>

<string value="GML"/>

<string value="XML"/>

</array>

</field>

</object>

</field>

<field name="GlossSee">

<string value="markup"/>

</field>

</object>

</field>

</object>

</field>

</object>

</field>

</object>

</field>

</object>

</json>


The schema for this generic format is as follows 

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://json.to.xml.for.osb"
           xmlns:tns="http://json.to.xml.for.osb" elementFormDefault="qualified">
  <xs:simpleType name="trueFalse">
    <xs:restriction base="xs:string">
      <xs:enumeration value="true"/>
      <xs:enumeration value="false"/>
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="number">
    <xs:attribute name="value" type="xs:double"/>
  </xs:complexType>
  <xs:complexType name="string">
    <xs:attribute name="value" type="xs:string"/>
  </xs:complexType>
  <xs:complexType name="boolean">
    <xs:attribute name="value" type="tns:trueFalse"/>
  </xs:complexType>
  <xs:complexType name="null"/>
  <xs:complexType name="object">
    <xs:sequence>
      <xs:element name="field" type="tns:field" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="array">
    <xs:sequence minOccurs="0" maxOccurs="unbounded">
      <xs:choice>
        <xs:element name="object" type="tns:object"/>
        <xs:element name="array" type="tns:array"/>
        <xs:element name="string" type="tns:string"/>
        <xs:element name="number" type="tns:number"/>
        <xs:element name="boolean" type="tns:boolean"/>
        <xs:element name="null" type="tns:null"/>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="field">
    <xs:choice>
      <xs:element name="object" type="tns:object"/>
      <xs:element name="array" type="tns:array"/>
      <xs:element name="string" type="tns:string"/>
      <xs:element name="number" type="tns:number"/>
      <xs:element name="boolean" type="tns:boolean"/>
      <xs:element name="null" type="tns:null"/>
    </xs:choice>
    <xs:attribute name="name" type="xs:string"/>
  </xs:complexType>
  <xs:element name="json">
    <xs:complexType>
      <xs:choice>
        <xs:element name="array" type="tns:array"/>
        <xs:element name="object" type="tns:object"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>


If we note here we see JSON can be represent by a JSON element where its child be a choice of an array or an object. An Object contains a field which can have a choice of its child being object, array, string, number, boolean or null and same happens with the array.

Thanks to Vladimir at https://bitbucket.org/vladimirdyuzhev for his concept.

No comments:

Post a Comment