不喜欢广告? 无广告 今天

XML 未死(不幸地)——像成年人一样将其转换为 JSON

更新于

你以为你逃过了XML。你错了。这里教你如何处理来自旧式API和企业系统的XML,理解其结构上的怪异之处,并将其转换为JSON,而不会失去理智。

XML并未死亡(不幸的是)——像成熟开发者一样将它转换为JSON 1
广告 移除?

你学会了REST,拥抱了JSON,认为XML时代已经结束,就像Flash或IE6那样,你会像篝火故事一样警告初级开发者。但你的新客户给了你银行集成的API凭证,结果你看到了一个长达400行的SOAP信封,直直地盯着你。

欢迎回到XML。它从未离开。

为什么XML无处不在

对于许多构建现代应用的开发者来说,XML看起来像是一种过时的技术。但在现实世界中——尤其是在企业软件、银行、医疗保健和政府系统中——XML是绝对关键的基础设施。你可能会在以下这些场景中遇到它:

  • SOAP Web服务 – 金融机构、保险平台和大型ERP系统仍使用SOAP作为标准。你的金融科技集成很可能需要经过一个。
  • 银行API – ISO 20022、SWIFT消息以及许多核心银行API均以XML格式通信。目前没有REST选项。
  • 政府数据 – HMRC、IRS以及大多数政府门户网站都接受或返回XML格式。这一趋势短期内不会改变。
  • 企业中间件 – SAP、Oracle以及老旧的ESB系统原生支持XML。如果你正在集成任何企业级系统,那么你很可能遇到XML。
  • RSS和Atom数据流 – 仍然使用XML。许多内容管道、新闻聚合器和监控工具都依赖它们。

令人不安的真相:XML不会消失,因为建立在它之上的系统不会消失。替换一家银行的核心基础设施不是一次冲刺任务。因此,你只能适应。

XML与JSON:真正让你出错的结构差异

在你开始转换之前,理解为什么XML到JSON不仅仅是格式转换非常重要。这两种格式在数据建模上存在差异,这些差异会引发真实的问题。

并列对比:两种格式中的相同数据

以一个简单的客户订单为例。这里是XML格式:

<order id="ORD-1042" currency="GBP">
  <customer>
    <name>Alice Martin</name>
    <email>alice@example.com</email>
  </customer>
  <items>
    <item sku="PRD-001">
      <description>Wireless Keyboard</description>
      <quantity>1</quantity>
      <price>49.99</price>
    </item>
    <item sku="PRD-007">
      <description>USB-C Hub</description>
      <quantity>2</quantity>
      <price>29.99</price>
    </item>
  </items>
</order>

这里是JSON格式:

{
  "order": {
    "@id": "ORD-1042",
    "@currency": "GBP",
    "customer": {
      "name": "Alice Martin",
      "email": "alice@example.com"
    },
    "items": {
      "item": [
        {
          "@sku": "PRD-001",
          "description": "Wireless Keyboard",
          "quantity": "1",
          "price": "49.99"
        },
        {
          "@sku": "PRD-007",
          "description": "USB-C Hub",
          "quantity": "2",
          "price": "29.99"
        }
      ]
    }
  }
}

你已经可以看到结构上的摩擦点。我们来逐一分析。

属性与键

XML元素可以携带属性(id="ORD-1042")以及子元素和文本内容。JSON没有属性的概念——所有内容都是键值对。最常见的约定是在转换时将属性前缀为 @ ,从而得到 "@id": "ORD-1042"。一些解析器使用 $ 或完全扁平化处理。这种约定很重要,因为你的消费代码需要知道预期的前缀。

数组与重复元素

这一点经常让开发者遇到麻烦。在JSON中,数组是显式的: [...]。在XML中,没有这种区别——重复的兄弟元素被隐式视为列表。一个解析器看到一个 <item> 元素时,可能返回一个对象。看到两个 <item> 元素时,它会返回一个数组。当API返回单个结果时,你的代码就会崩溃。

解决方法是为已知的列表字段强制使用数组,或使用能保留类型信息的库。当你处理单个数据时,务必检查某个字段看起来像单个对象,但在生产数据中可能有时是列表。

文本节点与混合内容

XML元素可以同时包含文本内容和子元素(混合内容)。JSON无法清晰地表示这一点。解析器处理方式不同——有些使用 #text 键,有些使用 _,有些则直接丢弃混合内容。如果你在转换带有混合内容的XML,请手动验证输出结果。

命名空间

SOAP响应中充满了XML命名空间: <ns2:getOrderResponse xmlns:ns2="http://...">。根据你的解析器,这些命名空间要么被剥离,要么被合并到键名(ns2:getOrderResponse),要么映射到URI。大多数情况下你希望它们被剥离,但如果两个命名空间共享元素名称,你将失去区分。在处理之前,了解你所面对的内容。

快速路径:无需编写解析器即可在线转换XML

如果你在调试API响应、探索一个不熟悉的XML模式,或进行一次性转换,编写解析器是过度的。使用 XML 到 JSON 转换器 ——粘贴你的XML,立即获得干净的JSON,并在编写任何代码前检查结构。

它处理属性(使用 @ 前缀约定)、嵌套元素、重复元素作为数组,并保留文本内容——这涵盖了大多数真实世界的API数据。它有助于快速理解剥离信封后的SOAP响应实际结构。

程序化转换:生产环境中的最佳选择

在生产环境中集成XML API时,你应该使用成熟的库而不是手动编写解析器。以下是各语言的推荐选项:

JavaScript / Node.js

import { XMLParser } from 'fast-xml-parser';

const parser = new XMLParser({
  ignoreAttributes: false,
  attributeNamePrefix: '@',
  isArray: (name) => ['item', 'product', 'order'].includes(name),
});

const result = parser.parse(xmlString);

fast-xml-parser 是Node.js的最佳选择。使用 isArray 强制处理已知列表元素为数组——这可以防止在生产环境中出现单个项与数组不一致的问题。

Python

import xmltodict

with open('response.xml') as f:
    data = xmltodict.parse(f.read())

import json
print(json.dumps(data, indent=2))

xmltodict 是Python的标准选择。它使用 @ 作为属性前缀,使用 #text 作为文本节点。请注意,它返回一个 OrderedDict,该结构可以与 json.dumps.

PHP

$xml = simplexml_load_string($xmlString);
$json = json_encode($xml);
$data = json_decode($json, true);

良好序列化。 simplexml_load_string + json_encode PHP的 DOMDocument 是快速路径,但它对属性处理不一致,且在边缘情况中可能丢失数据。在处理SOAP响应的生产环境中,建议使用 LIBXML_NOBLANKS 配合

或专用库。

  • 常见陷阱需注意 数字被转换为字符串。 "49.99"XML没有数字类型——所有内容都是文本。你的价格字段将是 49.99,而不是
  • 。转换后必须显式转换。 <active>true</active> 变成 "active": "true"布尔值仍为字符串。
  • 。在使用前需检查。 null 空元素变为 <middleName/> 或空对象。 null, "", 或者 {} 可能被转换为
  • ,具体取决于解析器。需测试边缘情况。 CDATA段
  • 可能被保留也可能被丢弃。如果API使用CDATA来转义HTML内容,需确认你的解析器是否处理它,避免内容被静默移除。 顺序无法保证。

某些模式中XML元素的顺序是重要的;而JSON对象的键顺序则不是。如果消费系统依赖顺序,必须显式处理。

专门处理SOAP <Envelope> SOAP在XML之上增加了一层:每个响应都被包裹在一个 <Body>中,带有 <Header> ,通常带有命名空间声明和一个

块。在转换为JSON之前,通常需要提取其中的主体内容。 zeep 在Python中使用 soapstrong-soap (SOAP客户端),你可以直接获得Python对象,无需自行解析XML。在Node.js中,也应如此操作。如果你直接使用 fetchaxios调用SOAP端点,你将需要手动剥离信封,然后再运行XML到JSON转换器。

为了快速查看SOAP响应, XML 到 JSON 转换器 非常有用——粘贴完整的信封,查看完整结构,从而确定你需要的数据路径。

接受现实并继续前进

当你意识到你的新项目必须集成一个2003年开发的SOAP API时,会有一种特别的痛苦。允许自己感受这种痛苦,然后继续前进。XML是一个已解决的问题——解析器成熟,转换工具存在,陷阱也已被充分记录。你不是第一个面对400行信封的开发者。

使用适合你语言的库,显式处理类型转换,为已知列表字段强制使用数组,并使用真实数据而非API文档中的理想化示例进行测试。文档会展示一个条目;生产环境会发送你五十个。

对于探索性工作——理解一个不熟悉的XML模式,验证转换逻辑在编写代码前——请将 XML 到 JSON 转换器 保存到书签中。它比每次都需要启动脚本要快得多。

想要享受无广告的体验吗? 立即无广告

安装我们的扩展

将 IO 工具添加到您最喜欢的浏览器,以便即时访问和更快地搜索

添加 Chrome 扩展程序 添加 边缘延伸 添加 Firefox 扩展 添加 Opera 扩展

记分板已到达!

记分板 是一种有趣的跟踪您游戏的方式,所有数据都存储在您的浏览器中。更多功能即将推出!

广告 移除?
广告 移除?
广告 移除?

新闻角 包含技术亮点

参与其中

帮助我们继续提供有价值的免费工具

给我买杯咖啡
广告 移除?