使用XML Schema将XML转换为JSON

8
我想将XML转换为JSON(具体来说,是OAI-PMH响应)。我目前正在使用node.js的xml2js,但问题在于JSON非常冗长,有太多的嵌套级别和数组,即使只有一个元素作为子元素,并且永远不会超过一个。问题在于xml2js对XML文件的模式一无所知,因此必须保守处理。

我的问题是,是否有任何其他(最好是JavaScript)代码可以使用XML Schema来指导转换过程?因此,如果模式定义了XML的类型和结构,则JSON会自动利用它并具有正确的类型,而不是不必要的数组级别。

6个回答

1
最终,我决定实现这样一个包:xml4js
因此,对于从XML Primer获取的XML:
<?xml version="1.0"?>
<purchaseOrder orderDate="1999-10-20" xmlns="http://www.example.com/PO">
   <shipTo country="US">
      <name>Alice Smith</name>
      <street>123 Maple Street</street>
      <city>Mill Valley</city>
      <state>CA</state>
      <zip>90952</zip>
   </shipTo>
   <billTo country="US">
      <name>Robert Smith</name>
      <street>8 Oak Avenue</street>
      <city>Old Town</city>
      <state>PA</state>
      <zip>95819</zip>
   </billTo>
   <comment>Hurry, my lawn is going wild!</comment>
   <items>
      <item partNum="872-AA">
         <productName>Lawnmower</productName>
         <quantity>1</quantity>
         <USPrice>148.95</USPrice>
         <comment>Confirm this is electric</comment>
      </item>
      <item partNum="926-AA">
         <productName>Baby Monitor</productName>
         <quantity>1</quantity>
         <USPrice>39.98</USPrice>
         <shipDate>1999-05-21</shipDate>
      </item>
   </items>
</purchaseOrder>

不使用XML Schema来指导转换过程,开启显式数组选项后,您将获得以下结果:
{
  "purchaseOrder": {
    "$": {
      "orderDate": "1999-10-20",
      "xmlns": "http://www.example.com/PO"
    },
    "shipTo": [
      {
        "$": {
          "country": "US"
        },
        "name": [
          "Alice Smith"
        ],
        "street": [
          "123 Maple Street"
        ],
        "city": [
          "Mill Valley"
        ],
        "state": [
          "CA"
        ],
        "zip": [
          "90952"
        ]
      }
    ],
    "billTo": [
      {
        "$": {
          "country": "US"
        },
        "name": [
          "Robert Smith"
        ],
        "street": [
          "8 Oak Avenue"
        ],
        "city": [
          "Old Town"
        ],
        "state": [
          "PA"
        ],
        "zip": [
          "95819"
        ]
      }
    ],
    "comment": [
      "Hurry, my lawn is going wild!"
    ],
    "items": [
      {
        "item": [
          {
            "$": {
              "partNum": "872-AA"
            },
            "productName": [
              "Lawnmower"
            ],
            "quantity": [
              "1"
            ],
            "USPrice": [
              "148.95"
            ],
            "comment": [
              "Confirm this is electric"
            ]
          },
          {
            "$": {
              "partNum": "926-AA"
            },
            "productName": [
              "Baby Monitor"
            ],
            "quantity": [
              "1"
            ],
            "USPrice": [
              "39.98"
            ],
            "shipDate": [
              "1999-05-21"
            ]
          }
        ]
      }
    ]
  }
}

但是该软件包提供了以下内容:
{
  "purchaseOrder": {
    "$": {
      "orderDate": "1999-10-20T00:00:00.000Z"
    },
    "shipTo": {
      "$": {
        "country": "US"
      },
      "name": "Alice Smith",
      "street": "123 Maple Street",
      "city": "Mill Valley",
      "state": "CA",
      "zip": 90952
    },
    "billTo": {
      "$": {
        "country": "US"
      },
      "name": "Robert Smith",
      "street": "8 Oak Avenue",
      "city": "Old Town",
      "state": "PA",
      "zip": 95819
    },
    "comment": "Hurry, my lawn is going wild!",
    "items": {
      "item": [
        {
          "$": {
            "partNum": "872-AA"
          },
          "productName": "Lawnmower",
          "quantity": 1,
          "USPrice": 148.95,
          "comment": "Confirm this is electric"
        },
        {
          "$": {
            "partNum": "926-AA"
          },
          "productName": "Baby Monitor",
          "quantity": 1,
          "USPrice": 39.98,
          "shipDate": "1999-05-21T00:00:00.000Z"
        }
      ]
    }
  }
}

附上的示例未按预期工作。https://github.com/peerlibrary/node-xml4js任何帮助都将非常有帮助。 - sharath chandra

1
我曾经遇到了与X2JS类似但相反的问题:如果只有一个子元素(即使应该是列表),它不会创建一个列表。对我来说,解决方案是向转换器提供额外的选项“arrayFormPaths”--这会导致匹配的元素成为数组,即使只有一个元素。
我同意应该有一种使用XML Schema来解决这个问题的方法......但我也找不到任何东西。

@Mitar,看起来很有前途。有更新的计划吗?我刚试着安装了一下:“发现13个漏洞(1个低级,10个中等,2个高级)”。 - JohnK
我在哪里可以找到你提到的X2JS库?它似乎与OP的xml2js不同,因为我在那里找不到你的“arrayFormPaths”选项。是这个吗?https://github.com/abdolence/x2js - Marcel

0
有一个非常维护良好的Python包叫做xmlschema,可以轻松地完成这个任务。
使用to_dict方法。
import xmlschema
import simplejson as json

my_schema = xmlschema.XMLSchema("../shiporder.xsd")
obj = my_schema.to_dict('../shiporder.xml')
# in case you want to save the json in a file
json.dumps(obj) 

你可以从w3schools获取船舶订单的示例xml和xsd。下载后,尝试在船舶订单xml中仅保留一个item,并查看模式如何保留数组类型。数字类型在转换为json后也会被保留。

我尝试了这种方法。看起来xmlschema或者simplejson依赖于Counter,而Counter只在Python 2.7中可用。然而,xmlschema在Python 2.7上无法安装。 - user358041

0
发现在GitHub上的以下项目库可以胜任这项工作: 模式感知XML到JSON转换器
这个库是用Java编写的。它还不完全成熟,但是可以使用提供的模式进行转换。

-1

-5
XML模式用于XML验证。使用XML模式无法转换任何内容。模式定义了XML文档的结构。如果您想要转换某些内容,您需要一个XSLT,它是一种XML转换规范。在这里查看如何在JavaScript中执行此操作:http://www.w3schools.com/xsl/xsl_client.asp

3
我希望将XML文档的结构转换为JSON。当然这有所帮助。例如, maxOccurs 可以帮助您知道是否应创建数组(如果 maxOccurs 为1,则您不需要数组)。而 type 可以帮助您将其转换为JSON类型。 - Mitar
1
@Mitar 你可以将XML模式转换为JSON,但这也需要XSLT。一个模式本身并不会转换任何东西。 - ceving
我想说的是,模式可以用来帮助转换过程。 - Mitar
@Mitar 是的,文本编辑器也可以帮助转换过程。 - ceving
该软件包基于node-xml2js构建,可以检测和解析XML Schema,然后将其用于将JavaScript对象转换为一致的基于模式驱动的结构。 - gvlx

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