开发者工具·语法转换器
XML 到 JSON 映射:属性、文本节点和一对多问题
· 工作原理
xml json 数据格式
没有单一正确的方法可以将 XML 转换为 JSON,因为 XML 具有 JSON 所缺乏的属性、混合内容和有序子项。这篇文章解释了常见的映射约定以及每个约定中的陷阱。
为什么一个 <item> 成为一个对象,两个成为一个数组 — XML feed,其 JSON 形状根据它有多少条目而变化
具有 `<item>one</item>` 的 Feed 会生成 `"item": "one"`;添加第二个同级将该属性更改为 `"item": ["one", "two"]`。解析器无法推断出一项在概念上是一项的列表,因为这两种含义具有相同的 XML 语法。因此,当生产发送第二个样本时,仅针对第一个样本构建的代码可能会失败。
ToolAcre 并没有将这种不稳定性隐藏在始终数组选项后面。它将名称一次记录为一个值,并将重复的同级记录为一个数组。这种直接映射很容易检查,但需要稳定集合形状的消费者必须使用模式知识或在转换后自行规范化结果。
XML 具有 JSON 所没有的特性 — 属性、与元素混合的文本、有序同级、命名空间、注释和处理指令
XML 将属性与子元素分开,保留同级顺序,允许元素之间存在文本,携带命名空间前缀,并且可以包含注释和处理指令。 JSON 提供对象和数组,但没有这些节点类别的内置等效项。因此,任何 XML 到 JSON 结果都是选定的投影,而不是通用翻译。
该读者删除声明、注释和处理说明。命名空间前缀保持逐字而不是被解析:`<ns:item>` 成为键 `ns:item`,而 `xmlns:ns` 成为 `@xmlns:ns`。混合文本是在一个键下连接的,因此它在子元素周围的原始位置会丢失,并且会出现一条警告,表示转换无法往返。
属性约定 - @ 或 $ 等前缀、它们存在的原因以及同名属性和子元素如何冲突
属性使用 `@` 前缀。 `<user id="7"><id>other</id></user>` 成为 `@id` 等于 `"7"` 且子 `id` 等于 `"other"` 的对象。该前缀可防止两个不同的 XML 构造在单个对象属性中发生冲突。当 JSON 写回 XML 时,它也成为转换器合约的一部分。
其他库可能使用 `$`、属性对象或其他约定。 ToolAcre 仅支持可见的 `@` 映射。在不更改编写器的情况下更改应用程序代码中的前缀会将属性转换为元素,因此在使用转换后的值作为中间检查形式时保留它。
文本节点约定 — #text 或 _ 表示元素内容,以及当元素同时具有文本和子元素时会发生什么
仅包含文本的元素会折叠为该字符串。当属性或子属性也存在时,文本位于 `#text` 下; CDATA 单独保存在 `#cdata` 下。自闭合标签变成空字符串。这些保留键使编写者可以将普通子名称与 JSON 本身未定义的内容类别区分开来。
混合内容仍然有损。在 `<p>before<b>bold</b>after</p>` 中,相对于子项的“之前”和“之后”位置无法从连接的 `#text` 属性中重建。该工具会检测该结构模式并发出警告。当文档顺序是含义的一部分时,请使用保留节点的 XML API。
一对多问题 - 重复元素仅在重复时才变成数组,以及为什么消费者必须防御性编码
仅在观察到重复后,重复的同级才会转为数组。单个 `<book>` 是一个对象;两本书是一个对象数组。这有时称为一对多问题,但这不是解析器缺陷。源文档根本不包含与其出现无关的列表声明。
防御性消费者可以使用模式知识规范已知路径:当 `catalogue.book` 还不是数组时,将其包装起来。不要将该规则应用于每个属性,因为普通标量不应仅仅为了对称而成为列表。转换器故意避免发明此类域信息。
工作示例:转换一个小型 RSS 样式文档 — 属性、重复元素和命名空间,并带注释的结果 JSON
转换 `<feed xmlns:m="https://example.invalid/meta"><item id="1"><m:title>One</m:title></item><item id="2"><m:title><![CDATA[Two & More]]></m:title></item></feed>`。根目录是 `feed`; `@xmlns:m` 保留命名空间声明; `item` 是一个数组;每个 `@id` 都是文本;第二个标题包含 `#cdata`。
类型推断默认处于关闭状态,因此即使 `id="2"` 仍保留字符串 `"2"`。启用推理可以让解析器将数字和布尔文本读取为 JavaScript 类型,但 XML 没有声明该意图。该选项是用户控制的猜测,而不是文档提供的证据。
这不包括什么 - 模式驱动的转换知道元素始终是列表,这需要 XSD 或手动映射
未加载 XSD,并且没有可用的架构驱动列表信息。当仅出现一个元素时,转换器无法知道该元素是可重复的,无法验证所需的子元素,无法将名称空间 URI 解析为应用程序类型或生成类型化客户端。成功的解析仅建立被配置的读取器接受的格式良好的 XML 。
DOCTYPE 声明在解析之前被拒绝,包括无害的声明。该边界可防止外部实体请求、本地文件读取和实体扩展。删除 DOCTYPE 也可能会删除文档所依赖的声明,因此只有当您拥有数据并了解后果时才可以这样做。
要点:XML 到 JSON 是映射,而不是翻译 - 以及语法转换器面板如何让您在浏览器中检查该映射
将结果视为 ToolAcre 的记录映射:`@` 用于属性,`#text` 用于混合元素文本,`#cdata` 用于 CDATA,重复同级和文字命名空间前缀之后的数组。这些规则使输出可预测,而无需假装 XML 和 JSON 共享一个数据模型。
对于检查而言,此投影快速且可读。为了实现持久集成,请测试一个或多个出现情况、与子级共享名称的属性、空元素、混合内容和命名空间。如果元素顺序或模式约束很重要,请根据该约定解析 XML 而不是依赖于通用转换后的形状。
将原始 XML 夹具保留在标准化期望旁边。如果依赖项升级更改了数组处理、空白修剪或实体解码,该配对会保留证据。它还为审阅者提供了一个查看 JSON 视图无法实现的区别的地方。仅转换后的对象无法证明空字符串是否来自自闭合元素、配对标签或源中的其他约定。