从 XSLT 中的字符代码创建文本

Creating text from character code in XSLT

我正在将文档从一种 XML 标准转换为另一种标准。要求之一是编号列表使用字母而不是罗马编号。我可以从列表位置创建 unicode,但似乎无法将它们插入 XML 输出。

也许我在这里没有看到明显的解决方案。在 JavaScript 中,我会使用 fromCharCode( ) 函数,但我还没有在 XSLT 中找到类似的选项。

我正在使用 XSL 2.0,但如果需要的话也可以使用 3.0 来简化操作。

我创建了一个简单的 XML 加 XSL 来显示我需要解决的问题。实际文件太大,无法在此处共享。

示例 XML 输入文档:

<doc>
    <p>Some text</p>
    <p>Some more text</p>
</doc>

所需输出:

<doc>
    <list>
        <list-item>
            <label>A</label>
            <p>Some text</p>
        </list-item>
        <list-item>
            <label>B</label>
            <p>Some more text</p>
        </list-item>
    </list>
</doc>

我试过这个:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">

<xsl:output method="xml" encoding="UTF-8"/>

<xsl:template match="/doc">
    <xsl:copy>
        <list>
            <xsl:apply-templates select="p"/>
        </list>
    </xsl:copy>
</xsl:template>

<xsl:template match="p">
    <xsl:variable name="number" as="xs:integer" select="position()"/>
    <list-item>
        <label>
            <xsl:value-of select="concat('&amp;#',$number + 65,';')" disable-output-escaping="yes"/>
        </label>
        <xsl:copy-of select="."/>
    </list-item>
</xsl:template>

</xsl:stylesheet>

我之前在其他生成的项目上使用过禁用输出转义(例如将 angular 括号放入 XML 输出),但似乎没有处理标准字符代码以同样的方式。上述 XSL 的输出如下所示:

doc>
<list>
    <list-item>
        <label>&#66;</label>
        <p>Some text</p>
    </list-item>
    <list-item>
        <label>&#67;</label>
        <p>Some more text</p>
    </list-item>
</list>
</doc>

有什么方法可以优雅地做到这一点(即我不必创建一个巨大的 xsl:choose 来调出每个可能的整数标签值,然后显式创建字母标签?

您可以使用 codepoints-to-string() 并将数字转换为字母。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/doc">
        <xsl:copy>
            <list>
                <xsl:apply-templates select="p"/>
            </list>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="p">
        <list-item>
            <label>
                <xsl:value-of select="codepoints-to-string(position() + 64)"/>
            </label>
            <xsl:copy-of select="."/>
        </list-item>
    </xsl:template>
    
</xsl:stylesheet>

或者您可以将 xsl:numbervalue="position()"format="A"

一起使用
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/doc">
        <xsl:copy>
            <list>
                <xsl:apply-templates select="p"/>
            </list>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="p">
        <list-item>
            <label>
                <xsl:number format="A" value="position()"/>
            </label>
            <xsl:copy-of select="."/>
        </list-item>
    </xsl:template>
    
</xsl:stylesheet>

最大 26 (='Z') 的快速解决方案是

<xsl:template match="p">
    <xsl:variable name="alphabet" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>    
    <xsl:variable name="number" as="xs:integer" select="position()"/>
    <list-item>
        <label><xsl:value-of select="substring($alphabet,$number,1)"/></label>
        <xsl:copy-of select="."/>
    </list-item>
</xsl:template>

输出如愿。
这可以通过使用 divxsl:if.

扩展到 26*26