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

XSLT实现:将单个属性拆分为带属性的多个元素

问题:拆分多rid的元素为独立元素

我有一段XML,其中的<xref>元素的rid属性包含多个交叉引用值,需要将其拆分为多个独立的<xref>元素,每个元素对应一个rid值。

输入XML

<p>Blah blah blah <xref ref-type="bibr" rid="ref004 ref005 ref006 ref007">4&#x2013;7</xref>.</p>

期望输出XML

<p>Blah blah blah <xref ref-type="bibr" rid="ref004">4</xref><xref
        ref-type="bibr" rid="ref005"/><xref ref-type="bibr" rid="ref006"/>&#x2013;<xref
        ref-type="bibr" rid="ref007">7</xref>.</p>

注意:中间两个交叉引用为空元素。

我使用了如下XSLT,但无法得到正确输出——它会将属性值作为元素内容插入:

错误的XSLT代码

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

<xsl:template match="xref">
    <xsl:variable name="rid" select="@rid"/>
    <xsl:choose>
        <xsl:when test="contains($rid, ' ')">
            <!-- Multiple references -->
            <xsl:variable name="refs" select="tokenize($rid, ' ')"/>
            <xsl:for-each select="$refs">
                <xsl:if test="position() &gt; 1">
                    <xsl:text> </xsl:text>
                </xsl:if>
                <xsl:variable name="refNum" select="substring-after(., 'ref')"/>
                <xsl:element name="xref">
                    <xsl:attribute name="ref-type">bibr</xsl:attribute>
                    <xsl:attribute name="rid">
                        <xsl:value-of select="concat('ref', $refNum)"/>
                    </xsl:attribute>
                    <xsl:value-of select="."/>
                </xsl:element>
            </xsl:for-each>
        </xsl:when>
        <xsl:otherwise>
            <!-- Single reference -->
            <xsl:element name="xref">
                <xsl:attribute name="ref-type">bibr</xsl:attribute>
                <xsl:attribute name="rid">
                    <xsl:value-of select="$rid"/>
                </xsl:attribute>
                <xsl:value-of select="."/>
            </xsl:element>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

修正后的XSLT解决方案

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

<xsl:template match="xref[@rid and contains(@rid, ' ')]">
    <!-- 拆分rid属性为单独的引用列表 -->
    <xsl:variable name="refs" select="tokenize(@rid, ' ')"/>
    <!-- 拆分原文本的起始和结束数字 -->
    <xsl:variable name="textParts" select="tokenize(normalize-space(.), '&#x2013;')"/>
    <xsl:variable name="startNum" select="$textParts[1]"/>
    <xsl:variable name="endNum" select="$textParts[2]"/>
    
    <xsl:for-each select="$refs">
        <xsl:variable name="pos" select="position()"/>
        <xsl:element name="xref">
            <!-- 复制原ref-type属性 -->
            <xsl:copy-of select="../@ref-type"/>
            <xsl:attribute name="rid" select="."/>
            <!-- 第一个元素用起始数字,最后一个用结束数字,中间为空 -->
            <xsl:if test="$pos = 1">
                <xsl:value-of select="$startNum"/>
            </xsl:if>
            <xsl:if test="$pos = count($refs)">
                <xsl:value-of select="$endNum"/>
            </xsl:if>
        </xsl:element>
        
        <!-- 在倒数第二个元素后插入连接符 -->
        <xsl:if test="$pos = count($refs) - 1">
            <xsl:text>&#x2013;</xsl:text>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

关键修正点

  • 解析原<xref>的文本内容,拆分出起始和结束数字,不再错误地将rid值作为元素内容
  • 根据每个拆分后<xref>的位置决定内容:第一个显示起始数字,最后一个显示结束数字,中间的为空元素
  • 在倒数第二个<xref>之后插入&#x2013;连接符,替代原代码中错误的空格分隔
  • 直接复制原<xref>的ref-type属性,避免硬编码,提升通用性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 12:52:47