将XML转换为JSON格式。

19

我需要将docx文件格式(即openXML格式)转换成JSON格式。我需要一些指导来完成此操作。提前致谢。


考虑使用 simplify-docx - Jthorpe
Underscore-java库有一个静态方法U.xmlToJson(xml)。 - Valentyn Kolesnikov
10个回答

13

您可以查看Json-lib Java库,该库提供了XML到JSON的转换功能。

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

如果你需要根标签,只需添加一个外层虚拟标签:

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

5
这很好,但结果是 {"test":"1.2","test2":"123"} 而不是 {"hello":{"test":"1.2","test2":"123"}},也就是说它只打印叶子节点(<hello>标签丢失了)。如果我们添加一个中间节点(作为<hello>的子节点和<test>的父节点),同样会被忽略。这是一个配置问题吗? - bluish
在这种情况下,我们有一个XML参数,例如<...>[2] jsfnek [5]<....>,但是在我的JSON中,我们只得到了[2]的第一个值。您能否帮助我理解为什么无法读取完整值? - ojus kulkarni

10

XML和JSON之间没有直接的映射关系;XML携带类型信息(每个元素都有名称)以及命名空间。因此,除非每个JSON对象都嵌入了类型信息,否则转换将会有损失。

但这并不一定重要。重要的是JSON的使用者知道数据契约。例如,给定以下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>

你可以将其转换为这样:
{
    "books": [
        { "author": "Jimbo Jones", "title": "Bar Baz", "summary": "Foo" },
        { "author": "Fake Person", "title": "Don't Care", "summary": "Dummy Data" },
    ]
}

消费者不需要知道 books 集合中的每个对象都是一个 book 对象。
编辑:
如果您有 XML 模式,并且正在使用 .NET,则可以使用 xsd.exe 从模式生成类。然后,您可以将源 XML 解析为这些类的对象,然后使用 DataContractJsonSerializer 将类序列化为 JSON。
如果没有模式,则很难绕过手动定义自己的 JSON 格式。

如何进行此转换?输入的 XML 格式有些复杂,因此转换必须易于操作且具有良好的性能。哪种编程语言更适合执行此操作? - vignesh
2
这正是XML-ValidatorBuddy可以为您做的。 - Fluffi1974
Jacob,我正在使用你的代码示例,并已成功将XML文件转换为JSON对象。但是,我的XML文件表示根元素(<DATA>)和分组元素(<AllCustomers>),其中所有其他<Customer>元素都嵌套在其中。我需要的是<Customer>元素,它可能包含任何属性、子元素和孙子元素等变化。是否有一种方法可以返回每个<Customer>元素的ArrayList<JSONObject>。换句话说,我是否可以指定类似于XPath的内容并仍然使用SAX?附言:由于大小限制,我无法使用DOM。 - Eyal Zinder
你是不是想把这个问题发到另一个答案上?我没有任何代码示例。 - Jacob

6

如果您对各种实现不满意,可以尝试自己编写。这是我今天下午编写的一些代码,可帮助您入门。它与net.sf.json和apache common-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();
}

以下是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;
    }
}

6

org.json命名空间中的XML类提供了这个功能。

您需要调用静态的toJSONObject方法

将格式良好(但不一定有效)的XML字符串转换为JSONObject。在此转换中可能会丢失某些信息,因为JSON是数据格式,而XML是文档格式。XML使用元素、属性和内容文本,而JSON使用无序的名称/值对集合和值数组。JSON不喜欢区分元素和属性。类似元素的序列表示为JSONArray。内容文本可以放置在“content”成员中。注释、prologs、DTD和<[[ ]]>被忽略。


这绝对是最简单和最清晰的方法。谢谢。 - Domenic D.
我曾尝试使用这个,但它创建了基于节点/文本的XML。如何创建基于属性的XML?例如:如果我的JSON数据是: {Order:{OrderLine:{ItemID:"1234"}},OrderNo:"4567"} 所需输出为: <Order OrderNo="4567"><OrderLine ItemID="1234"/></Order> 这是基于节点的。我正在寻找基于属性的XML转换。请让我知道您是否有任何建议。 - Aki

4
如果您需要在XML转换为JSON之前能够操纵您的XML,或者想要对您的表示进行细粒度控制,请选择XStream。在xml-to-object、json-to-object、object-to-xml和object-to-json之间进行转换非常容易。这里是XStream文档中的一个示例:
<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>

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

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

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

注意:尽管方法名称为toXML(),但由于使用了Jettison驱动程序,XStream将生成JSON。

4
将完整的docx文件转换为JSON似乎不是一个好主意,因为docx是以文档为中心的XML格式,而JSON是以数据为中心的格式。XML通常被设计为既是文档中心又是数据中心。虽然技术上可以将以文档为中心的XML转换为JSON,但处理生成的数据可能过于复杂。尝试专注于实际需要的数据,并仅转换该部分。

1

链接已经修复。 - Piyush Chordia

0

Docx4j

我以前用过docx4j,值得一看。

unXml

你也可以看看我开源的unXml库,它可以在Maven Central上获得。

它很轻量级,并且有一个简单的语法来从你的xml中挑选出XPaths,并将它们作为Json属性返回到Jackson ObjectNode中。


0

你提供的示例是 PHP 的;但问题标签是 Java。 - Paul
1
网站现在已被删除,这个回答也应该被删除。 - PeterS

0

使用

xmlSerializer.setForceTopLevelObject(true)

在生成的 JSON 中包含根元素。

你的代码应该像这样:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接