I have an xml like, values can be
<n1>value1</n1>
<n1>value1</n1>
<n1>value2</n1>
I need to check if all these values are same and if same I would need to assign it to another element. I am using XSLT v1.0.
Thanks,
I have an xml like, values can be
<n1>value1</n1>
<n1>value1</n1>
<n1>value2</n1>
I need to check if all these values are same and if same I would need to assign it to another element. I am using XSLT v1.0.
Thanks,
Good question, +1.
Just use:
not(/*/n1[1] != /*/n1)
Assuming that all n1
elements are selected in a variable named $v
, this can be expressed in just 14 characters-long XPath expression:
not($v[1] != $v)
Explanation 1:
By definition:
/*/n1[1] != /*/n1
is true()
exactly if there exists a node in /*/n1
whose string value isn't equal to the string value of /*/n1[1]
The logical negation of this:
not(/*/n1[1] != /*/n1)
is true()
iff no node in /*/n1
exists whose string value isn't equal to the string value of /*/n1[1]
-- that is, if all nodes in /*/n1
have the same sting value.
Explanation 2:
This follows from a more general double negation law :
every x has property y
is equivalent to:
There is no x that doesn't have property y
Assume a document of this form:
<root>
<n1>value1</n1>
<n1>value1</n1>
<n1>value1</n1>
</root>
The following simple stylesheet determines whether every n1
element has the same value:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:value-of select="
concat('All same? ', count(/*/n1[.=/*/n1[1]])=count(/*/n1))"/>
</xsl:template>
</xsl:stylesheet>
Output:
All same? true
The key to this stylesheet is the expression:
count(/*/n1[.=/*/n1[1]])=count(/*/n1))
...which compares the count of the n1
elements whose value equals the value of the first n1
element to the count of all n1
elements. These counts will be equal only when every n1
node has the same value.
This can be made a little easier to read by first selecting all n1
into a variable named n
:
count($n[.=$n[1]])=count($n)
Conditionally perform some action based on the result like this:
<xsl:template match="/">
<xsl:variable name="all" select="count(/*/n1[.=/*/n1[1]])=count(/*/n1)"/>
<xsl:if test="$all">All same</xsl:if>
<xsl:if test="not($all)">Not all same</xsl:if>
</xsl:template>