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

如何用XSLT 1.0提取每个<one>节点下不同父节点的唯一state值?

解决XSLT 1.0中合并两类节点下值并去重的问题

我懂你现在的困扰:之前分开用Muenchian分组处理<one>直接子节点的<Maddress>和<co>子节点下的<Maddress>,结果合并后出现了重复的<state>值,比如第一个<one>里的ak会被输出两次。这是因为你把两类节点的分组拆成了独立的key,没有把所有目标<state>放在统一的分组逻辑里,而且没限定分组的范围是当前<one>节点。

核心思路

要解决这个问题,我们需要:

  • 把所有需要提取的<state>节点(包括<one>直接下的<Maddress>和<co>下的<Maddress>)统一纳入一个key的匹配范围
  • 分组时绑定到当前<one>节点的上下文,确保每个<one>内部的<state>值独立去重(不会和其他<one>的state混淆)

完整XSLT实现代码

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

    <!-- 定义key:将每个<one>节点的唯一标识与state值拼接作为分组键,确保每个one内部独立分组 -->
    <xsl:key name="state-by-one-and-value" 
             match="one/Maddress/address/state | one/co/Maddress/address/state"
             use="concat(generate-id(ancestor::one), '|', .)" />

    <!-- 根模板:触发对所有<one>节点的处理 -->
    <xsl:template match="/">
        <xsl:apply-templates select="filename/root/one" />
    </xsl:template>

    <!-- 处理每个<one>节点 -->
    <xsl:template match="one">
        <!-- 生成序号,比如1.、2. -->
        <xsl:number format="1." />
        <!-- 遍历当前one下所有唯一的state节点 -->
        <xsl:for-each select="(Maddress/address/state | co/Maddress/address/state)[generate-id() = generate-id(key('state-by-one-and-value', concat(generate-id(current()), '|', .))[1])]">
            <!-- 除了第一个元素,前面加逗号分隔 -->
            <xsl:if test="position() > 1">, </xsl:if>
            <xsl:value-of select="." />
        </xsl:for-each>
        <!-- 换行,让每个one的结果单独一行 -->
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

代码解释

  1. Key的定义:

    • match属性同时匹配两类<state>节点:one/Maddress/address/state和one/co/Maddress/address/state
    • use属性用concat(generate-id(ancestor::one), '|', .)把当前<one>节点的唯一ID和<state>的值拼接成分组键,这样每个<one>内部的相同<state>值会被分到同一组,不同<one>的相同值不会混淆。
  2. 节点的处理:

    • 用<xsl:number>生成你需要的序号格式
    • <xsl:for-each>筛选当前<one>下所有属于分组第一个节点的<state>,也就是去重后的唯一值
    • 用<xsl:if>处理逗号分隔,避免第一个元素前出现多余的逗号

测试结果

用你提供的输入XML运行这个XSLT,会得到和你期望一致的输出:

1.ak, vr, fg
2.pp, fg, ak

为什么之前的代码会出错?

你之前的代码定义了两个独立的key,分别处理两类<Maddress>的<state>,然后在同一个<one>模板里分开遍历这两组去重后的结果。这样一来,比如第一个<one>里直接的<Maddress>有ak,<co>下的<Maddress>也有ak,就会被分别输出,导致重复。而我们的方案把所有目标<state>放在同一个分组逻辑里,自然就能在<one>内部完成全局去重。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:20:13