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

如何在XSLT中使用带有两个匹配条件的键?

如何在XSLT中使用带有两个匹配条件的键?

看起来你想要把XML里相同RecordId的<object>元素分组,然后在每个组里获取特定AttributeName(比如MBRSH、Label)对应的AttributeValue对吧?你的Muenchian方法尝试方向是对的,但问题出在键的定义没有把RecordId和AttributeName关联起来,导致每次拿到的都是全局的匹配结果,而不是对应RecordId组内的结果。

我来给你调整一下思路和代码:

首先,我们可以通过两种方式实现需求:一种是用组合键精准定位,另一种是先分组再组内查找,两种方式都能解决你遇到的问题。

方法一:用组合键精准匹配

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <!-- 键1:按RecordId分组所有object -->
    <xsl:key name="objects-by-recordid" match="array/object" use="property[@name='RecordId']/literal" />

    <!-- 键2:用RecordId+AttributeName的组合值作为键,定位对应AttributeValue -->
    <xsl:key name="attr-by-name-and-id" match="array/object/property[@name='AttributeValue']/literal" 
             use="concat(../../property[@name='RecordId']/literal, '|', ../property[@name='AttributeName']/literal)" />

    <xsl:template match="/">
        <!-- 遍历所有唯一的RecordId分组(自动去重) -->
        <xsl:for-each select="array/object[count(. | key('objects-by-recordid', property[@name='RecordId']/literal)[1]) = 1]">
            <xsl:variable name="current-recordid" select="property[@name='RecordId']/literal" />
            
            <!-- 获取当前RecordId下各个属性对应的值 -->
            <xsl:variable name="mbrsh-value" select="key('attr-by-name-and-id', concat($current-recordid, '|', 'MBRSH'))" />
            <xsl:variable name="label-value" select="key('attr-by-name-and-id', concat($current-recordid, '|', 'Label'))" />
            <xsl:variable name="is-active-value" select="key('attr-by-name-and-id', concat($current-recordid, '|', 'Is_Active'))" />

            <!-- 这里可以输出你需要的结构,示例如下 -->
            <record>
                <id><xsl:value-of select="$current-recordid" /></id>
                <membership><xsl:value-of select="$mbrsh-value" /></membership>
                <category><xsl:value-of select="$label-value" /></category>
                <active-status><xsl:value-of select="$is-active-value" /></active-status>
            </record>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

代码说明

  • objects-by-recordid键:负责把所有<object>按RecordId分组,确保我们只遍历每个RecordId一次,避免重复处理。
  • attr-by-name-and-id键:用RecordId+分隔符+AttributeName的组合值作为键,这样就能精准定位到某个RecordId下特定属性的值,不会和其他RecordId的结果混淆。

方法二:先分组再组内查找(更直观)

如果你觉得组合键有点绕,也可以先拿到当前RecordId的所有对象组,再直接在组内过滤属性:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:key name="objects-by-recordid" match="array/object" use="property[@name='RecordId']/literal" />

    <xsl:template match="/">
        <xsl:for-each select="array/object[count(. | key('objects-by-recordid', property[@name='RecordId']/literal)[1]) = 1]">
            <xsl:variable name="current-group" select="key('objects-by-recordid', property[@name='RecordId']/literal)" />
            <xsl:variable name="current-recordid" select="property[@name='RecordId']/literal" />

            <record>
                <id><xsl:value-of select="$current-recordid" /></id>
                <membership><xsl:value-of select="$current-group[property[@name='AttributeName']/literal='MBRSH']/property[@name='AttributeValue']/literal" /></membership>
                <category><xsl:value-of select="$current-group[property[@name='AttributeName']/literal='Label']/property[@name='AttributeValue']/literal" /></category>
                <active-status><xsl:value-of select="$current-group[property[@name='AttributeName']/literal='Is_Active']/property[@name='AttributeValue']/literal" /></active-status>
            </record>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

代码说明

  • 先通过objects-by-recordid键拿到当前RecordId对应的所有对象组current-group,然后直接在组内筛选出AttributeName符合要求的对象,再提取它的AttributeValue,逻辑更直白,适合简单场景。

你之前的问题核心就是没有把RecordId和AttributeName做关联,导致查找时没有限定在当前RecordId的组内,现在用上面两种方法调整后,应该就能得到你想要的结果了。

备注:内容来源于stack exchange,提问作者Ndilokelwa Luis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 11:28:12