如何在XSLT中同时过滤多子节点,排除含blue属性的item
解决方案
要实现同时检查product/defaultmarkers和firstmarkers节点下所有Marker的remarks属性,仅保留两个节点均**不包含(不区分大小写、忽略空格)"blue"**的item,需要修改XSLT的过滤逻辑,核心是处理字符串的空格和大小写,并同时验证两个节点的所有Marker。
关键逻辑说明
- 处理空格:用
normalize-space()去除remarks属性值的前后空格,并将中间连续空格替换为单个空格,避免空格干扰匹配。 - 不区分大小写:用
translate()将属性值中的大写"BLUE"转为小写"blue",统一匹配基准。 - 双节点验证:确保
defaultmarkers和firstmarkers下没有任何一个Marker的remarks处理后包含"blue",才保留对应的item。
XSLT 2.0+ 实现代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <filtered-items> <xsl:for-each select="products/product"> <!-- 过滤条件:两个marker节点下均无符合条件的Marker --> <xsl:if test="not(exists(defaultmarkers/Marker[contains(translate(normalize-space(@remarks), 'BLUE', 'blue'), 'blue')])) and not(exists(firstmarkers/Marker[contains(translate(normalize-space(@remarks), 'BLUE', 'blue'), 'blue')]))"> <xsl:copy-of select="item"/> </xsl:if> </xsl:for-each> </filtered-items> </xsl:template> </xsl:stylesheet>
XSLT 1.0 兼容实现
如果使用XSLT 1.0(无exists()函数),用count()判断是否存在匹配节点:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <filtered-items> <xsl:for-each select="products/product"> <xsl:if test="count(defaultmarkers/Marker[contains(translate(normalize-space(@remarks), 'BLUE', 'blue'), 'blue')]) = 0 and count(firstmarkers/Marker[contains(translate(normalize-space(@remarks), 'BLUE', 'blue'), 'blue')]) = 0"> <xsl:copy-of select="item"/> </xsl:if> </xsl:for-each> </filtered-items> </xsl:template> </xsl:stylesheet>
常见错误排查
- 未处理空格:直接匹配原始
remarks会忽略带空格的情况(如" BLUE "),必须用normalize-space()。 - 大小写未统一:仅匹配小写"blue"会漏掉大写或混合大小写的情况,
translate()是XSLT中实现大小写不敏感匹配的通用方法。 - 逻辑运算符错误:误用
or代替and,会导致只要其中一个节点无blue就保留,不符合需求。
内容的提问来源于stack exchange,提问作者gyuszmok
相关产品推荐
相关产品推荐

