删除不在指定XSLT编码中的字符

时间:2014-03-14 07:21:06

标签: xml xslt encoding character-encoding

我正在尝试将 UTF-8 xml 源文件转换为 iso-8859-1 xml 目标文件。 我希望 XSLT 删除 iso-8859-1 中无效的所有字符。有可能吗?

理想的方法是接收目标编码作为参数,删除有关此编码的所有无效字符,并使用该参数在xsl:output tag中设置编码属性。

我对包含中文字符的文件执行了测试,我的 XSLT 包含

<xsl:output method="xml" encoding="iso-8859-1" indent="yes" />

但中文字符转换为&amp;#20320 ;

提前致谢。

3 个答案:

答案 0 :(得分:1)

假设XSLT 1.0:
这是可能的,但相当乏味。您需要列出集合中的所有字符,然后在输出到结果树的每个文本节点上使用translate()函数(两次)。例如,这个样式表:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:param name="charset" select="'1234567890'" />

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="text()">
    <xsl:value-of select="translate(., translate(., $charset, ''), '')"/>
</xsl:template>

</xsl:stylesheet>

应用于以下输入时:

<input>
    <para>John has 3 apples.</para>
    <para>Eve has 2 oranges.</para>
</input>

将导致:

<?xml version="1.0" encoding="UTF-8"?>
<input>
  <para>3</para>
  <para>2</para>
</input>

答案 1 :(得分:1)

XSL输出编码确定输出文件所在的编码

它保证写入输出文件/流的字符不在定义的字符范围之外,在本例中为iso-8859-1。并且字符串'&#20320;'在该范围内,即使它所代表的字符(U + 4F60,你)不是。

<output charset="...">指令切换字节编码(例如'你'在UTF-8中为0xE4 0xBD 0xA0,在UTF-16中为0x60 0x4F但如果不可能它不会破坏你的文本,也就是说它不会在输出中替换输入中的中文字符(甚至更糟,没有)。

它尝试使用定义良好的编码方案来保留字符:编号的字符实体。显示数据的用户代理可以将其显示为问号,如果具有该功能,则可以将其显示为原始字符。

以下XML:

<?xml version="1.0" encoding="iso-8859-1"?>
<test>&#20320;</test>

<?xml version="1.0" encoding="UTF-8"?>
<test>你</test>

都显示为

<test>你</test>

在我的浏览器中,你的XSLT处理器所做的事实上是正确的事情。想想你真的想要丢失那些角色。

答案 2 :(得分:1)

对于iso-8859-1,您可以

replace($x, '[^&#x1;-&#xff;]', '')

但这并不能概括为其他编码。

如果您正在使用Saxon,那么我建议您自定义序列化程序(您可以设置自己的SerializerFactory,它可以创建一个包含您自己的XMLEmitter的管道,它可以将标准XMLEmitter子类化为省略不在选中的字符编码而不是转义它们。)

或者,对输出进行后处理(例如使用Perl或Awk)以删除所有数字字符引用。

然而,不仅如此,我还会质疑这一要求。你想做什么似乎不是一件好事。