пример показывает, что множество дочерних элементов
int
элемента
numbers
одновременно считает как равным, так и неравным множеству дочерних элементов
byte
.
Приведем еще несколько примеров.
Листинг 3.4. Входящий документ B
<numbers>
<int>1</int>
<byte>2</byte>
<int>3</int>
<byte>4</byte>
</numbers>
Результат:
false and true
Листинг 3.5. Входящий документ C
<numbers>
<int>1</int>
<byte>1</byte>
<int>1</int>
</numbers>
Результат:
true and false
С математической точки зрения операции сравнения множеств определены в XSLT, мягко говоря, странно. Например, единственный случай, когда для двух множеств не будет выполняться неравенство ("
!=
") — это когда все узлы обоих множеств будут иметь одинаковое строковое представление. Вместе с тем, операции сравнения множеств очень часто используются в качестве условий и потому нужно хорошо понимать различия между ними и математическими операциями сравнения.
XSLT определяет единственную операцию над множествами — операцию объединения "
|
". Выражение "
$A | $B
" возвратит множество узлов, присутствующих либо в
$A
, либо в
$B
, либо и там, и там.
В XSLT нет встроенного оператора, который позволил бы установить принадлежность узла некоторому множеству. Для этой цели используется очень хитроумный прием, основанный на использовании функции
count
, которая возвращает количество узлов множества. Представим, что множество
$node
содержит некоторый узел, и мы хотим проверить, входит ли он во множество
$nodeset
. Сделать это можно при помощи выражения
count($nodeset) = count($node | $nodeset)
которое будет истинным тогда и только тогда, когда
$node
полностью принадлежит
$nodeset
.
Этот метод позволяет реализовать в XSLT другие операции над множествами — пересечение, разность и симметрическую разность. Подробное описание этих операций приводится в главе 11.
В XSLT также нет оператора, который позволил бы проверить тождественность двух узлов. Например, если каждое из множеств
$A
и
$B
содержит по одному узлу, при помощи простого оператора равенства (
$A = $B
) мы не сможем проверить, один и тот же это узел или два разных узла с одинаковыми текстовыми значениями.
Для того чтобы корректно выполнить такое сравнение, можно использовать функцию
generate-id
, которая для каждого из узлов дерева генерирует уникальный строковый идентификатор, присущий только этому узлу и никакому другому, причем для одних и тех же узлов идентификаторы всегда будут генерироваться одинаковыми. Таким образом, для проверки тождественности двух узлов, содержащихся во множествах
$A
и
$B
, будет достаточно сравнить их уникальные идентификаторы:
generate-id($А) = generate-id($В)
Множества узлов могут быть преобразованы в булевые значения, числа и строки.
При преобразовании в булевый тип пустое множество узлов преобразуется в
false
, а непустое — в
true
. Например, чтобы проверить, есть ли у текущего узла атрибут
value
, можно написать:
<xsl:if test="@value">
<xsl:text>Value attribute exists here.</xsl:text>
</xsl:if>
Выражение
@value
возвратит непустое множество, состоящее из узла атрибута
value
, если он есть в текущем элементе, или пустое множество, если такого атрибута нет. В первом случае логическим эквивалентом будет
true
, во втором —
false
, то есть текст будет выведен только в случае наличия атрибута
value
.
При преобразовании множества узлов в строку, результатом будет строковое значение первого в порядке просмотра узла множества.
Пример
Листинг 3.6. Входящий документ
<catalog>
<item>A</item>
<item>B</item>
<item>C</item>
<item>D</item>
</catalog>
Листинг 3.7. Преобразование
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of select="catalog/item"/>
</xsl:template>
</xsl:stylesheet>
Результат:
A
При преобразовании множества узлов в число, множество сначала приводится к строке, а затем строка преобразуется в численное значение. Проще говоря, численным значением множества узлов будет численное значение первого узла в порядке просмотра документа.