我编写了一个 XSLT 来处理一组 XML。
XSLT 处理良好,但这些 XML 具有不同的编码集。目前我正在使用输出标签,如图所示:
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
但这会强制将编码更改为UTF-8
,但我需要与实际 XML 文档中存在的值相同的值。
我怎样才能得到这个?
但这会强制将编码更改为 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=['""]([a-zA-Z0-9-]+)['""].*$"
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 处理器。