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

XSLT 1.0条件标签处理:仅首次同名attr保留<remove-all-values>

问题:XSLT 1.0 实现同名属性仅首次保留<remove-all-values>标签

源XML文档

<instance class-name="Deelnemer">
  <attr attr-name="achternaam">
       <value>McFly</value>
  </attr>
  <attr attr-name="geslacht">
       <value>MAN</value>
  </attr>
  <attr attr-name="geboortedatum">
       <value>1968-03-14</value>
  </attr>
  <attr attr-name="verzorgers">
       <value>{"uuid":"f5a8fecd-7ea6-499e-a8a6-c6eb20e582b8","volgnummer":1}</value>
  </attr>
  <attr attr-name="verzorgers">
       <value>{"uuid":"54748d2b-b2bf-4362-8520-4c4827a6660c","volgnummer":2}</value>
  </attr>
</instance>

期望转换结果

<modify-attr attr-name="achternaam">
  <remove-all-values/>
  <add-value>
    <value>McFly</value>
  </add-value>
</modify-attr>
<modify-attr attr-name="geslacht">
  <remove-all-values/>
  <add-value>
    <value>MAN</value>
  </add-value>
</modify-attr>
<modify-attr attr-name="geboortedatum">
  <remove-all-values/>
  <add-value>
    <value>1968-03-14</value>
  </add-value>
</modify-attr>
<modify-attr attr-name="verzorgers">
  <remove-all-values/>
  <add-value>
    <value>{"uuid":"f5a8fecd-7ea6-499e-a8a6-c6eb20e582b8","volgnummer":1}</value>
  </add-value>
</modify-attr>
<modify-attr attr-name="verzorgers">
  <add-value>
    <value>{"uuid":"54748d2b-b2bf-4362-8520-4c4827a6660c","volgnummer":2}</value>
  </add-value>
</modify-attr>

可行XSLT 1.0解决方案

提供两种实现思路,均能满足需求:

方法1:使用preceding-sibling直接判断

通过检查当前<attr>节点之前是否存在同名节点,决定是否输出<remove-all-values>标签:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

  <!-- 匹配根节点,遍历所有attr子节点 -->
  <xsl:template match="/instance">
    <xsl:apply-templates select="attr"/>
  </xsl:template>

  <!-- 处理每个attr节点 -->
  <xsl:template match="attr">
    <modify-attr attr-name="{@attr-name}">
      <!-- 仅当前是第一个同名attr时,输出remove-all-values -->
      <xsl:if test="not(preceding-sibling::attr[@attr-name = current()/@attr-name])">
        <remove-all-values/>
      </xsl:if>
      <add-value>
        <xsl:copy-of select="value"/>
      </add-value>
    </modify-attr>
  </xsl:template>
</xsl:stylesheet>

方法2:使用key分组(更高效)

对于节点数量较多的场景,key分组利用索引机制,性能更优,通过判断当前节点是否为分组内第一个节点控制标签输出:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

  <!-- 按attr-name分组定义key -->
  <xsl:key name="attrGroup" match="attr" use="@attr-name"/>

  <!-- 匹配根节点,遍历所有attr子节点 -->
  <xsl:template match="/instance">
    <xsl:apply-templates select="attr"/>
  </xsl:template>

  <!-- 处理每个attr节点 -->
  <xsl:template match="attr">
    <modify-attr attr-name="{@attr-name}">
      <!-- 判断是否为当前分组的第一个节点 -->
      <xsl:if test="generate-id() = generate-id(key('attrGroup', @attr-name)[1])">
        <remove-all-values/>
      </xsl:if>
      <add-value>
        <xsl:copy-of select="value"/>
      </add-value>
    </modify-attr>
  </xsl:template>
</xsl:stylesheet>

说明

  • 方法1逻辑直观,但节点数量较多时,每次判断需遍历前置节点,性能会下降。
  • 方法2通过索引分组,判断效率更高,适合处理大型XML文档。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 23:48:22