Reputation: 1193
I have a situation where I need to select the nodes based on certain conditions and then apply Muenchian grouping to get unique values. I am on XSLT 1.0
<Parent>
<Child>
<A></A>
<B></B>
<C></C>
</Child>
<Child>
<A></A>
<B></B>
<C></C>
</Child>
<Child>
<A></A>
<B></B>
<C></C>
</Child>
</Parent>
The Condition that I have for use attribute is: If A is not blank, use A. Otherwise use B.
I had thought of a solution that would work for Fixed Width values for Node A and B. So If A and B are of length n, I can do something like this:
<xsl:key name="groupKey" match="/Parent/Child" use="substring(concat(A,B),1,n)">
So, If A is not present, I can use B. But I haven't been able to figure out how to use string-length() to derive the expression for variable lengths for A and B. Any Ideas?
Upvotes: 2
Views: 910
Reputation: 243579
In case you want to use the concat()
function:
use="concat(A, B[not(string(../A)])"
And if by blank you mean empty or whitespace-only, then use:
use="concat(A, B[not(normalize-space(../A)])"
Finally, if you really want to use both concat()
and substring()
(and this is really tricky, so I don't recommend it):
concat(substring(A, 1 div string(A) or 0),
substring(B, 1 div not(string(A)))
)
Here is a complete example for the last case, showing what the call to concat()
returns:
XML document:
<t>
<p>
<A>xxx</A>
<B>yyy</B>
</p>
<p>
<A/>
<B>zzz</B>
</p>
</t>
Transformation (just outputs the results of the evaluated expressions):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="p">
<xsl:value-of select=
"concat(substring(A, 1 div string(A) or 0),
substring(B, 1 div not(string(A)))
)"/>
</xsl:template>
</xsl:stylesheet>
Wanted (correct) result produced:
xxx
zzz
Upvotes: 2
Reputation: 52888
Here's another option that uses a different use
.
XML Input
<Parent>
<Child>
<A>both</A>
<B>both</B>
<C>c</C>
</Child>
<Child>
<A>a</A>
<B></B>
<C>c</C>
</Child>
<Child>
<A></A>
<B>b</B>
<C>c</C>
</Child>
</Parent>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="child" match="Child" use="(A[string()]|B[string()])[1]"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:for-each select="Child[count(.|key('child',(A[string()]|B[string()])[1])[1])=1]">
<group key="{(A[string()]|B[string()])[1]}">
<xsl:apply-templates select="key('child',(A[string()]|B[string()])[1])"/>
</group>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML Output
<Parent>
<group key="both">
<Child>
<A>both</A>
<B>both</B>
<C>c</C>
</Child>
</group>
<group key="a">
<Child>
<A>a</A>
<B/>
<C>c</C>
</Child>
</group>
<group key="b">
<Child>
<A/>
<B>b</B>
<C>c</C>
</Child>
</group>
</Parent>
Upvotes: 1