使用 HTML Purifier 处理 MathML 的方法
在网页开发中,MathML(数学标记语言)常用于呈现复杂的数学公式,但默认的 HTML Purifier 配置会自动过滤掉 MathML 相关的标签和属性,导致公式无法正常显示。本文将介绍如何调整 HTML Purifier 的配置,使其在过滤不安全内容的同时,保留合法的 MathML 内容。
HTML Purifier 与 MathML 的基本关系
HTML Purifier 是一款用于过滤和净化 HTML 内容的工具,默认遵循 HTML 标准的安全规则,而 MathML 不属于标准 HTML 的标签集合,因此默认配置下会被当作未知标签过滤。要让 HTML Purifier 支持 MathML,需要手动配置允许 MathML 相关的标签、属性和命名空间。
基础配置步骤
首先需要通过 Composer 安装 HTML Purifier,执行以下命令:
composer require ezyang/htmlpurifier
接下来是核心的配置代码,我们需要自定义 HTML Purifier 的配置对象,添加 MathML 相关的允许规则:
<?php
require_once 'vendor/autoload.php';
// 初始化 HTML Purifier 配置
$config = HTMLPurifier_Config::createDefault();
// 开启 MathML 支持
$config->set('HTML.AllowedElements', array_merge(
$config->get('HTML.AllowedElements') ?? [],
// 基础 MathML 容器标签
['math', 'mfrac', 'mi', 'mn', 'mo', 'mrow', 'msqrt', 'mstyle']
));
$config->set('HTML.AllowedAttributes', array_merge(
$config->get('HTML.AllowedAttributes') ?? [],
// MathML 常用属性
['math.xmlns', 'math.display', 'mfrac.linethickness', 'mstyle.fontsize']
));
// 允许 MathML 命名空间
$config->set('Attr.AllowedNamespaces', [
'http://www.w3.org/1998/Math/MathML' => true
]);
// 创建 Purifier 实例
$purifier = new HTMLPurifier($config);
// 待处理的包含 MathML 的内容
$dirtyHtml = '<div>
<p>下面的公式展示了二次方程求根公式:</p>
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mstyle fontsize="1.2em">
<mrow>
<mi>x</mi>
<mo>=</mo>
<mfrac>
<mrow>
<mo>-</mo>
<mi>b</mi>
<mo>±</mo>
<msqrt>
<mrow>
<msup>
<mi>b</mi>
<mn>2</mn>
</msup>
<mo>-</mo>
<mn>4</mn>
<mi>a</mi>
<mi>c</mi>
</mrow>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mi>a</mi>
</mrow>
</mfrac>
</mrow>
</mstyle>
</math>
</div>';
// 净化内容
$cleanHtml = $purifier->purify($dirtyHtml);
echo $cleanHtml;上述代码中,我们首先保留了 HTML Purifier 默认允许的 HTML 元素和属性,在此基础上新增了 MathML 相关的标签和属性。同时启用了 MathML 的命名空间,确保带有命名空间的 <math> 标签不会被过滤。最后将待处理的包含 MathML 的 HTML 内容传入 purify 方法,得到净化后的安全内容。
进阶配置:支持更多 MathML 标签
如果需要支持更复杂的数学公式,比如矩阵、上下标等,可以扩展允许的标签和属性列表,示例如下:
<?php
require_once 'vendor/autoload.php';
$config = HTMLPurifier_Config::createDefault();
// 扩展允许的 MathML 标签,包含矩阵、上下标、操作符等
$mathmlTags = [
'math', 'mfrac', 'mi', 'mn', 'mo', 'mrow', 'msqrt', 'mstyle',
'msup', 'msub', 'msubsup', 'munder', 'mover', 'munderover',
'mtable', 'mtr', 'mtd', 'mfenced', 'mtext', 'mspace'
];
$config->set('HTML.AllowedElements', array_merge(
$config->get('HTML.AllowedElements') ?? [],
$mathmlTags
));
// 扩展允许的 MathML 属性
$mathmlAttrs = [
'math.xmlns', 'math.display', 'mfrac.linethickness', 'mstyle.fontsize',
'msup.base', 'msup.sup', 'munder.accentunder', 'mover.accent',
'mtable.columnspacing', 'mtd.columnspan'
];
$config->set('HTML.AllowedAttributes', array_merge(
$config->get('HTML.AllowedAttributes') ?? [],
$mathmlAttrs
));
// 允许 MathML 命名空间
$config->set('Attr.AllowedNamespaces', [
'http://www.w3.org/1998/Math/MathML' => true
]);
// 禁止自动添加 <p> 标签包裹内容,避免破坏 MathML 结构
$config->set('AutoFormat.AutoParagraph', false);
$purifier = new HTMLPurifier($config);
// 包含矩阵公式的测试内容
$dirtyHtml = '<math xmlns="http://www.w3.org/1998/Math/MathML">
<mtable>
<mtr>
<mtd><mi>a</mi></mtd>
<mtd><mi>b</mi></mtd>
</mtr>
<mtr>
<mtd><mi>c</mi></mtd>
<mtd><mi>d</mi></mtd>
</mtr>
</mtable>
</math>';
$cleanHtml = $purifier->purify($dirtyHtml);
echo $cleanHtml;这里额外添加了矩阵、上下标等常用 MathML 标签,同时关闭了自动段落功能,避免 HTML Purifier 自动添加 <p> 标签破坏 MathML 原有的嵌套结构。如果业务中需要支持更多特殊 MathML 标签,可以参考 MathML 规范补充到允许的标签列表中。
注意事项
- 只添加业务必需的 MathML 标签和属性,过多的允许规则会降低内容过滤的安全性,可能引入 XSS 风险。
- 如果网页中同时使用了 MathJax 等公式渲染库,需要确保净化后的 MathML 内容符合渲染库的要求,部分渲染库可能需要特定的属性或标签格式。
- 测试时需要验证各种边界情况,比如嵌套层级很深的 MathML 公式、包含特殊字符的公式内容,确保净化后公式仍能正常显示。
- 如果净化后的内容需要存储到数据库,建议先净化再存储,避免存储不安全的内容,同时减少每次展示时的净化开销。