【问题标题】:XSLT - Transform unicode charactersXSLT - 转换 unicode 字符
【发布时间】:2017-02-08 09:42:24
【问题描述】:

我有一个这样的xml,

<doc>
    <?PIValue  &#x00D2;&#x00D3;&#x00D4;&#x00D5;&#x00D6;&#x00D8; &#x00C0;&#x00C1;&#x00C2;&#x00C3;&#x00C4;&#x00C5;?>
    <p>&#x00D2;&#x00D3;&#x00D4;&#x00D5;&#x00D6;&#x00D8; &#x00C0;&#x00C1;&#x00C2;&#x00C3;&#x00C4;&#x00C5;</p>
</doc>

我对此 XML 进行了 XSLT 转换,如下所示,

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

    <xsl:template match="doc">
        <doc>
            <xsl:apply-templates/>
            <p2><xsl:value-of select="processing-instruction('PIValue')"/></p2>
        </doc>
    </xsl:template>

    <xsl:template match="p">
        <p1>
            <xsl:apply-templates/>
        </p1>
    </xsl:template>

上面的输出把这个转换成这个,

<doc>
    <?PIValue &#x00D2;&#x00D3;&#x00D4;&#x00D5;&#x00D6;&#x00D8; &#x00C0;&#x00C1;&#x00C2;&#x00C3;&#x00C4;&#x00C5;?>
    <p1>ÒÓÔÕÖØ ÀÁÂÃÄÅ</p1>
    <p2>&amp;#x00D2;&amp;#x00D3;&amp;#x00D4;&amp;#x00D5;&amp;#x00D6;&amp;#x00D8; &amp;#x00C0;&amp;#x00C1;&amp;#x00C2;&amp;#x00C3;&amp;#x00C4;&amp;#x00C5;</p2>
</doc>

如您所见,Unicode 字符在 &lt;p&gt; 元素内,在输出中显示为普通文本(在 &lt;p1&gt; 元素内)。但处理指令中的相同 unicode 字符未显示,因为输出中有相关字符(在 &lt;p2&gt; 元素内)。

如何更改我的转换以在元素中显示文本字符串。

expected output,

<doc>
    <?PIValue &#x00D2;&#x00D3;&#x00D4;&#x00D5;&#x00D6;&#x00D8; &#x00C0;&#x00C1;&#x00C2;&#x00C3;&#x00C4;&#x00C5;?>
    <p1>ÒÓÔÕÖØ ÀÁÂÃÄÅ</p1>
    <p2>ÒÓÔÕÖØ ÀÁÂÃÄÅ</p2>
</doc>

【问题讨论】:

  • 好问题,但没有简单的解决方案,因为输入中的p 元素内容中的字符引用只是由XML 解析器转换为相应的字符。 pi 内容不会发生这种情况,因为那是字符内容。您具体使用哪种 XSLT 处理器?
  • @MartinHonnen,我正在使用 XSLT 2.0

标签: xml xslt unicode xslt-2.0


【解决方案1】:

在 XML 中,字符引用(如&amp;#xd2;)在元素和属性内容中被识别,但在处理指令或 cmets 中不被识别。因此,在您的处理指令中,字符串 &amp;#x00D2; 只是一个 8 个字符的字符串,而不是对单个字符 xD2 的引用。

如果您想将 &amp;#x00D2; 字符串解释为字符引用,那么您可以将它们提交给 XML 解析器(正如 Martin Honnen 建议的那样),或者您可以在自己的代码中“手动”解析它们。没那么难:xsl:analyze-string 会提取'00D2' 部分,写一个递归函数将十六进制转换为整数相当简单,然后最后一部分是调用 codepoints-to-string 将整数代码转换为字符(=长度为 1 的字符串)。

【讨论】:

    【解决方案2】:

    如果您可以切换到 XSLT 3.0,您可以使用

    <?xml version="1.0" encoding="UTF-8" ?>
    <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
    
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="doc">
            <doc>
                <xsl:apply-templates/>
                <p2><xsl:value-of select="parse-xml-fragment(processing-instruction('PIValue'))"/></p2>
            </doc>
        </xsl:template>
    
        <xsl:template match="p">
            <p1>
                <xsl:apply-templates/>
            </p1>
        </xsl:template>
    </xsl:transform>
    

    【讨论】:

    • 感谢您的回答。但我想在 XSLT 2.0 中做到这一点。 XSLT 2.0 中没有任何直接的方法可以做到这一点吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 2015-11-24
    • 2014-04-14
    • 2023-03-25
    • 2010-10-08
    相关资源
    最近更新 更多