My XML looks like this:
3&
If you want to do this in a generic way then you are really stretching the capability of XSLT 1.0 beyond its design limits. But it can be done.
Write a named template called deep-equal that takes two elements as its arguments and returns a string containing the character "F" if and only if they are not equal (for your purposes).
It might look like this:
<xsl:template name="deep-equal">
<xsl:param name="a"/>
<xsl:param name="b"/>
<xsl:choose>
<xsl:when test="local-name(a) != local-name(b)">F</xsl:when>
<xsl:when test="namespace-uri(a) != namespace-uri(b)">F</xsl:when>
<xsl:when test="normalize-space(a) != normalize-space(b)">F</xsl:when>
<xsl:when test="count(a/*) != count(b/*)">F</xsl:when>
<xsl:otherwise>
<xsl:variable name="diffs">
<xsl:for-each select="*">
<xsl:variable name="position" select="position()"/>
<xsl:call-template name="deep-equal">
<xsl:with-param name="a" select="."/>
<xsl:with-param name="b" select="$b/*[$position]"/>
</xsl:call-template>
</xsl:for-each>
</xsl:variable>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Apply this to all relevant pairs of elements:
<xsl:variable name="comparison">
<xsl:for-each select="baz[position() >= 2]">
<xsl:call-template name="deep-equal">
<xsl:with-param name="a" select="../baz[1]"/>
<xsl:with-param name="b" select="."/>
</xsl:call-template>
</xsl:for-each>
</xsl:variable>
Test if the result contains an "F":
<xsl:if test="contains($comparison, 'F')">...</xsl:if>
If all the
bazchildren are same thendoSomethingelsedoSomethingElse. My current node isfoo.
This is confusing because:
baz are not children of foo;Try something like:
<xsl:template match="foo">
<xsl:variable name="first-baz" select="(bar/baz)[1]" />
<xsl:choose>
<xsl:when test="bar/baz[date!=$first-baz/date or time!=$first-baz/time]">
<!-- THEY ARE NOT ALL SAME -->
</xsl:when>
<xsl:otherwise>
<!-- THEY ARE ALL SAME -->
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Note that this assumes that every baz has a date and a time. Otherwise you need to test for not(date=$first-baz/date) etc.
See also: http://www.jenitennison.com/xslt/grouping/muenchian.html
Now, assuming all the
bar/bazelements have the same tags (not necessarilydateandtimebut saya,bandc), what would be the test attribute for that case?
This makes it significantly more complex. Still you could construct a key:
<xsl:key name="first-baz" match="foo/bar[1]/baz[1]/*" use="name()" />
then make your test:
<xsl:when test="bar/baz/*[. != key('first-baz', name())]">
This returns true if any child of baz exists whose string-value is different from an equally named node that is child of the first baz.
Note that the key, as defined here, is document-wide. If you want to restrict the test to the current foo ancestor, then you must include its id in the key.