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

使用XSLT Muenchian方法提取节点属性值并去重的问题

解决XSLT中按Product节点独立获取去重@value属性的问题

嘿,我来帮你搞定这个需求!首先得指出你现有代码里的几个关键问题,然后给你一个能实现目标的可行方案:

需求回顾

你需要针对每个独立的<Product>节点,获取它祖先、自身及所有后代节点的@value属性值,去重后输出成指定的<values>标签格式,而且不能用//选择器,必须基于Product节点的轴来处理。

现有代码的问题

  1. Key匹配对象错误:你定义的<xsl:key>匹配的是value元素,但我们要处理的是@value属性,二者完全不匹配;
  2. 无效的sortedvalues节点:你的代码里用到了sortedvalues,但你的XML中根本不存在这个节点,导致key的索引和排序条件全部失效;
  3. 未针对单个Product独立处理:当前逻辑没有绑定到每个Product的上下文,会导致全局去重,不符合你要每个Product输出自身去重值的需求。

另外,你的原始XML存在标签未闭合的问题,我先帮你修正为可正常解析的版本:

<Root> 
  <something value="asd"></something> 
  <something value="dsa"></something> 
  <Product> 
    <something value="asd"></something> 
    <something value="dsa"></something> 
    <something value="asd"></something> 
    <anothernode> 
      <something value="qwe"></something> 
    </anothernode> 
    <anothernode2> 
      <something value="ewq"></something> 
    </anothernode2> 
    <something value="ewq"></something> 
  </Product> 
  <Product> 
    <something value="asd"></something> 
    <something value="dsa"></something> 
    <something value="asd"></something> 
    <anothernode> 
      <something value="qwe"></something> 
    </anothernode> 
    <anothernode2> 
      <something value="ewq"></something> 
    </anothernode2> 
    <something value="ewq"></something> 
  </Product> 
</Root>

可行的XSLT解决方案

下面的代码完全符合你的要求,每个Product节点独立处理,基于轴获取属性并去重:

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

  <!-- 为当前Product上下文的@value属性创建key,按属性值分组 -->
  <xsl:key name="unique-values" match="ancestor-or-self::*/@value | descendant-or-self::*/@value" use="." />

  <!-- 从根节点开始,只处理每个Product节点 -->
  <xsl:template match="/Root">
    <xsl:apply-templates select="Product"/>
  </xsl:template>

  <!-- 处理单个Product节点 -->
  <xsl:template match="Product">
    <Product>
      <!-- 筛选当前Product下的唯一@value值:只保留每组的第一个元素 -->
      <xsl:for-each select="(ancestor-or-self::*/@value | descendant-or-self::*/@value)[generate-id() = generate-id(key('unique-values', .)[1])]">
        <!-- 按属性值排序,让输出更整洁 -->
        <xsl:sort select="."/>
        <values><xsl:value-of select="."/></values>
      </xsl:for-each>
    </Product>
  </xsl:template>

  <!-- 忽略空白文本节点,避免输出多余内容 -->
  <xsl:template match="text()"/>
</xsl:stylesheet>

代码说明

  • Key的作用:unique-valueskey会把当前Product上下文里所有符合条件的@value属性按值分组,相同值会被归为一组;
  • Product节点处理:对每个Product,先输出<Product>标签,再通过generate-id()判断是否是每组的第一个元素,从而实现去重;
  • 排序优化:加入<xsl:sort>让输出的<values>按字母顺序排列,和你期望的输出一致;
  • 清理输出:最后一个模板用来忽略XML里的空白文本,避免输出多余的换行或空格。

用这个代码处理修正后的XML,就能得到你想要的输出:

<Product>
  <values>asd</values>
  <values>dsa</values>
  <values>ewq</values>
  <values>qwe</values>
</Product>
<Product>
  <values>asd</values>
  <values>dsa</values>
  <values>ewq</values>
  <values>qwe</values>
</Product>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:43:42