fn:deep-equal
This function assesses whether two sequences are deep-equal to each other. To be deep-equal, they must contain items that are pairwise deep-equal; and for two items to be deep-equal, they must either be atomic values that compare equal, or nodes of the same kind, with the same name, whose children are deep-equal, or maps with matching entries, or arrays with matching members.
Signatures
fn:deep-equal(
$parameter1 as item()*,
$parameter2 as item()*
) as xs:boolean
fn:deep-equal(
$parameter1 as item()*,
$parameter2 as item()*,
$collation as xs:string
) as xs:boolean
Properties
The two-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on collations, and implicit timezone.
The three-argument form of this function is deterministic, context-dependent, and focus-independent. It depends on collations, and static base URI, and implicit timezone.
Rules
The $collation
argument identifies a collation which is used at all levels
of recursion when strings are compared (but not when names are compared), according
to
the rules in Choosing a collation.
If the two sequences are both empty, the function returns true
.
If the two sequences are of different lengths, the function returns
false
.
If the two sequences are of the same length, the function returns true
if
and only if every item in the sequence $parameter1
is deep-equal to the
item at the same position in the sequence $parameter2
. The rules for
deciding whether two items are deep-equal follow.
Call the two items $i1
and $i2
respectively.
If $i1
and $i2
are both atomic values, they are deep-equal if
and only if ($i1 eq $i2)
is true
, or if both values are
NaN
. If the eq
operator is not defined for $i1
and $i2
, the function returns false
.
If $i1
and $i2
are both maps, the result is true
if and only if all the
following conditions apply:
-
Both maps have the same number of entries.
-
For every entry in the first map, there is an entry in the second map that:
-
has the same key (note that the collation is not used when comparing keys), and
-
has the same associated value (compared using the
fn:deep-equal
function, under the collation supplied in the original call tofn:deep-equal
).
-
If $i1
and $i2
are both arrays, the result is true
if and only if all
the following conditions apply:
-
Both arrays have the same number of members (
array:size($i1) eq array:size($i2)
). -
Members in the same position of both arrays are deep-equal to each other, under the collation supplied in the original call to
fn:deep-equal
: that is,every $p in 1 to array:size($i1) satisfies deep-equal($i1($p), $i2($p), $collation)
If $i1
and $i2
are both nodes, they are compared as described
below:
-
If the two nodes are of different kinds, the result is
false
. -
If the two nodes are both document nodes then they are deep-equal if and only if the sequence
$i1/(*|text())
is deep-equal to the sequence$i2/(*|text())
. -
If the two nodes are both element nodes then they are deep-equal if and only if all of the following conditions are satisfied:
-
The two nodes have the same name, that is
(node-name($i1) eq node-name($i2))
. -
Either both nodes are annotated as having simple content or both nodes are annotated as having complex content. For this purpose "simple content" means either a simple type or a complex type with simple content; "complex content" means a complex type whose variety is mixed, element-only, or empty.
It is a consequence of this rule that validating a document D against a schema will usually (but not necessarily) result in a document that is not deep-equal to D. The exception is when the schema allows all elements to have mixed content.
-
The two nodes have the same number of attributes, and for every attribute
$a1
in$i1/@*
there exists an attribute$a2
in$i2/@*
such that$a1
and$a2
are deep-equal. -
One of the following conditions holds:
-
Both element nodes are annotated as having simple content (as defined in 3(b) above), and the typed value of
$i1
is deep-equal to the typed value of$i2
. -
Both element nodes have a type annotation that is a complex type with variety element-only, and the sequence
$i1/*
is deep-equal to the sequence$i2/*
. -
Both element nodes have a type annotation that is a complex type with variety mixed, and the sequence
$i1/(*|text())
is deep-equal to the sequence$i2/(*|text())
. -
Both element nodes have a type annotation that is a complex type with variety empty.
-
-
-
If the two nodes are both attribute nodes then they are deep-equal if and only if both the following conditions are satisfied:
-
The two nodes have the same name, that is
(node-name($i1) eq node-name($i2))
. -
The typed value of
$i1
is deep-equal to the typed value of$i2
.
-
-
If the two nodes are both processing instruction nodes, then they are deep-equal if and only if both the following conditions are satisfied:
-
The two nodes have the same name, that is
(node-name($i1) eq node-name($i2))
. -
The string value of
$i1
is equal to the string value of$i2
.
-
-
If the two nodes are both namespace nodes, then they are deep-equal if and only if both the following conditions are satisfied:
-
The two nodes either have the same name or are both nameless, that is
fn:deep-equal(node-name($i1), node-name($i2))
. -
The string value of
$i1
is equal to the string value of$i2
when compared using the Unicode codepoint collation.
-
-
If the two nodes are both text nodes or comment nodes, then they are deep-equal if and only if their string-values are equal.
In all other cases the result is false.
Error Conditions
A type error is raised [ERRFOTY0015] if either input sequence contains a function item that is not a map or array.
Notes
The two nodes are not required to have the same type annotation, and they are not
required to have the same in-scope namespaces. They may also differ in their parent,
their base URI, and the values returned by the is-id
and
is-idrefs
accessors (see is-id Accessor and
is-idrefs Accessor). The order of children is significant,
but the order of attributes is insignificant.
The contents of comments and processing instructions are significant only if these nodes appear directly as items in the two sequences being compared. The content of a comment or processing instruction that appears as a descendant of an item in one of the sequences being compared does not affect the result. However, the presence of a comment or processing instruction, if it causes a text node to be split into two text nodes, may affect the result.
Comparing items of different kind (for example, comparing an atomic
value to a node, or a map to an array, or an integer to an xs:date
) returns false, it does not return an error. So
the result of fn:deep-equal(1, current-dateTime())
is false
.
Comparing a function (other than a map or array) to any other value raises a type error.
Examples
let $at := <attendees> <name last='Parker'
first='Peter'/> <name last='Barker' first='Bob'/> <name last='Parker'
first='Peter'/> </attendees>
The expression fn:deep-equal($at, $at/*)
returns false()
.
The expression fn:deep-equal($at/name[1], $at/name[2])
returns false()
.
The expression fn:deep-equal($at/name[1], $at/name[3])
returns true()
.
The expression fn:deep-equal($at/name[1], 'Peter Parker')
returns false()
.
The expression fn:deep-equal(map{1:'a', 2:'b'}, map{2:'b', 1:'a'})
returns true()
.
The expression fn:deep-equal([1, 2, 3], [1, 2, 3])
returns true()
.
The expression fn:deep-equal((1, 2, 3), [1, 2, 3])
returns false()
.