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

XSLT实现XML中x元素空n属性的递增赋值问题

正确填充XML中空n属性的XSLT实现

问题背景

输入XML:

<div>  
  <p>  
    <x n="1"/>  
    <x n=""/>  
    <x n=""/>  
    <x n=""/>  
    <x n="190"/>  
    <x n=""/>  
    <x n=""/>  
  </p>
</div>

需求:将x元素的空n属性从最近的已有有效值开始递增填充,目标结果:

<div>  
  <p>  
    <x n="1"/>  
    <x n="2"/>  
    <x n="3"/>  
    <x n="4"/>  
    <x n="190"/>  
    <x n="191"/>  
    <x n="192"/>  
  </p>
</div>

原尝试的XSLT方案(仅部分生效):

<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" version="1.0" encoding="UTF-8" indent="yes"/>    
    <xsl:template match="@* | node()">    
        <xsl:copy>    
            <xsl:apply-templates select="@* | node()"/>    
        </xsl:copy>    
    </xsl:template>    
    <xsl:template match="x[@n = '']/@n">    
        <xsl:attribute name="n" select="preceding::x[number(@n)]/@n + 1"/>    
    </xsl:template>
</xsl:stylesheet>

原方案问题:XSLT基于原始节点树处理,而非处理后的结果。第二个空n的x能找到原始树中第一个有效值,但后续空节点的前序在原始树里仍无有效值,无法继续递增。

正确的XSLT实现

通过递归遍历并实时跟踪当前数值,实现连续递增填充:

<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" version="1.0" encoding="UTF-8" indent="yes"/>

    <!-- 身份模板:复制未特殊处理的节点和属性 -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 处理包含x元素的p节点,初始化数值并启动递归处理 -->
    <xsl:template match="p">
        <xsl:copy>
            <xsl:variable name="x-nodes" select="x"/>
            <!-- 初始化当前数值:取第一个x的有效值,无有效值则默认设为1 -->
            <xsl:variable name="initial-val" as="xs:integer">
                <xsl:choose>
                    <xsl:when test="$x-nodes[1]/@n != ''">
                        <xsl:sequence select="xs:integer($x-nodes[1]/@n)"/>
                    </xsl:when>
                    <xsl:otherwise>1</xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:call-template name="process-x">
                <xsl:with-param name="nodes" select="$x-nodes"/>
                <xsl:with-param name="current-val" select="$initial-val"/>
            </xsl:call-template>
        </xsl:copy>
    </xsl:template>

    <!-- 递归处理x节点的模板 -->
    <xsl:template name="process-x">
        <xsl:param name="nodes" as="element(x)*"/>
        <xsl:param name="current-val" as="xs:integer"/>

        <xsl:if test="$nodes">
            <xsl:variable name="current-node" select="$nodes[1]"/>
            <xsl:copy>
                <xsl:choose>
                    <!-- 节点n非空:复制属性,更新当前数值 -->
                    <xsl:when test="$current-node/@n != ''">
                        <xsl:attribute name="n" select="$current-node/@n"/>
                        <xsl:call-template name="process-x">
                            <xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
                            <xsl:with-param name="current-val" select="xs:integer($current-node/@n)"/>
                        </xsl:call-template>
                    </xsl:when>
                    <!-- 节点n为空:使用当前数值,递增加一 -->
                    <xsl:otherwise>
                        <xsl:attribute name="n" select="$current-val"/>
                        <xsl:call-template name="process-x">
                            <xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
                            <xsl:with-param name="current-val" select="$current-val + 1"/>
                        </xsl:call-template>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:copy>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

方案说明

  1. 身份模板保证XML原有结构不被破坏,仅处理需要修改的x元素。
  2. 针对p节点,先获取所有x节点序列,初始化当前数值为第一个x的有效值(无有效值则默认设为1,可按需调整)。
  3. 递归模板process-x逐个处理x节点:
    • 若当前节点n非空,直接复制属性并更新当前数值。
    • 若当前节点n为空,使用当前数值填充,然后将数值加1传递给下一个节点。
  4. 基于处理过程中的实时数值跟踪,而非原始节点树,实现连续递增填充。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:34:57