/* * Copyright (c) 2016 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.io.html.svg.mapping.json; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.stax.StAXResult; import javax.xml.transform.stax.StAXSource; import org.w3c.dom.Document; import org.xml.sax.SAXException; import de.odysseus.staxon.json.JsonXMLConfig; import de.odysseus.staxon.json.JsonXMLConfigBuilder; import de.odysseus.staxon.json.JsonXMLInputFactory; import de.odysseus.staxon.json.JsonXMLOutputFactory; import de.odysseus.staxon.json.stream.impl.JsonStreamFactoryImpl; import de.odysseus.staxon.xml.util.PrettyXMLStreamWriter; @SuppressWarnings("javadoc") public class JsonXML { public static void toJson(Reader xmlReader, Writer jsonWriter) throws XMLStreamException, FactoryConfigurationError, TransformerConfigurationException, TransformerException, TransformerFactoryConfigurationError { /* * If we want to insert JSON array boundaries for multiple elements, we * need to set the <code>autoArray</code> property. If our XML source * was decorated with <code><?xml-multiple?></code> processing * instructions, we'd set the <code>multiplePI</code> property instead. * With the <code>autoPrimitive</code> property set, element text gets * automatically converted to JSON primitives (number, boolean, null). */ JsonXMLConfig config = new JsonXMLConfigBuilder().namespaceDeclarations(true) .autoArray(true).autoPrimitive(true).prettyPrint(false).build(); /* * Create source (XML). */ XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(xmlReader); Source source = new StAXSource(reader); /* * Create result (JSON). */ // create stream factory manually due to class loading issues XMLStreamWriter writer = new JsonXMLOutputFactory(config, new JsonStreamFactoryImpl()) .createXMLStreamWriter(jsonWriter); Result result = new StAXResult(writer); /* * Copy source to result via "identity transform". */ TransformerFactory.newInstance().newTransformer().transform(source, result); } public static void toXML(Reader jsonReader, Writer xmlWriter) throws XMLStreamException, FactoryConfigurationError, TransformerConfigurationException, TransformerException, TransformerFactoryConfigurationError { /* * If the <code>multiplePI</code> property is set to <code>true</code>, * the StAXON reader will generate <code><xml-multiple></code> * processing instructions which would be copied to the XML output. * These can be used by StAXON when converting back to JSON to trigger * array starts. Set to <code>false</code> if you don't need to go back * to JSON. */ JsonXMLConfig config = new JsonXMLConfigBuilder().multiplePI(false).build(); /* * Create source (JSON). */ XMLStreamReader reader = new JsonXMLInputFactory(config, new JsonStreamFactoryImpl()) .createXMLStreamReader(jsonReader); Source source = new StAXSource(reader); /* * Create result (XML). */ XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(xmlWriter); Result result = new StAXResult(new PrettyXMLStreamWriter(writer)); // format // output /* * Copy source to result via "identity transform". */ TransformerFactory.newInstance().newTransformer().transform(source, result); } public static Document toDOM(Reader jsonReader) throws XMLStreamException, FactoryConfigurationError, TransformerConfigurationException, TransformerException, TransformerFactoryConfigurationError, ParserConfigurationException, IOException, SAXException { /* * Sadly not working like this - we get a NullPointerException because * during the transformation setXmlVersion is called with null */ // JsonXMLConfig config = new JsonXMLConfigBuilder().multiplePI(false).build(); // // Create source (JSON). // XMLStreamReader reader = new JsonXMLInputFactory(config, new JsonStreamFactoryImpl()).createXMLStreamReader(jsonReader); // Source source = new StAXSource(reader); // // Create result (DOM). // DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); // Document doc = builder.newDocument(); // Result result = new DOMResult(doc); // // Copy source to result via "identity transform". // TransformerFactory.newInstance().newTransformer().transform(source, result); // return doc; // XXX instead use the less tidy way via a string... StringWriter xmlWriter = new StringWriter(); try { toXML(jsonReader, xmlWriter); } finally { xmlWriter.close(); } // parse the document from the string String xmlString = xmlWriter.toString(); DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); try (ByteArrayInputStream in = new ByteArrayInputStream( xmlString.getBytes(StandardCharsets.UTF_8))) { return builder.parse(in); } } }