使用 basex 解析带有扩展 unicode 字符的 html 时出错

问题描述

我在使用 basex html 解析器解析带有扩展 unicode 字符的 html 时遇到了问题。是否可以让解析器支持特殊字符?

代码

let $htmlRaw := '<span class="eqn">&#120746; + &#120747; = &#120748;</span>'
let $htmlParsed := html:parse($htmlRaw,map { 'encoding': 'utf-8'})
return (
  'INPUT',$htmlRaw,'OUTPUT',$htmlParsed
)

输出

INPUT
<span class="eqn">? + ? = ?</span>
OUTPUT
<html>
  <body>
    <span class="eqn">?? + ?? = ??</span>
  </body>
</html>

错误似乎与 basex 不支持的 tagsoup 库的 output-encoding 参数有关。

例如:-

$ echo "<span class="eqn">&#120746; + &#120747; = &#120748;</span>" | java -jar tagsoup-1.2.1.jar --html

<html><body><span class="eqn">&#55349;&#57258; + &#55349;&#57259; = &#55349;&#57260;</span>
</body></html>

$ echo "<span class="eqn">&#120746; + &#120747; = &#120748;</span>" | java -jar tagsoup-1.2.1.jar --html --output-encoding=utf-16
<html><body><span class="eqn">? + ? = ?</span>
</body></html>

解决方法

如果我在 BaseX 的 HtmlParser.java (https://github.com/martin-honnen/basex/commit/4711a390e4069d363243f48c95456544916f40f7) 中添加 opt(writer,"encoding",Strings.UTF8); 作为第 156 行,问题似乎消失了。但是,我不确定这是修复它的正确方法。

问题的根源似乎是两个问题,TagSoup,在没有将 XMLWriter 的输出编码设置为任何 Unicode 编码(如 UTF-8 或 UTF-16)的情况下,输出两个数字字符引用,代表一个 Unicode 字符之外的BMP。

因此,您必须将 UTF-8 或 UTF-16 设置为 TagSoup 的 XMLWriter 的输出编码,然后它切换到 Unicode 模式并只输出字符而不是字符引用,这两种编码 TagSoup 的 XMLWriter 似乎都适合StringWriter BaseX 设置的字符。

此外,BaseX 的内部 String 到 byte[] 转换似乎需要 UTF-8 编码的字符串,不确定为什么在 Java 平台上会出现这种情况,但 token 函数将工作委托给 {{1} } 函数。

这样,HtmlParser 中的修复方法似乎是设置 utf8

,

Martin Honnen 的回答很好地描述了这个问题。修复了错误的新快照可用 (https://files.basex.org/releases/latest/)。

如果您将 HTML 输入作为字符串传递,则它已经以 UTF-8 编码;但如果您有二进制输入,则 encoding 选项会很有帮助:

let $data := file:read-binary('my.html')
return html:parse($data,map { 'encoding': 'CP1252'})