Операции над множествами (XPath)
Язык XPath поддерживает операцию задания |.
Union (|), оператор
The |или оператор union возвращает объединение двух своих операндов, которые должны быть наборами узлов. Например, //author | //publisher возвращает набор узлов, в котором объединены все узлы //author и все узлы //publisher. Для объединения нескольких наборов узлов можно связать несколько операторов union по цепочке друг с другом. Например, //author | //publisher | //editor | //book-seller возвращает набор узлов, содержащий все узлы //author, //publisher, //editor и //book-seller elements. Оператор union сохраняет порядок следования элементов в документе и не возвращает повторяющиеся элементы.
Примеры
Выражение |
Ссылается на |
---|---|
first-name | last-name |
Набор узлов, содержащий элементы <first-name> и <last-name> в текущем контексте. |
(bookstore/book | bookstore/magazine) |
Набор узлов, содержащий элементы <book> или <magazine> внутри элемента <bookstore>. |
book | book/author |
Набор узлов, содержащий все элементы <book> и все элементы <author> внутри элементов <book>. |
(book | magazine)/price |
Набор узлов, содержащий все элементы <price> элементов <book> или <magazine>. |
Пример
В следующем примере иллюстрируется действие оператора 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 |
not() |
Логическое НЕТ |
8 |
and |
Логическое И |
9 |
or |
Логическое ИЛИ |
Пример
В следующем примере иллюстрируется действие приведенного выше приоритета операторов.
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>