You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Saxon9将UTF-8 XML转win-1251 CSV报十进制160字符编码错误

UTF-8编码XML转windows-1251编码CSV报字符不支持错误

问题现象

将UTF-8编码的XML转换为win-1251(windows-1251)编码的CSV文件时,程序抛出如下错误:

net.sf.saxon.trans.DynamicError: Output character not available in this encoding (decimal 160)

已确认报错原因:XML文本中存在十进制编码为160的字符,Saxon 9.1.0.8版本判定该字符不在win-1251编码的支持范围内。
此前曾尝试在XSLT转换前预处理XML清理非法字符,但方案未生效,预处理代码如下:

Charset charset = Charset.forName("windows-1251");
        CharsetDecoder decoder = charset.newDecoder();
        CharsetEncoder encoder = charset.newEncoder();
        encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
        String result = s;

        try {
            ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(s));
            CharBuffer cbuf = decoder.decode(bbuf);
            result = cbuf.toString();
        } catch (CharacterCodingException cce) {
            log.error("Exception during character encoding/decoding: " + cce.getMessage());
        }

相关配置与执行信息

  • 转换执行命令:
java -cp saxon-9.1.0.8.jar net.sf.saxon.Transform -t -s:myxml.xml -xsl:myxsl.xsl -o:result.csv
  • 执行后完整错误日志:
Saxon 9.1.0.8J from Saxonica
Java version 1.8.0_333
Warning: at xsl:stylesheet on line 11 column 81 of myxsl.xsl:
  Running an XSLT 1.0 stylesheet with an XSLT 2.0 processor
Stylesheet compilation time: 378 milliseconds
Processing file:/D:/111/myxml2.xml
Building tree for file:/D:/111/myxml2.xml using class net.sf.saxon.tinytree.TinyBuilder
Tree built in 4 milliseconds
Tree size: 46 nodes, 0 characters, 99 attributes
Loading net.sf.saxon.event.MessageEmitter
Error at xsl:value-of on line 46 of myxsl.xsl:
  Output character not available in this encoding (decimal 160)
  at xsl:apply-templates (file:/D:/111/my/myxsl.xsl#66)
     processing /blocks/table[1]/head[1]/row[1]/col[2]
  at xsl:apply-templates (file:/D:/111/myxsl.xsl#73)
     processing /blocks/table[1]/head[1]/row[1]
  at xsl:apply-templates (file:/D:/111/myxsl.xsl#32)
     processing /blocks/table[1]/head[1]
  at xsl:apply-templates (file:/D:/111/myxsl.xsl#24)
     processing /blocks/table[1]
  in built-in template rule
Transformation failed: Run-time errors were reported
  • 使用的XSL样式表示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE csv-style [
<!ENTITY semicolons     ';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;'>
<!ENTITY commas         ',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'>
]>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" >
<xsl:output method="text" indent="no" omit-xml-declaration="yes" encoding="windows-1251"/>

<xsl:param name="delim">semicolon</xsl:param>
<xsl:param name="showHead">yes</xsl:param>
<xsl:variable name="delimStr">
    <xsl:choose>
        <xsl:when test="$delim = 'comma'">&commas;</xsl:when>
        <xsl:otherwise>&semicolons;</xsl:otherwise>
    </xsl:choose>
</xsl:variable>

<xsl:template match="blocks">
    <xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="description|pair|foot|body/table/head">
<!-- don't do anything just skip it-->
</xsl:template>

<xsl:template match="table">
    <xsl:apply-templates select="table|head|body"/>
</xsl:template>

<xsl:template match="col">
    <xsl:if test="position()=1">
        <xsl:value-of select="substring($delimStr, 1, @id - 1)"/>
    </xsl:if>
<xsl:choose>
    <xsl:when test="@value">
        <xsl:text>&quot;</xsl:text><xsl:variable name="escape">
        <xsl:call-template name="_replace_string">
            <xsl:with-param name="string" select="@value" />
        </xsl:call-template>
    </xsl:variable>
    <xsl:value-of select="$escape" /><xsl:text>&quot;</xsl:text>

    </xsl:when>
    <xsl:otherwise>
        <xsl:text>""</xsl:text>
        <xsl:apply-templates/>
    </xsl:otherwise>
</xsl:choose>
<xsl:choose>
    <xsl:when test="position()=last()">
        <xsl:value-of select="substring($delimStr, 1, ancestor::table[1]/@colNum - @id)"/>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="substring($delimStr, 1, following-sibling::col[1]/@id - @id)"/>
    </xsl:otherwise>
</xsl:choose>
</xsl:template> <!-- col -->

<xsl:template match="row">
    <xsl:if test="col[@value][1]">
        <xsl:apply-templates select="col"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:if>
</xsl:template>

<xsl:template match="head">
    <xsl:if test="$showHead = 'yes'">
        <xsl:apply-templates select="*"/>
    </xsl:if>
</xsl:template>

<xsl:template match="body">
    <xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template name="_replace_string">
    <xsl:param name="string" select="''"/>
    <xsl:variable name="find">"</xsl:variable>
    <xsl:variable name="replace">""</xsl:variable>
    <xsl:choose>
        <xsl:when test="contains($string,$find)">
            <xsl:value-of select="concat(substring-before($string,$find),$replace)"/>
            <xsl:call-template name="_replace_string">
                <xsl:with-param name="string" select="substring-after($string,$find)"/>
                <xsl:with-param name="find" select="$find"/>
                <xsl:with-param name="replace" select="$replace"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$string"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>
  • 待转换的XML样例:
<?xml version="1.0" encoding="UTF-8" ?><blocks type="report"><functions><func num="4" text=" nameOf_10031"></func><func num="5" text="name Of_10071"></func><func num="6" text="name Of_10006"></func></functions><description name="[441] testesttest with 160 "><rows total="44" start="1" end="44" show-data="yes"></rows><columns count="10"><column id="1" type="4" position="1" width="" format="&apos;dd.mm.yyyy&apos;"></column><column id="2" type="4" position="2" width="" format="&apos;dd.mm.yyyy&apos;"></column><column id="3" type="3" position="3" width=""></column><column id="4" type="2" position="4" width=""></column><column id="5" type="2" position="5" width=""></column><column id="6" type="2" position="6" width=""></column><column id="7" type="2" position="7" width=""></column><column id="8" type="2" position="8" width=""></column><column id="9" type="2" position="9" width=""></column><column id="10" type="2" position="10" width=""></column></columns></description><pair name="ReportName" value="test test test "></pair><table colNum="10" id="12561"><head><row><col id="1" value="test test test"></col><col id="2" value=" test test test"></col><col id="3" value="test test test"></col><col id="4" value="test test test"></col><col id="5" value="test test test"></col><col id="6" value="test test test"></col><col id="7" value="test test test"></col><col id="8" value=" test test test"></col><col id="9" value="test test test"></col><col id="10" value="test test test"></col></row></head><body><row num="1"><col id="1" value="01.07.2006"></col><col id="2"></col><col id="3" value="53363"></col><col id="4" value="65187" record-id="65187"></col><col id="5" value="53363" record-id="53368"></col><col id="6" value="test test test" record-id="1974"></col><col id="7"></col><col id="8"></col><col id="9" value="test test test"></col><col id="10"></col></row></body></table></blocks>

测试确认使用Saxon-HE-10.3等新版本Saxon时转换无异常,但受环境限制无法升级Saxon版本,寻求该问题的最优解决方式。


内容的提问来源于stack exchange,提问作者Thomazzz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 00:21:55