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
baz
children are same thendoSomething
elsedoSomethingElse
. 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/baz
elements have the same tags (not necessarilydate
andtime
but saya
,b
andc
), 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.