XSLT - 转换 unicode 字符

XSLT - Transform unicode characters

我有一个这样的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>

如您所见,<p> 元素中的 unicode 字符在输出中显示为普通文本(在 <p1> 元素中)。但是处理指令中的相同 unicode 字符没有显示,因为输出中有相关字符(在 <p2> 元素内)。

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

expected output,

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

如果可以切换到 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>

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

的引用

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