Наборы узлов XPath
Как следует из имени, набор узлов (node set) является просто совокупностью узлов. Набор узлов может включать несколько узлов, единственный узел или быть пустым. Поскольку главная задача XPath — определять место разделов документов, постольку возвращающие наборы узлов выражения XPath являются наиболее популярными типами выражений. Например, выражение XPath child::PLANET возвращает набор узлов из всех элементов <PLANET>, дочерних для контекстного узла. Выражение child::PLANET/child::NAME возвращает набор узлов из всех элементов <NAME>, дочерних для элементов <PLANET> контекстного узла. Выражения XPath такого рода называются путями расположения, location path (W3C называет их «самой важной конструкцией» в XPath), и существенная часть этой главы будет посвящена разъяснению путей расположения.
Чтобы выбрать узел или узлы из набора узлов или обработать их, вы можете воспользоваться следующими функциями XPath для работы с наборами узлов, которые впервые встретились нам в главе 4 (и которые мы более подробно рассмотрим в следующей главе):
• count(node-set). Эта функция возвращает количество узлов в наборе. Если опустить параметр «набор узлов», функция будет применена к контекстному узлу;
• id(string ID). Эта функция возвращает набор узлов из элемента, чей ID удовлетворяет строке, переданной функции в качестве параметра, или пустой набор узлов, если ни у какого элемента нет указанного ID. Можно указать несколько идентификаторов, разделенных символами-разделителями, — в таком случае функция вернет набор узлов из элементов с этими идентификаторами;
• last(). Возвращает номер последнего узла в наборе;
• local-name(node-set). Возвращает локальное имя первого узла в наборе. Если опустить параметр «набор узлов», функция будет применена к контекстному узлу;
• name(node-set). Возвращает полностью определенное имя первого узла в наборе. Если опустить параметр «набор узлов», функция будет применена к контекстному узлу;
• namespace-uri(node-set). Возвращает URI пространства имен первого узла в наборе. Если опустить параметр «набор узлов», функция будет применена к контекстному узлу;
• position(). Возвращает позицию контекстного узла в контекстном наборе узлов (начиная с 1).
В следующем примере (из главы 6) для подсчета количества узлов в наборе применяется функция count. В этом случае набор узлов состоит из всех элементов <PLANET> в planets.xml, и я получил его при помощи пути расположения «\\PLANET» (который как путь расположения также является выражением XPath):
<xsclass="underline" stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsclass="underline" output method="xml" indent="yes"/>
<xsclass="underline" template match="*">
<xsclass="underline" copy>
<xsclass="underline" apply-templates/>
</xsclass="underline" copy>
</xsclass="underline" template>
<xsclass="underline" template match="PLANET">
<xsclass="underline" copy use-attribute-sets="numbering">
<xsclass="underline" apply-templates/>
</xsclass="underline" copy>
</xsclass="underline" template>
<xsclass="underline" attribute-set name="numbering">
<xsclass="underline" attribute name="number"><xsclass="underline" number/></xsclass="underline" attribute>
<xsclass="underline" attribute name="total">
<xsclass="underline" value-of select="count(//PLANET)"/>
</xsclass="underline" attribute>
</xsclass="underline" attribute-set>
</xsclass="underline" stylesheet>
Ниже показан результат; заметьте, что у каждого элемента <PLANET> есть оба атрибута, number и total, и атрибут total содержит общее число элементов <PLANET> в документе:
<?xml version="1.0" encoding="UTF-8"?>
<PLANETS>
<PLANET number="1" total="3">
<NAME>Mercury</NAME>
<MASS>.0553</MASS>
<DAY>58.65</DAY>
<RADIUS>1516</RADIUS>
<DENSITY>.983</DENSITY>
<DISTANCE>43.4</DISTANCE>
</PLANET>
<PLANET number="2" total="3">
<NAME>Venus</NAME>
<MASS>.815</MASS>
<DAY>116.75</DAY>
<RADIUS>3716</RADIUS>
<DENSITY>.943</DENSITY>
<DISTANCE>66.8</DISTANCE>
</PLANET>
<PLANET number="3" total="3">
<NAME>Earth</NAME>
<MASS>1</MASS>
<DAY>1</DAY>
<RADIUS>2107</RADIUS>
<DENSITY>1</DENSITY>
<DISTANCE>128.4</DISTANCE>
</PLANET>
</PLANETS>
Среди функций для работы с наборами узлов в особенности обратите внимание на функции name и local-name. С их помощью можно определить имя текущего элемента: например, если текущим элементом является <DAY>, local-name вернет DAY. Следующая таблица стилей демонстрирует, для чего это может понадобиться; в ней я использую такие теги, как <PLANETS>, <PLANET> и <DATA>, в качестве элементов буквального результата:
<?xml version="1.0"?>
<xsclass="underline" stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsclass="underline" output method="xml"/>
<xsclass="underline" template match="PLANETS">
<PLANETS>
<xsclass="underline" for-each select="PLANET">
<PLANET>
<xsclass="underline" for-each select="*">
<DATA>