ISO-8859-1 字符在 XSLT 属性中被视为 UTF-8

Posted

技术标签:

【中文标题】ISO-8859-1 字符在 XSLT 属性中被视为 UTF-8【英文标题】:ISO-8859-1 characters treated as UTF-8 in XSLT attributes 【发布时间】:2012-02-16 07:10:48 【问题描述】:

如果我确保始终使用 ISO-8859-1 作为编码,则 ¬ 字符(ISO-8859-1 中的 0xAC)适用于普通文本。但是,在属性中使用它时,它会转义为:%C2%AC。我知道它需要为 url 转义,但不是为什么它以与 UTF-8 相同的方式转义它,而不仅仅是%AC,因为我期望它对 ISO-8859-1 进行转义。

由于转义在输出 html 文件中,唯一的结论是 xslt 处理器是原因。

例子:

input.xml stylesheet.xslt makefile

对我来说生成:

output.html

使用 xsltproc 生成输出,针对 libxml 20707、libxslt 10126 和 libexslt 815 编译。这是在 #! Linux (amd64)。我也尝试过:xmlstarlet tr(也使用 libxml)、xalan 和 google chrome(通过添加 <?xml-stylesheet ... >,请参阅 input_ss.xml 标签),结果相同。

Opera 根本不会转义它,它允许 ¬ 在 url 和属性中按字面意思使用。

这是 xslt 的标准行为还是属性转义方式中的错误?无论哪种方式,除了用 %AC 替换 %C2%AC 之外,还有其他解决方案吗?记住,对于其他有效的 ISO-8859-1 和在 UTF-8 中无效的字符,几乎可以肯定是相同的。

【问题讨论】:

【参考方案1】:

这里使用了 3 种不同的基于文本的技术,XML、HTML 和 URI。

所有这些都有转义机制 - 也就是说,使用文本来指示在给定上下文中不可能或难以指示的其他文本的方法。

无符号字符¬ (U+00AC) 可以在前两个中转义为¬或 ¬ 可能带有一些前导零,在 XML 和 HTML 中(¬ 也适用于 HTML)。无论 XML 或 HTML 采用何种编码,都将使用此转义,因为它与字符 ¬ 相关,而不是与给定字符编码中的八位字节集相关 - 实际上,我们通常只会在以下情况下使用它正在使用的编码中没有这样的八位组。

在这种情况下,这是不必要的,因为输出采用字符编码,无需对其进行转义,因此在源代码中您可以看到 The ¬ character 未转义。

此 HTML 包含 URI 的文本。 HTML 的编码与此无关,因为编码是我们将 HTML 的文本从一台机器获取到另一台机器的方式,但是当解析 HTML 以读取此 URI 时,我们已经过了那个点并且正在处理在文本级别使用一些文本 - 也就是说,它不再具有编码。

现在,URI 有自己的转义机制。这必须在 ¬ 的情况下使用,因为它不是 URI 中允许的字符(与 IRI 相对)。遗憾的是,与 XML 和 HTML 中的转义不同,这些转义基于给定编码中的八位字节,而不是字符本身的代码点。

现在很容易将其视为一个错误,但 URI 是在 1994 年指定的,而正式的工作可以追溯到 1989/1990 年,而 Unicode 1.0 于 1991 年发布,直到 1996 年才具有开创性的 2.0,所以事后诸葛亮比 URI 的发明者有更多的好处。 (HTML 多年前也有同样的问题,但它的编码格式使它更容易解决这个问题,而没有那么多的向后兼容性问题。

那么,我们应该对这些八位字节使用什么编码?原始规范未定义,但实际上唯一可能的选择是 UTF-8。它是唯一一种编码,可以为那些通常用于 URI 特殊字符的转义符提供 0x20 - 0x7F 范围内的转义符,同时还覆盖所有 UCS。

也没有办法表明另一种选择可能更合适。请记住,我们在文本级别上工作,因此您对 ISO-8859-1 的使用完全无关紧要。即使我们在解析 HTML 时跟踪编码,URI 也会以与文档无关的方式被使用,所以我们仍然无法使用它。总之,如果我们必须使用基于八位字节的编码,并且我们必须保持 ASCII 范围内的字符与它们在 ASCII 中的八位字节匹配,那么编码的唯一可能基础是 UTF-8。

因此,¬any URI 中的转义必须始终为 %C2%AC

可能有一些遗留系统期望 URI 使用其他编码,但解决方案是修复损坏的位,而不是修复工作的位,所以如果某些东西期望 ¬%AC,那么就抓住它关闭通过将%C2%AC 转换为接近其用途(如果它本身输出%AC,那么您当然需要在它到达外界之前将其修复为%C2%AC)。

【讨论】:

【参考方案2】:

XSLT 规范规定,在序列化 URI 值属性时,所有非 ASCII 字符都使用表示字符的 UTF-8 八位字节的 %HH 转义进行转义。虽然过去使用过其他编码的 %HH 转义,但现在已不再使用。这完全独立于文档本身的编码。

【讨论】:

很好的答案,但乔恩第一个到达那里。

以上是关于ISO-8859-1 字符在 XSLT 属性中被视为 UTF-8的主要内容,如果未能解决你的问题,请参考以下文章

如何通过abap中的XSLT程序读取XML文件的属性

在 Python 中使用 ISO 8859-1 编码字符

Python ISO-8859-1 编码

如何在 Java 中的 ISO-8859-1 和 UTF-8 之间进行转换?

将字符串从 UTF-8 转换为 ISO-8859-1

如何使用正确的字符编码在 jQueryMobile 1.3.1 中通过 AJAX 加载 ISO-8859-1 内容?