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

XSLT使用xsltproc处理多文件时提取唯一元素异常问题求助

问题原因

  • 命名空间匹配错误:你的cooking.xml、menu.xml都声明了默认命名空间https://cooking.com/2022/cooking,但XSLT中定义的cook前缀并没有用到节点匹配、路径查询、key定义的规则中,导致key('rcp', $menu)匹配不到任何节点,这是你当前输出为空的直接原因。
  • preceding-sibling轴作用域限制:preceding-sibling仅能查询和当前节点属于同一个父节点的前置兄弟节点。你执行cooking/recipe[@name = $menu]/ingredients查询得到的是分属不同recipe节点的ingredient集合,每个ingredient仅能感知到自己所属recipe下的兄弟节点,自然返回多个独立的食材集合,无法实现跨recipe去重。

修复方案

你可以使用XSLT 1.0标准的Muenchian分组法实现去重,无需依赖EXSLT扩展,修正后的完整样式表如下:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:cook="https://cooking.com/2022/cooking"
exclude-result-prefixes="cook">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>

<!-- 定义食材去重用的key,匹配规则加上命名空间前缀 -->
<xsl:key name="ingredient" match="cook:ingredient" use="@name" />

<xsl:template match="cook:cooking">
    <cooking xmlns="https://cooking.com/2022/cooking">
        <xsl:variable name="menu" select="cook:recipe/@name" />
        <!-- 切换上下文到cooking.xml使用key -->
        <xsl:for-each select="document('cooking.xml')">
            <!-- 选中菜单对应食谱的食材,Muenchian法去重 -->
            <xsl:for-each select="cook:cooking/cook:recipe[@name = $menu]/cook:ingredient[count(. | key('ingredient', @name)[1]) = 1]">
                <ingredient name="{@name}"/>
            </xsl:for-each>
        </xsl:for-each>
    </cooking>
</xsl:template>
  
</xsl:stylesheet>

执行原命令xsltproc shop.xsl menu.xml > ingredients.xml即可得到你期望的输出结果。

如果你希望继续使用EXSLT的set:distinct方法,只需要将原有样式表中所有节点匹配、路径查询的规则都加上cook前缀即可正常工作。


内容的提问来源于stack exchange,提问作者Jon Smirl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 21:36:04