Javascript is required
踩坑避坑发布于 2026-07-28审校于 2026-08-085 分钟阅读

XML Formatter:空白文本节点污染与 mixed content

XML formatter 如果只是对字符串重新排版,空白通常只是字符;如果先解析成 DOM 再序列化,插入的换行和缩进可能成为元素之间的文本节点。对于 <p>Hello <b>world</b>!</p> 这类 mixed content,空白本身可能有意义。本文只讨论空白文本节点与格式化边界。

XML FormatterWhitespaceDOMMixed Content

一、问题概述:看起来只是缩进,DOM 中却多了文本

元素内容全部是子元素时,换行缩进通常可以被视为格式空白;但文本与子元素交错时,Hello world! 的相邻空白属于内容。formatter 若无条件插入换行,重新解析后可能改变 textContent 或混合内容的显示。

二、最小复现:格式化前后的文本节点

下面的 XML 说明同一个元素既包含文本又包含子元素。是否允许在 <b> 前后插入换行,必须由 mixed-content 规则决定,而不能只看元素深度。

const inline = "<p>Hello <b>world</b>!</p>";
const pretty = "<p>\n  Hello <b>world</b>\n  !\n</p>";

console.log(inline);
console.log(pretty);
// A DOM reparse can expose the inserted newlines as text nodes.

三、根因:字符串格式化和 DOM 序列化不是同一操作

字符串 formatter 可以在不理解 XML 树的情况下调整字符,但 DOM 序列化会依据节点类型重新输出文本、属性和元素。解析再格式化还会丢失原始前缀/实体表示等词法细节,因此必须明确是要保留源码字符,还是要输出新的 DOM 表示。

四、推荐方案:检测 mixed content 后选择内联或保守输出

若元素同时拥有非空文本节点和元素子节点,应将其视为 mixed content,默认保持内联,或由 schema 提供专门排版规则。只有元素内容完全由元素子节点组成时,才适合自动插入缩进空白。字符串格式化与 DOM 重解析应分开验证。

五、完整代码:识别 mixed content

下面的节点模型只用于排版决策。isMixedContent 把非空文本和元素子节点同时存在视为混合内容,formatter 可以据此跳过自动换行。

type Node =
  | { kind: "text"; value: string }
  | { kind: "element"; name: string; children: Node[] };

function isMixedContent(node: Extract<Node, { kind: "element" }>): boolean {
  const hasText = node.children.some((child) => child.kind === "text" && child.value.trim() !== "");
  const hasElement = node.children.some((child) => child.kind === "element");
  return hasText && hasElement;
}

const paragraph: Node = {
  kind: "element",
  name: "p",
  children: [{ kind: "text", value: "Hello " }, { kind: "element", name: "b", children: [{ kind: "text", value: "world" }] }, { kind: "text", value: "!" }],
};
console.log(isMixedContent(paragraph)); // true

六、常见错误方案

把所有文本节点的空白都 trim 会删除 Hello 末尾或单词之间的必要空格;把每个元素都展开成多行会污染 mixed content;只比较格式化后的字符串也无法发现 DOM 重新解析后多出的文本节点。

七、边界条件:纯元素、纯文本与 CDATA

纯元素容器通常可以安全缩进,但仍要考虑 xml:space="preserve" 等约定;纯文本节点的前后空白可能属于数据;CDATA 解析后通常表现为文本,排版策略不能依据源码标记臆测。

八、如何验证格式没有污染内容

分别测试纯元素树、纯文本、mixed content、CDATA、xml:space 和相邻空白。比较格式化前后解析 DOM 的 textContent、子节点类型和顺序;如果目标是源码级格式化,还要比较实体和换行是否按预期保留。

九、FAQ

问:所有 XML 都能漂亮地换行吗?答:不是,mixed content 和 xml:space 可能要求保留空白。

问:只在字符串层格式化是不是一定安全?答:它不会新增 DOM 文本节点,但仍需正确识别标签、注释和 CDATA 边界。

问:DOM 序列化会保留原始缩进吗?答:DOM 通常只保留节点信息,不保证源码中的空白表示。

十、总结

XML formatter 必须区分源码字符排版与解析 DOM 后的重新序列化。纯元素内容可以自动缩进,mixed content 和保留空白场景应保持内联或遵循 schema;验证时比较 DOM 文本节点,而不只比较视觉格式。

来源与延伸阅读

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

相关文章

继续阅读

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

打开关联工具