Conversion of Web-Content’s XML to JSON

In some of the project, I have seen the requirements to convert web-content’s xml into JSON format to expose their web-content related API to 3rd party or perform some operation on data/manipulate data. I know you will be thinking that we can use Liferay's jsonws to fetch the web-content in JSON format but still you will get article content in xml format.

To achieve this, I have written 1 utility which will convert your web-content xml data into JSON format.

Web-Content XML Sample

<?xml version="1.0"?>
 <root available-locales="en_US" default-locale="en_US">
     <dynamic-element name="title" type="text" index-type="keyword" instance-id="pwwx">
         <dynamic-element name="description" instance-id="wnpv" type="text" index-type="keyword">
             <dynamic-content language-id="en_US"><![CDATA[Happy Birthday Sachin!!!]]></dynamic-content>
         </dynamic-element>
         <dynamic-element name="linkLabel" instance-id="scqc" type="text" index-type="keyword">
             <dynamic-element name="url" instance-id="lyre" type="text_box" index-type="text">
                 <dynamic-element name="linkTarget" instance-id="tnzj" type="list" index-type="keyword">
                     <dynamic-content language-id="en_US"><![CDATA[_self]]></dynamic-content>
                 </dynamic-element>
                 <dynamic-content language-id="en_US"><![CDATA[http://localhost:8080/web/guest/home]]></dynamic-content>
             </dynamic-element>
             <dynamic-content language-id="en_US"><![CDATA[Click here for your gift]]></dynamic-content>
         </dynamic-element>
         <dynamic-content language-id="en_US"><![CDATA[Birthday Wishes!!!]]></dynamic-content>
     </dynamic-element>
     <dynamic-element name="title" type="text" index-type="keyword" instance-id="tvfp">
         <dynamic-element name="description" instance-id="ghlm" type="text" index-type="keyword">
             <dynamic-content language-id="en_US"><![CDATA[Happy Anniversary Dear!!!]]></dynamic-content>
         </dynamic-element>
         <dynamic-element name="linkLabel" instance-id="rcvm" type="text" index-type="keyword">
             <dynamic-element name="url" instance-id="gieq" type="text_box" index-type="text">
                 <dynamic-element name="linkTarget" instance-id="cael" type="list" index-type="keyword">
                     <dynamic-content language-id="en_US"><![CDATA[_blank]]></dynamic-content>
                 </dynamic-element>
                 <dynamic-content language-id="en_US"><![CDATA[http://localhost:8080/web/guest/home]]></dynamic-content>
             </dynamic-element>
             <dynamic-content language-id="en_US"><![CDATA[1 Click here for your gift]]></dynamic-content>
         </dynamic-element>
         <dynamic-element name="linkLabel" type="text" index-type="keyword" instance-id="ltsx">
             <dynamic-element name="url" instance-id="hgci" type="text_box" index-type="text">
                 <dynamic-element name="linkTarget" instance-id="knzz" type="list" index-type="keyword">
                     <dynamic-content language-id="en_US"><![CDATA[_self]]></dynamic-content>
                 </dynamic-element>
                 <dynamic-content language-id="en_US"><![CDATA[http://localhost:8080/web/guest/home]]></dynamic-content>
             </dynamic-element>
             <dynamic-content language-id="en_US"><![CDATA[2 Click here for your gift]]></dynamic-content>
         </dynamic-element>
         <dynamic-content language-id="en_US"><![CDATA[Anniversary Wishes!!!]]></dynamic-content>
     </dynamic-element>
 </root>

 

Converted JSON Output

{
  "title": [
    {
      "linkLabel": {
        "linkLabel": "Click here for your gift",
        "url": {
          "linkTarget": "_self",
          "url": "http://localhost:8080/web/guest/home"
        }
      },
      "description": "Happy Birthday Sachin!!!",
      "title": "Birthday Wishes!!!"
    },
    {
      "linkLabel": [
        {
          "linkLabel": "1 Click here for your gift",
          "url": {
            "linkTarget": "_blank",
            "url": "http://localhost:8080/web/guest/home"
          }
        },
        {
          "linkLabel": "2 Click here for your gift",
          "url": {
            "linkTarget": "_self",
            "url": "http://localhost:8080/web/guest/home"
          }
        }
      ],
      "description": "Happy Anniversary Dear!!!",
      "title": "Anniversary Wishes!!!"
    }
  ]
}

 

Solution:

Please see the below code snippet to convert web-content XML to  JSON

Create the parseContent function

 public static JSONObject parseContent(String contentXML, String langId) {
        JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
        try {
            Document doc = SAXReaderUtil.read(contentXML);
            Node root = doc.getRootElement();
            // fetch the nodes of xml
            fetchNode(jsonObject, root, langId);
        } catch (DocumentException e) {
            jsonObject.put("Content", "There are no matching contents.");
        }
        return jsonObject;
}  

FetchNode method to fetch the nodes and convert into JSON

  private static void fetchNode(JSONObject jsonObject, Node prentNode, String langId) {
        List<Node> nodes = prentNode.selectNodes("dynamic-element");
        List<String> nodeList = new ArrayList<>();
        for (Node node : nodes) {
            NodeModel nodeModel = convertToNodeMap(node, langId);
            // Checking if same node is existing multiple times on same level, If yes then
            // we have to consider it as array.
            if (!nodeList.contains(nodeModel.getNodeName())) {
                nodeList.add(nodeModel.getNodeName());
                 List<Node> childNodeList = prentNode.selectNodes("dynamic-element[@name='" + nodeModel.getNodeName() + "']");
                // if we are getting more than 1 time same node name on same level, it means it
                // is repeatable field. So we need to treat it as array.
                if (childNodeList.size() > 1) {
                    JSONArray jsonArray = fetchChildNodeArray(childNodeList, langId);
                    jsonObject.put(nodeModel.getNodeName(), jsonArray);
                } else {
                    List<Node> childNodeWithSingleEntryList = node.selectNodes("dynamic-element");
                    // Checking if node has child
                    if (!childNodeWithSingleEntryList.isEmpty()) {
                        // if node has children
                        jsonObject.put(nodeModel.getNodeName(), fetchChildNodeObject(childNodeList, langId));
                    } else {
                        // if node hasn't children
                        jsonObject.put(nodeModel.getNodeName(), nodeModel.getNodeValue());
                    }
                }
            }
        }
    }

Fetch the child Node and convert into an Array

private static JSONArray fetchChildNodeArray(List<Node> childNodeList, String langId) {
        JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
        for (Node childNode : childNodeList) {
            JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
            NodeModel childNodeModel = convertToNodeMap(childNode, langId);
            jsonObject.put(childNodeModel.getNodeName(), childNodeModel.getNodeValue());
            jsonArray.put(jsonObject);
            // Fetch the children node
            fetchNode(jsonObject, childNode, langId);
        }
        return jsonArray;
    }    

Fetch the child node and convert into Json Object

private static JSONObject fetchChildNodeObject(List<Node> childNodeList, String langId) {
        JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
        for (Node childNode : childNodeList) {
            NodeModel childNodeModel = convertToNodeMap(childNode, langId);
            jsonObject.put(childNodeModel.getNodeName(), childNodeModel.getNodeValue());
            // Fetch the children node
            fetchNode(jsonObject, childNode, langId);
        }
        return jsonObject;
    }

Convert the node to nodeMap which contain the node name and node value

private static NodeModel convertToNodeMap(Node node, String langId) {
        Node nodeValue = node.selectSingleNode("dynamic-content[@language-id='" + langId + "']");
        String nodeKey = nodeValue.getParent().attribute("name").getStringValue();
        NodeModel nodeModel = new NodeModel();
        nodeModel.setNodeName(nodeKey);
        nodeModel.setNodeValue(nodeValue.getStringValue());
        return nodeModel;
    }

 

NodeModel .java

public class NodeModel {
    private String nodeName;
    private String nodeValue;

    public String getNodeName() {
        return nodeName;
    }

    public void setNodeName(String nodeName) {
        this.nodeName = nodeName;
    }

    public String getNodeValue() {
        return nodeValue;
    }

    public void setNodeValue(String nodeValue) {
        this.nodeValue = nodeValue;
    }
}