Javascript is required
实现原理发布于 2026-07-28审校于 2026-08-084 分钟阅读

JSON 转 XML:属性与 CDATA 的映射约定

JSON 字符串只有字符内容,不携带 XML 的属性节点或 CDATA 标记。转换器必须通过约定键名或中间模型表达这些意图;否则把字符串放进属性、普通文本或 CDATA 的结果会依赖工具默认行为。本文只讨论属性与 CDATA 的映射,不讨论数组冲突或 SOAP。

JSON to XMLCDATAAttributesEscaping

一、问题概述:字符串内容不等于 XML 表示方式

description: "a < b" 在 XML 中可以是转义后的普通文本,也可以放进 CDATA;id 还可能要求作为属性。三种表示的字符结果、schema 类型和接收方处理方式不同,不能只看最终显示文本。

二、最小复现:先约定属性与 CDATA 键

本文采用 $attributes 表示属性、$text 表示普通文本、$cdata 表示 CDATA。一个节点只能在 $text$cdata 中选择一个,属性值始终按 XML 属性规则转义。

const input = {
  message: {
    $attributes: { id: "m-1" },
    $cdata: "if (a < b && c > d) return;",
  },
};
// <message id="m-1"><![CDATA[if (a < b && c > d) return;]]></message>

三、根因:CDATA 是 XML 语法标记,不是 JSON 数据类型

JSON.parse 和 JSON.stringify 不会保留“这是 CDATA”这一意图;它们只处理字符串。属性同样不是 JSON 的原生层级。必须在转换边界引入明确约定,并让 schema 验证器拒绝同时出现普通文本和 CDATA 的对象。

四、推荐方案:使用中间模型并显式选择表示

先把输入规范化为 name、attributes、text 或 cdata,再交给 XML serializer。普通文本必须转义 &<>;属性还要处理引号。CDATA 不能包含 ]]>,遇到该序列时要拆成多个 CDATA 段,而不是直接拼接无效 XML。

五、完整代码:安全处理属性和 CDATA

下面的代码返回 XML 内容片段,展示属性转义和 CDATA 分段;它不负责命名空间、数组或 SOAP Envelope。

function escapeAttribute(value: string): string {
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll("\"", "&quot;");
}

function wrapCdata(value: string): string {
  return "<![CDATA[" + value.replaceAll("]]>", "]]]]><![CDATA[>") + "]" + "]>";
}

function messageXml(id: string, script: string): string {
  return "<message id=\"" + escapeAttribute(id) + "\">" + wrapCdata(script) + "</message>";
}

console.log(messageXml("m&1", "if (a < b && c > d) return;"));

六、常见错误方案

把所有字符串都包进 CDATA 会改变需要实体转义的普通文本约定;把 $cdata 当成属性会生成错误层级;直接输出 ]]> 会截断 CDATA。只转义 < 而不处理 &,也会让已有实体片段产生非法或不同语义。

七、边界条件:混合内容、空值与控制字符

空字符串可以是空元素、空 CDATA 或缺失字段,必须在契约中区分。一个节点同时拥有文本和子元素时属于 mixed content,不应被普通对象遍历器随意排序。非法 XML 控制字符也应在序列化前拒绝,而不是替换成问号。

八、如何验证映射结果

测试属性中的 &<>"、CDATA 中的 ]]>、空字符串、换行、Unicode 和控制字符。先用 XML parser 验证文档可解析,再检查属性值、文本值和 CDATA 内容是否保持;最后用接收方 schema 确认该字段确实允许 CDATA 等价的字符内容。

九、FAQ

问:CDATA 能保存任意字符串吗?答:不能直接包含 ]]>,且 XML 仍禁止某些控制字符。

问:CDATA 与普通文本的值有区别吗?答:解析后的字符通常可相同,但序列化形式和 schema/接收方约定可能不同。

问:JSON 能自动恢复原来的属性吗?答:不能,属性意图必须由输入约定或外部 schema 提供。

十、总结

JSON 没有属性和 CDATA 类型,必须通过显式键名或中间模型表达。属性按 XML 规则转义,普通文本与 CDATA 分开选择,并对 ]]>、控制字符和混合内容做边界验证。

来源与延伸阅读

技术审校所依据的规范与权威参考资料。

相关文章

继续阅读

可打开关联的浏览器工具,使用自己的样本验证文中的处理流程。

打开关联工具