Reputation: 13
I am working on a transform to wrap consecutive elements of the same type into a single element, but only if there is no text between the nodes.
For example:
<foo>ABC</foo><foo>DEF</foo> <foo>GHI</foo>
<foo>JKL</foo>
Should transform to:
<bar>
<foo>ABC</foo>
<foo>DEF</foo>
<foo>GHI</foo>
<foo>JKL</foo>
</bar>
Whitespace should be ignored whether it is a space or a return. Any other text should indicate an end to what should be wrapped. For example:
<foo>ABC</foo><foo>DEF</foo> some text in between <foo>GHI</foo>
<foo>JKL</foo>
Should transform to:
<bar>
<foo>ABC</foo>
<foo>DEF</foo>
</bar> some text in between
<bar>
<foo>GHI</foo>
<foo>JKL</foo>
</bar>
I have tried selecting the <foo>
element using:
foo[following-sibling::node()[1][normalize-space()='']]
But this is not picking up the case where there is a space between the <foo>
elements. (There are additional criteria in the full template match, but this is the part that is not working as I expect.
I wrote a test transform to output the value of using the normalize-space
function on the text following the element, and it outputs a single space for the lines where there is a space between the elements. However, if I query for:
foo[following-sibling::node()[1][normalize-space()=' ']]
It does not find those elements. So, I'm totally confused.
Any help would be greatly appreciated!
Upvotes: 0
Views: 280
Reputation: 13
The issue with [normalize-space()='']
or [not(normalize-space())]
seeming to not work was because there were non-breaking spaces instead of regular spaces in a couple places. I updated the template match to use [not(normalize-space(translate(.,' ', ' ')))]
and it worked.
Upvotes: 1
Reputation: 167446
Assuming XSLT 2.0 you can use
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="*[foo]">
<xsl:copy>
<xsl:for-each-group select="node()" group-adjacent="boolean(self::foo | self::text()[not(normalize-space())])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<bar>
<xsl:apply-templates select="current-group()"/>
</bar>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:transform>
http://xsltransform.net/ncntCSS
Upvotes: 0