Операции с наборами
Язык XPath поддерживает операцию |
с наборами.
Union (|), оператор
Оператор |
, или union, возвращает объединение двух своих операндов, которые должны быть наборами узлов. Например, //author | //publisher
возвращает набор узлов, в котором объединены все узлы //author
и все узлы //publisher
. Для объединения нескольких наборов узлов можно связать несколько операторов union по цепочке друг с другом. Например, //author | //publisher | //editor | //book-seller
возвращает набор узлов, содержащий все узлы //author
, //publisher
, //editor
и //book-seller elements
. Оператор union сохраняет порядок расположения документов и не возвращает повторяющиеся документы.
Примеры
Выражение | Ссылается на |
---|---|
|
Набор узлов, содержащий элементы |
|
Набор узлов, содержащий элементы |
|
Набор узлов, содержащий все элементы |
|
Набор узлов, содержащий все элементы |
Пример
В следующем примере иллюстрируется действие оператора union.
XML-файл (test.xml)
<?xml version="1.0"?>
<test>
<x a="1">
<x a="2" b="B">
<x>
<y>y31</y>
<y>y32</y>
</x>
</x>
</x>
</test>
XSLT-файл (test.xsl)
Приведенная ниже таблица стилей XSLT выбирает все элементы <x>
, атрибут a
которых равен 2
, а также элементы <x>
без атрибутов.
<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<!-- Suppress text nodes not covered in subsequent template rule. -->
<xsl:template match="text()"/>
<!-- Handles a generic element node. -->
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="*|@*" />
<xsl:if test="text()">
<xsl:value-of select="."/>
</xsl:if>
</xsl:element>
</xsl:template>
<!-- Handles a generic attribute node. -->
<xsl:template match="@*">
<xsl:attribute name="{name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="/test">
<xsl:apply-templates select="//x[@a=2] | //x[not(@*)]"/>
</xsl:template>
</xsl:stylesheet>
Результат выполнения данного преобразования:
<x a="2" b="B">
<x>
<y>31</y>
<y>y32</y>
</x>
</x>
<x>
<y>y31</y>
<y>y32</y>
</x>
Очередность
В следующей таблице показан порядок приоритета (от наибольшего к наименьшему) между логическими операторами и операторами сравнения.
Очередность | Операторы | Описание |
---|---|---|
1 |
|
Группирование |
2 |
|
Фильтры |
3 |
|
Операции с путями |
4 |
|
Сравнения |
5 |
|
Сравнения |
6 |
|
Объединение |
7 |
|
Логическое НЕ |
8 |
|
Логическое И |
9 |
|
Логическое ИЛИ |
Пример
В следующем примере иллюстрируется действие приведенного выше приоритета операторов.
XML-файл (test.xml)
<?xml version="1.0"?>
<test>
<x a="1">
<x a="2" b="B">
<x>
<y>y31</y>
<y>y32</y>
</x>
</x>
</x>
<x a="1">
<x a="2">
<y>y21</y>
<y>y22</y>
</x>
</x>
<x a="1">
<y>y11</y>
<y>y12</y>
</x>
<x>
<y>y03</y>
<y>y04</y>
</x>
</test>
Базовый XSLT-файл (test.xsl)
Этот базовый XSLT-файл будет использоваться в следующих примерах в качестве отправной точки.
<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<!-- Suppress text nodes not covered in subsequent template rule. -->
<xsl:template match="text()"/>
<!-- Handles a generic element node. -->
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="*|@*" />
<xsl:if test="text()">
<xsl:value-of select="."/>
</xsl:if>
</xsl:element>
</xsl:template>
<!-- Handles a generic attribute node. -->
<xsl:template match="@*">
<xsl:attribute name="{name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Вариант 0. Пробный запуск
В таблицу стилей XSLT можно добавить следующее правило шаблона.
<xsl:template match="/test">
<xsl:apply-templates select="*|@*/>
</xsl:template>
В результате будет сформирован XML-документ, идентичный исходному, но без инструкции по обработке <?xml version="1.0"?>
.
В следующих вариантах показаны различные способы написания этого правила шаблона. Смысл в том, чтобы показать порядок, в котором операторы XPath связываются с элементом.
Вариант 1. () связывается плотнее, чем []
Следующее правило шаблона выбирает первый элемент <y>
в порядке документа из всех элементов <y>
в исходном документе.
<xsl:template match="/test">
<xsl:apply-templates select="(//y)[1]"/>
</xsl:template>
Далее приведен результат.
<y>y31</y>
Вариант 2. [] связывает плотнее, чем / или //
Следующее правило шаблона выбирает все элементы <y>
, которые являются первыми среди своих одноуровневых элементов.
<xsl:template match="/test">
<xsl:apply-templates select="//y[1]"/>
</xsl:template>
Далее приведен результат.
<y>y31</y>
<y>y21</y>
<y>y11</y>
<y>y03</y>
Вариант 3. and, not
Следующее правило шаблона выбирает все элементы <x>
, у которых нет дочерних элементов <x>
, есть родительский элемент <x>
и нет ни одного атрибута.
<xsl:template match="/test">
<xsl:apply-templates select=
"//x[./ancestor::*[name()='x'] and *[name()!='x'] and not(@*)]"/>
</xsl:template>
В результате получается один элемент <x>
, приведенный ниже вместе с дочерними элементами:
<x>
<y>y31</y>
<y>y32</y>
</x>
Вариант 4. or, and, not
Следующее правило шаблона выбирает каждый элемент <x>
, который является дочерним элементом элемента <x>
, или не является родительским элементом элемента <x>
и не имеет атрибутов.
<xsl:template match="/test">
<xsl:apply-templates select=
"//x[./ancestor::*[name()='x'] or *[name()!='x'] and not(@*)]"/>
</xsl:template>
В результате создается набор узлов, содержащих следующие элементы <x>
, перечисленные далее вместе с их дочерними элементами.
<x a="2" b="B">
<x>
<y>y31</y>
<y>y32</y>
</x>
</x>
<x>
<y>y31</y>
<y>y32</y>
</x>
<x a="2">
<y>y21</y>
<y>y22</y>
</x>
<x>
<y>y03</y>
<y>y04</y>
</x>
Вариант 5. and, or, not
Следующее правило шаблона выбирает каждый элемент <x>
, который является дочерним элементом элемента <x>
, но не является родительским элементом элемента <x>
или который не имеет атрибутов.
<xsl:template match="/test">
<xsl:apply-templates select=
"//x[./ancestor::*[name()='x'] and *[name()!='x'] or not(@*)]"/>
</xsl:template>
В результате создается набор узлов, содержащих следующие элементы <x>
, перечисленные далее вместе с их дочерними элементами.
<x>
<y>y31</y>
<y>y32</y>
</x>
<x a="2">
<y>y21</y>
<y>y22</y>
</x>
<x>
<y>y03</y>
<y>y04</y>
</x>