Главная » XSLT » Отбор узлов по контексту

0

Задача

Требуется отобрать узлы, лежащие между двумя заданными.

Решение XSLT 1.0

В XSLT 1.0 есть несколько способов решить эту задачу. Самый простой для понимания заключается в вычислении позиций узлов, которые должны отбирать­ся на каждом шаге. Предположим, что имеется такой документ:

<doc>

<heading>Да не нужна мне никакая структура</heading>

<para>1.1</para>

<para>1.2</para>

<para>1.3</para>

<para>1.4</para>

<heading>Признания обитателя плоской земли</heading>

<para>2.1</para>

<para>2.2</para>

<para>2.3</para>

<heading>Плоские иерархии сохраняют леса!</heading> <para>3.1</para> <para>3.2</para> </doc>

<xsl:template match="/doc"> <xsl:copy>

<!– Сначала отбираем ограничивающие элементы –> <xsl:apply-templates select="heading"/> </xsl:copy> </xsl:template>

<!– Сопоставление с ограничивающими элементами –> <xsl:template match="heading">

<!– Вычисляем, сколько интересующих нас элементов (para) следует за этим заголовком –>

<xsl:variable name="numFollowingPara"

select="count(following-sibling::para)"/>

<!– Вычисляем, сколько интересующих нас элементов (para) следует за следующим заголовком, и вычитаем это значение из полученного ранее счетчика, чтобы узнать позицию последнего абзаца в данной группе –> <xsl:variable name="lastParaInHeading" select="$numFollowingPara -

count(following-sibling::heading[1]/following-sibling::para)"/>

<!– Теперь можно отобрать нужные элементы по позиции относительно текущего заголовка –>

<xsl:apply-templates

select="following-sibling::para[position() &lt;= $lastParaInHeading]"/>

</xsl:template>

XSLT 2.0

Эта задача как будто специально придумана для демонстрации команды for-each-group. В данном случае мы воспользуемся атрибутом group- starting-with:

<xsl:template match="/doc"> <xsl:copy>

<xsl:for-each-group select="*" group-starting-with="heading">

<!– Отобрать элементы para в группе, ограниченной с двух сторон элементами heading –>

<xsl:apply-templates select="current-group()[self::para]"/> </xsl:for-each-group>

</xsl:copy>

</xsl:template>

Обсуждение

Отбор узлов на основе их позиции относительно других узлов – типичная задача, возникающая, когда нужно преобразовывать XML-документы, где структура подразумевается неявно, а не закодирована прямо в иерархии. Ясно, что если бы каждая группа, состоящая из заголовка и относящихся к нему абзацев, содержалась внутри отдельного родительского элемента (например, section), то задача была бы тривиальна. Здесь мы имеем классический компромисс между простотой документа с точки зрения его создателя и с точки зрения того, кто дол­жен его преобразовывать. С появлением в XSLT 2.0 команды for-each-group обрабатывать слабо структурированные документы стало гораздо проще.

Мангано Сэл  XSLT. Сборник рецептов. – М.: ДМК Пресс, СПБ.: БХВ-Петербург, 2008. – 864 с.: ил.

По теме:

  • Комментарии