【问题标题】:Preserve xml encoding XSLT保留 xml 编码 XSLT
【发布时间】:2015-08-14 10:37:58
【问题描述】:

我编写了一个 XSLT 来处理一组 XML。
XSLT 处理良好,但这些 XML 具有不同的编码集。目前我正在使用如图所示的输出标签:

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

但这会强制将编码更改为UTF-8,但我需要与实际 XML 文档中相同的值。
我怎样才能得到这个?

【问题讨论】:

  • 没有纯粹的 XSLT 方法可以实现这一点,因为 XSLT 处理器不知道输入的编码。您在哪个环境(例如 .NET、Java)中使用 XSLT?您需要编写代码让 XML 解析器确定输入的编码,然后操作 XSLT 结果序列化的输出编码。
  • @MartinHonnen:这取决于您所说的“纯”。实际上,您可以在 XSLT 2.0 和 3.0 中做到这一点,而无需借助扩展功能。有了 XSLT 1.0(此处未指定),情况就不同了。

标签: xml xslt encoding preserve


【解决方案1】:

但这会强制将编码更改为 UTF-8,但我需要与实际 XML 文档中相同的值。

从 XML 的角度来看,使用什么编码没有区别,只要正确的字符被转义(这是由 XSLT 处理器为您完成的)。每个 XML 处理器都需要支持 UTF-8、UTF-16 和 US-ASCII。例如,如果您的 XML 必须使用会与 UTF 编码混淆的旧技术(例如一些较旧的 FTP 系统)传输,则可以使用后者。

也就是说,在 XSLT 2.0 和 3.0 中,有一些方法可以通过简单地使用 xsl:result-document 来动态执行此操作,还有一个技巧是将 XML 加载为未解析的文本:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:f="http://example.com/functions">

    <xsl:template match="/">
        <xsl:result-document href="output-filename" encoding="{f:get-encoding(.)}">
            <!-- your code -->
        </xsl:result-document>
    </xsl:template>

    <xsl:function name="f:get-encoding">
        <xsl:param name="node" />
        <xsl:variable name="regex">^.*encoding=['"]([a-zA-Z0-9-]+)["'].*$</xsl:variable>
        <xsl:value-of select="replace(tokenize(unparsed-text($node/base-uri()), '\n')[1], $regex, '$1')"/>        
    </xsl:function>

 </xsl:stylesheet>

甚至在 xsl:output 上使用 XSLT 3.0

简而言之,仅仅几行代码就展示了很多 XSLT、XPath 和 XDM 的新概念:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:param name="input-url" static="yes" select="'yourinput.xml'" />

    <xsl:variable name="get-encoding" static="yes" select='
        let $regex := "^.*encoding=[&apos;""]([a-zA-Z0-9-]+)[&apos;""].*$"
        return function($n) {
            replace(tokenize(unparsed-text($n), "\n")[1], $regex, "$1")
        }' />

    <!-- a shadow attribute is replaced with the actual attribute by the same name -->
    <xsl:output _encoding="{$get-encoding($input-url)}" />

    <xsl:template match="/">
        <!-- your code here -->
        <result />
    </xsl:template>

</xsl:stylesheet>

这段代码使用Exselt 可以正常运行,但我的Saxon 版本(还)不支持它(它不允许在静态表达式中使用unparsed-text),但我确信'很快就会出现,或者是某种可配置的东西。我没有测试其他 XSLT 处理器。

【讨论】:

  • 使用 &lt;xsl:variable name="regex"&gt;^.*encoding=['"]([a-zA-Z0-9-]+)["'].*$&lt;/xsl:variable&gt; 的基于正则表达式的编码解析是否适用于 Saxon?我在 Windows 上使用 Saxon 9.6 HE 和 Java 1.8 尝试了您的示例,但它在 xsl:result-document 上抛出了诸如 SESU0007: Invalid encoding name: &lt;?xml version="1.0" encoding="ISO-8859-1"?&gt; 之类的错误,这意味着未提取编码名称。看起来.* 不匹配的字符串中有一个尾随空格0xD 字符。
猜你喜欢
  • 2013-03-19
  • 2014-07-11
  • 1970-01-01
  • 1970-01-01
  • 2016-11-20
  • 2016-03-03
  • 2019-12-17
  • 2018-06-18
  • 2015-06-30
相关资源
最近更新 更多