XSL模糊规则匹配与相邻分组问题:同CSS类相邻元素合并模板故障
Hey there! As someone who’s wrestled with XSLT grouping quirks before, I totally get how frustrating those "fuzzy" matching issues can be when trying to merge adjacent elements by class. Let’s break down the most common culprits and how to fix them.
Common Causes & Fixes
1. Whitespace Nodes Sneaking In
Your current code excludes empty text nodes with node() except text()[not(normalize-space())], but sometimes non-empty whitespace (like newlines or tabs between elements) can still throw off grouping. Even if they look empty, hidden whitespace might slip through, breaking the "adjacent" check.
Try tightening up your node selection to explicitly filter out all whitespace-only text nodes:
<xsl:for-each-group select="node()[not(self::text()[normalize-space()=''])]" group-adjacent="@class=$classFusion">
This ensures no stray whitespace nodes create gaps between elements you want to merge.
2. Partial Class Matches (The #1 "Fuzzy" Culprit)
If your @class attributes have multiple classes (like class="foo bar"), comparing @class=$classFusion will only match exact strings. So if $classFusion is "foo", elements with class="foo bar" won’t group with elements that only have class="foo"—that’s a super common "fuzzy" mismatch!
To fix this, check if the target class exists as a whole word in the @class attribute (avoiding false matches like "foo" in "foobar"):
group-adjacent="contains(concat(' ', @class, ' '), concat(' ', $classFusion, ' '))"
The extra spaces around @class and $classFusion ensure you’re matching full class names, not substrings.
3. Parameter Passing Glitches
Double-check that your $classFusion parameter is being passed correctly. If it has extra whitespace, is empty, or isn’t the exact string you expect, your grouping will either fail entirely or match unintended elements.
Add a quick debug comment to verify the parameter value:
<xsl:comment>Debug: classFusion value is '<xsl:value-of select="$classFusion"/>'</xsl:comment>
This will show up in your output and let you confirm the parameter is what you think it is.
4. Unintended Nodes Breaking Adjacency
Comments, processing instructions, or even hidden elements between your target nodes can break the "adjacent" grouping. If you only want to merge element nodes (not other node types), adjust your selection to target only elements:
<xsl:for-each-group select="*" group-adjacent="contains(concat(' ', @class, ' '), concat(' ', $classFusion, ' '))">
Then inside the group, you can handle only the groups where the class match is true.
5. XSLT Version Compatibility
Quick sanity check: for-each-group is an XSLT 2.0+ feature. If you’re stuck on an older XSLT 1.0 processor, this syntax won’t work at all. If that’s the case, you’ll need a recursive template approach instead of grouping—but since you’re using for-each-group, I assume you’re on 2.0 or higher.
Quick Debugging Hack
Temporarily output each node’s class and position to visualize exactly what’s being grouped:
<xsl:for-each select="node()[not(self::text()[normalize-space()=''])]"> <xsl:comment>Node <xsl:value-of select="position()"/> has class: '<xsl:value-of select="@class"/>'</xsl:comment> </xsl:for-each>
This will help you spot gaps or mismatches you might have missed.
If you can share the rest of your xsl:choose block and a sample input XML, we can narrow it down even further—but these fixes should cover most common fuzzy matching scenarios!
内容的提问来源于stack exchange,提问作者R. BR

