XML 转 JSON:浏览器 DOMParser 的解析、错误检测与非流式边界
浏览器中的 DOMParser 可以把 XML 字符串解析为 Document,再通过元素、属性和子节点构造 JSON。它适合需要 DOM 查询的中小型输入,但解析结果必须检查错误节点,且整个字符串会先进入内存;本文不提供未经测试的性能数字,也不把 DOMParser 描述成流式方案。
一、问题概述:解析成功与业务转换是两件事
parseFromString 返回 Document 并不等于输入 XML 合法或 JSON 映射正确。浏览器可能把解析错误放进 parsererror 元素;即使没有错误,属性、重复子元素和空元素仍需要单独的转换规则。
二、最小复现:解析 XML 并检查错误节点
不同浏览器对错误文档的展示文本和 parsererror 细节可能不同,因此只把“存在错误节点”作为控制流条件,不依赖某个固定错误字符串。
function parseXml(source: string): XMLDocument {
const document = new DOMParser().parseFromString(source, "application/xml");
const errors = document.getElementsByTagName("parsererror");
if (errors.length > 0) throw new Error("XML parser reported an error");
return document;
}
const doc = parseXml("<root><item>one</item></root>");
console.log(doc.documentElement.localName); // root三、根因:DOMParser 是整文档、非流式的 DOM 构建过程
DOMParser 接收完整字符串并构建文档树,调用方随后才能遍历节点。因此输入越大,内存和遍历成本越需要通过实际环境评估;不能从一次样例推导通用耗时,也不能在接收大量数据时假设它会逐块释放。
四、推荐方案:先验证 Document,再做明确的节点投影
把 XML 解析、parsererror 检测和 DOM→JSON 投影拆开。投影时显式处理属性、文本、重复元素和空元素;如果输入来自不可信来源,还要在业务层限制大小和允许的结构。需要真正流式处理时,应选择支持流式事件的解析方案,而不是给 DOMParser 加一个不存在的选项。
五、完整代码:将 DOM 元素投影为保守 JSON
以下函数使用元素 localName 作为键,重复子元素归并为数组,属性放在 $attributes。它只展示投影策略;生产代码仍需根据 schema 处理混合内容和命名空间。
function elementToJson(element: Element): unknown {
const children = Array.from(element.children);
const attributes = Object.fromEntries(Array.from(element.attributes).map((attr) => [attr.name, attr.value]));
if (children.length === 0) {
return Object.keys(attributes).length === 0 ? (element.textContent ?? "") : { $attributes: attributes, $text: element.textContent ?? "" };
}
const result: Record<string, unknown> = Object.keys(attributes).length ? { $attributes: attributes } : {};
for (const child of children) {
const key = child.localName;
const value = elementToJson(child);
result[key] = key in result ? (Array.isArray(result[key]) ? [...(result[key] as unknown[]), value] : [result[key], value]) : value;
}
return result;
}六、常见错误方案
只读取 textContent 会丢失属性和嵌套元素;看到 parsererror 就读取固定英文文案会在不同浏览器中失效;把所有子元素按 nodeName 合并会把不同 namespace 的同名元素混在一起。把 DOMParser 当作流式解析器也会造成错误的内存预期。
七、边界条件:空元素、CDATA 与命名空间
<item/> 的 textContent 为空,不代表它一定应转换为空字符串;CDATA 在 DOM 中通常作为文本内容呈现,若要保留表示形式需要额外约定。命名空间场景应使用 namespaceURI/localName,而不是只看带前缀的 nodeName。
八、如何验证解析与投影
分别测试合法 XML、未闭合标签、错误嵌套、空元素、属性、重复节点、CDATA 和 namespace。断言错误输入被拒绝、合法 Document 的根节点正确、重复键归并为数组,并在目标浏览器中记录实际内存行为,而不是填写猜测的耗时数据。
九、FAQ
问:DOMParser 会返回 null 表示 XML 错误吗?答:浏览器通常返回带错误信息的 Document,错误节点和文案存在实现差异,应按文档检查。
问:DOMParser 能边下载边解析吗?答:它接收完整字符串,不是流式 API;需要流式处理应选用相应解析器。
问:为什么解析成功还要做 schema 验证?答:XML well-formed 只保证语法,不保证字段、基数和业务类型。
十、总结
浏览器 XML→JSON 的流程是完整字符串进入 DOMParser、检查 parsererror、再按明确规则遍历 DOM。DOMParser 是非流式整文档模型,不能编造性能承诺;属性、重复元素、空值和 namespace 必须由投影契约处理。
来源与延伸阅读
技术审校所依据的规范与权威参考资料。
相关文章
XML 转 JSON:namespace URI、prefix 与 localName 的区别
用相同 URI 的不同前缀示例说明 XML 命名空间身份由 namespace URI 决定,转换时应保留 URI 与 localName,而不是依赖 prefix。
错误排查XML 转 JSON:单节点与多节点的数组形状推断
解释 XML 只有一个子节点和出现多个同名节点时的 JSON 形状差异,比较始终数组、schema 驱动和后处理三种策略。
实现原理XML Formatter 自闭合标签缩进:Token、标签类型与缩进栈
用受限 token 化和缩进栈说明 XML formatter 如何区分开始、结束、自闭合标签及注释,并明确不覆盖完整 XML 规范。
继续阅读
可打开关联的浏览器工具,使用自己的样本验证文中的处理流程。
打开关联工具