2011-02-25 45 views
19

Tengo que convertir el formato de archivo docx (que está en formato openXML) en formato JSON. Necesito algunas pautas para hacerlo. Gracias por adelantado.Convertir XML a formato JSON

Respuesta

10

No hay una asignación directa entre XML y JSON; XML lleva consigo información de tipo (cada elemento tiene un nombre), así como el espacio de nombres. Por lo tanto, a menos que cada objeto JSON tenga incrustada información de tipo, la conversión será con pérdida.

Pero eso no necesariamente importa. Lo que importa es que el consumidor de JSON conozca el contrato de datos. Por ejemplo, dado este XML:

<books> 
    <book author="Jimbo Jones" title="Bar Baz"> 
    <summary>Foo</summary> 
    </book> 
    <book title="Don't Care" author="Fake Person"> 
    <summary>Dummy Data</summary> 
    </book> 
</books> 

podría convertir a esto:

{ 
    "books": [ 
     { "author": "Jimbo Jones", "title": "Bar Baz", "summary": "Foo" }, 
     { "author": "Fake Person", "title": "Don't Care", "summary": "Dummy Data" }, 
    ] 
} 

y el consumidor no tendría que saber que cada objeto de la colección books era un objeto book.

Editar:

Si usted tiene un esquema XML para el XML y está utilizando .NET, puede generar clases del esquema utilizando xsd.exe. Luego, podría analizar el código fuente XML en objetos de estas clases, luego usar un DataContractJsonSerializer para serializar las clases como JSON.

Si no tiene un esquema, será difícil moverse manualmente definiendo manualmente su formato JSON.

+0

Cómo hacer esta conversión ... El xml de entrada es algo complejo, por lo que la conversión debe ser fácil y tener un buen rendimiento ... ¿Qué idioma se prefiere para hacer esto? – vignesh

+2

esto es exactamente lo que [XML-ValidatorBuddy] (http://www.xml-tools.com/ValidatorBuddy.htm) puede hacer por usted – Fluffi1974

+0

Jacob, Estoy usando su ejemplo de código y he transformado con éxito un archivo XML a un objeto JSON. Sin embargo, mi archivo XML representa un elemento raíz () y un elemento de agrupación (), donde están anidados todos los demás elementos . El elemento es lo que busco, y puede contener cualquier variación de atributos, elementos secundarios y elementos secundarios, etc. ¿Hay alguna manera de que devuelva un ArrayList de cada elemento ? En otras palabras, ¿puedo especificar algo similar a XPath y todavía usar SAX? P.S: No puedo usar DOM debido a los límites de tamaño. –

13

Puede echar un vistazo a la biblioteca de Java Json-lib, que proporciona la conversión XML-to-JSON.

String xml = "<hello><test>1.2</test><test2>123</test2></hello>"; 
XMLSerializer xmlSerializer = new XMLSerializer(); 
JSON json = xmlSerializer.read(xml); 

Si necesita la etiqueta raíz demasiado, basta con añadir una etiqueta ficticia exterior:

String xml = "<hello><test>1.2</test><test2>123</test2></hello>"; 
XMLSerializer xmlSerializer = new XMLSerializer(); 
JSON json = xmlSerializer.read("<x>" + xml + "</x>"); 
+5

Sería bueno, pero el resultado es '{" test ":" 1.2 "," test2 ":" 123 "}' y no '{" hello ": {" test ":" 1.2 "," test2 ": "123"}} ', es decir, solo imprime las hojas (se pierde la etiqueta' '). Lo mismo ocurre si agregamos un nodo intermedio (hijo de '' y padre de ''): se ignorará. ¿Es una cuestión de configuración? – bluish

4

Si tiene que ser capaz de manipular el código XML antes de que se convierte en JSON, o quiere fina gran control de su representación, vaya con XStream. Es muy fácil convertir entre: xml-to-object, json-to-object, object-to-xml y object-to-json. He aquí un ejemplo de XStream's docs:

XML:

<person> 
    <firstname>Joe</firstname> 
    <lastname>Walnes</lastname> 
    <phone> 
    <code>123</code> 
    <number>1234-456</number> 
    </phone> 
    <fax> 
    <code>123</code> 
    <number>9999-999</number> 
    </fax> 
</person> 

POJO (DTO):

public class Person { 
    private String firstname; 
    private String lastname; 
    private PhoneNumber phone; 
    private PhoneNumber fax; 
    // ... constructors and methods 
} 

Convertir de XML a POJO:

String xml = "<person>...</person>"; 
XStream xstream = new XStream(); 
Person person = (Person)xstream.fromXML(xml); 

Y después de POJO a JSON :

XStream xstream = new XStream(new JettisonMappedXmlDriver()); 
String json = xstream.toXML(person); 

Nota: aunque el método dice toXML() XStream producirá JSON, ya que se utiliza el controlador Jettison.

4

La conversión de archivos docx completos en JSON no parece una buena idea, porque docx es un formato XML centrado en documentos y JSON es un formato centrado en datos. XML en general está diseñado para ser tanto centrado en documentos como en datos. Aunque es técnicamente posible convertir XML centrado en documentos en JSON, el manejo de los datos generados puede ser demasiado complejo. Intenta enfocarte en los datos realmente necesarios y convierte solo esa parte.

6

El XML class en el espacio de nombres org.json le proporciona esta funcionalidad.

usted tiene que llamar la estática toJSONObject method

convierte una cadena XML bien formado (pero no necesariamente válida) en un JSONObject. Parte de la información puede perderse en esta transformación porque JSON es un formato de datos y XML es un formato de documento. XML usa elementos, atributos y texto de contenido, mientras que JSON usa colecciones desordenadas de pares de nombre/valor y matrices de valores. A JSON no le gusta distinguir entre elementos y atributos. Las secuencias de elementos similares se representan como JSONArrays. El texto del contenido puede colocarse en un miembro de "contenido". Comentarios, prologs, DTDs y < [[]]> ​​son ignorados.

+0

Este es definitivamente el enfoque más simple y limpio. Gracias. –

+0

Estaba tratando de usar esto, pero crea Node/text based xmls. cómo crear xml basado en atributos? Ejemplo: si mis datos JSON son: {Order: {OrderLine: {ItemID: "1234"}}, OrderNo: "4567"} Reqrd O/P: que está basado en un nodo. Estoy buscando conversiones xml de atributos base. Por favor, avíseme si tiene alguna sugerencia. – Aki

6

Si no está satisfecho con las diversas implementaciones, intente rodar las suyas. Aquí hay un código que escribí esta tarde para que comiences. Funciona con net.sf.json y Apache Commons-lang:

static public JSONObject readToJSON(InputStream stream) throws Exception { 
    SAXParserFactory factory = SAXParserFactory.newInstance(); 
    factory.setNamespaceAware(true); 
    SAXParser parser = factory.newSAXParser(); 
    SAXJsonParser handler = new SAXJsonParser(); 
    parser.parse(stream, handler); 
    return handler.getJson(); 
} 

Y la aplicación SAXJsonParser:

package xml2json; 

import net.sf.json.*; 
import org.apache.commons.lang.StringUtils; 
import org.xml.sax.*; 
import org.xml.sax.helpers.DefaultHandler; 
import java.util.ArrayList; 
import java.util.List; 

public class SAXJsonParser extends DefaultHandler { 

    static final String TEXTKEY = "_text"; 

    JSONObject result; 
    List<JSONObject> stack; 

    public SAXJsonParser(){} 
    public JSONObject getJson(){return result;} 
    public String attributeName(String name){return "@"+name;} 

    public void startDocument() throws SAXException { 
     stack = new ArrayList<JSONObject>(); 
     stack.add(0,new JSONObject()); 
    } 
    public void endDocument() throws SAXException {result = stack.remove(0);} 
    public void startElement (String uri, String localName,String qName, Attributes attributes) throws SAXException { 
     JSONObject work = new JSONObject(); 
     for (int ix=0;ix<attributes.getLength();ix++) 
      work.put(attributeName(attributes.getLocalName(ix)), attributes.getValue(ix)); 
     stack.add(0,work); 
    } 
    public void endElement (String uri, String localName, String qName) throws SAXException { 
     JSONObject pop = stack.remove(0);  // examine stack 
     Object stashable = pop; 
     if (pop.containsKey(TEXTKEY)) { 
      String value = pop.getString(TEXTKEY).trim(); 
      if (pop.keySet().size()==1) stashable = value; // single value 
      else if (StringUtils.isBlank(value)) pop.remove(TEXTKEY); 
     } 
     JSONObject parent = stack.get(0); 
     if (!parent.containsKey(localName)) { // add new object 
      parent.put(localName, stashable); 
     } 
     else {         // aggregate into arrays 
      Object work = parent.get(localName); 
      if (work instanceof JSONArray) { 
       ((JSONArray)work).add(stashable); 
      } 
      else { 
       parent.put(localName,new JSONArray()); 
       parent.getJSONArray(localName).add(work); 
       parent.getJSONArray(localName).add(stashable); 
      } 
     } 
    } 
    public void characters (char ch[], int start, int length) throws SAXException { 
     JSONObject work = stack.get(0);   // aggregate characters 
     String value = (work.containsKey(TEXTKEY) ? work.getString(TEXTKEY) : ""); 
     work.put(TEXTKEY, value+new String(ch,start,length)); 
    } 
    public void warning (SAXParseException e) throws SAXException { 
     System.out.println("warning e=" + e.getMessage()); 
    } 
    public void error (SAXParseException e) throws SAXException { 
     System.err.println("error e=" + e.getMessage()); 
    } 
    public void fatalError (SAXParseException e) throws SAXException { 
     System.err.println("fatalError e=" + e.getMessage()); 
     throw e; 
    } 
} 
0

docx4j

He usado docx4j antes, y vale la pena echar un vistazo a.

unXml

También podría retirar mi fuente abierta unXml -library que está disponible en Maven Central.

Es ligero, y tiene una sintaxis simple para elegir XPaths de su xml, y hacer que se devuelvan como atributos Json en un JacksonObjectNode.