David Michael Gang
David Michael Gang

Reputation: 7309

convert xpath expression result to json

I want to convert a dom nodelist to a json array and send the result to a rest client:

Each node of the xml represents the following:

<A NAME="x" COUNT="y">
  <B KEY="z1" VALUE="z2"/>
  <B KEY="z3" VALUE="z4"/>
</A>

I want that i i will have for the output an array of objects where each object looks like the following:

{"NAME":"x", 
 "COUNT":"y", 
 "B": [ {"KEY": "z1,  VALUE:"z2"},
        {"KEY":"z3", VALUE:"z4"} ]
}

I tried to use the GSON library:

package com.a;


import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Test {
    private static final String XPATH = "/A/B";
    
    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
        File f = new File("C:/Users/abc/Desktop/a.xml");
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = null;
        builder = builderFactory.newDocumentBuilder();
        Document xmlDocument = builder.parse(f);
        XPath xPath =  XPathFactory.newInstance().newXPath();
        
        NodeList nodeList = (NodeList) xPath.compile(XPATH).evaluate(xmlDocument, XPathConstants.NODESET);
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        
        String jsonOutput = gson.toJson(nodeList);
        System.out.println(jsonOutput);
        
        
        
        
    }

}

but i am getting an error

Exception in thread "main" java.lang.StackOverflowError at

java.lang.StringBuffer.append(StringBuffer.java:224) at

java.io.StringWriter.write(StringWriter.java:84) at

com.google.gson.stream.JsonWriter.newline(JsonWriter.java:569) at

com.google.gson.stream.JsonWriter.beforeName(JsonWriter.java:586)

How can i fix this code?

As it is possible to convert a whole xml to json (Quickest way to convert XML to JSON in Java)

I assume that it is possible to convert dom nodes to json. What is wrong here?

Upvotes: 1

Views: 5691

Answers (1)

syllabus
syllabus

Reputation: 581

What's wrong ? you simply don't use the lib described on your link (Quickest way to convert XML to JSON in Java)

Gson will use java reflection to generate a json string from any object. From a DOM Document (or node), even when it doesn't end up with a StackOverflowError, it will not produce what you expect. here is the result for your XML:

{"fNamespacesEnabled":false,"mutationEvents":false,"actualEncoding":"UTF-8","standalone":false,"fDocumentURI":"...a.xml","changes":0,"allowGrammarAccess":false,"errorChecking":true,"ancestorChecking":true,"xmlVersionChanged":false,"documentNumber":0,"nodeCounter":0,"xml11Version":false,"flags":6}

Actually it seems that if any method has been invoked on a DOM Document (ex: getDocumentElement), the gson.toJson end up with a StackOverflowError.

As you can see in the link, a jar that will do the job can be found here: http://mvnrepository.com/artifact/org.json/json

It implies that you re-convert the nodes extracted with your XPath to string. You can do it with that:

private static String toString(Node n) throws TransformerFactoryConfigurationError, TransformerException {
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    StreamResult result = new StreamResult(new StringWriter());
    DOMSource source = new DOMSource(n);
    transformer.transform(source, result);
    return result.getWriter().toString();
}

With all that, all you have to do is to loop through your nodeList, convert it to string, and then convert it to json

for (int i = 0; i < nodeList.getLength(); i++) {
    Node n = nodeList.item(i);
    JSONObject xmlJSONObj = XML.toJSONObject(toString(n));
    String jsonPrettyPrintString = xmlJSONObj.toString(1);
    System.out.println(jsonPrettyPrintString);
}

Upvotes: 3

Related Questions