Использование XPath position () во вложенном контексте не дает желаемого результата - PullRequest
0 голосов
/ 25 сентября 2019

Используя XPath 1, я пытаюсь вернуть набор узлов item s в пределах определенного диапазона, в котором есть различные значения dept_number.Диапазон, в котором находятся эти предметы, является динамическим.Документ структурирован следующим образом:

<data>
    <items>
        <item>
            <dept_number>1</dept_number>
        </item>
        <item>
            <dept_number>1</dept_number>
        </item>
        <item>
            <dept_number>2</dept_number>
        </item>
        <item>
            <dept_number>2</dept_number>
        </item>
        <item>
            <dept_number>3</dept_number>
        </item>
        <item>
            <dept_number>4</dept_number>
        </item>
        <item>
            <dept_number>4</dept_number>
        </item>
    </items>
</data>

Лучший способ, которым я мог бы подумать, это сделать следующим образом:

/data/items/item[not(dept_number = preceding-sibling::item[position() > $min]/dept_number) and position() > $min and position() <= $max]/dept_number

, где $min - нижняя границадиапазон и $max - верхняя граница.Это не работает.Например, если я использую

/data/items/*[name() = 'item' and not(dept_number = preceding-sibling::*[position() > 1]/dept_number) and position() > 1 and position() <= 5]/dept_number

, он возвращает

<dept_number>1</dept_number>
<dept_number>2</dept_number>
<dept_number>2</dept_number>
<dept_number>3</dept_number>

, который не является набором различных значений.Я ожидаю, что

<dept_number>1</dept_number>
<dept_number>2</dept_number>
<dept_number>3</dept_number>

Я полагаю, что проблема заключается в использовании position() во вложенном контексте (т. Е. /data/items/item[... preceding-sibling::item[position() > $min] ...]. Кажется, он использует результат, который вы получите из position() при использованииво внешнем контексте, а не во внутреннем.

В xslt я также пытался использовать ключи как таковые:

<xsl:key name="dept_number_key" match="/data/items/item" use="dept_number"/>
<xsl:for-each select="/data/items/item[generate-id() = generate-id(key('dept_number_key', dept_number)[1]) and position() $gt; $min-pos and position() &lt;= $max-pos]">
</xsl:for-each>

, но это все равно не работает.

Любая помощь будет принята с благодарностью.

Редактировать: я имею в виду не диапазон значений dept_number, а диапазон <item> тегов в <items>. Например, еслидиапазон был от 3 до 5, я хотел бы вернуть третий, четвертый и пятый тег <item> в пределах <items>.

1 Ответ

1 голос
/ 25 сентября 2019

--- отредактировано в ответ на уточнение ---

Я начну с копирования элементов в диапазоне в новый «документ», чтобыпозже вы можете использовать для этого мюнхенскую группировку, чтобы получить только разные значения.Без этого группировка может завершиться неудачей, если, например, элемент № 3 не является первым элементом с данным значением dept_number.

Рассмотрим следующую таблицу стилей:

XSLT 1.0+ EXSLT node-set () function

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="min-pos" select="3" />
<xsl:variable name="max-pos" select="5" />

<xsl:key name="dept_number_key" match="item" use="dept_number" />

<xsl:template match="/data">
    <xsl:variable name="items-in-range">
        <xsl:copy-of select="items/item[$min-pos &lt;= position() and position() &lt;= $max-pos]"/>
    </xsl:variable>
    <root>
        <xsl:copy-of select="exsl:node-set($items-in-range)/item[generate-id() = generate-id(key('dept_number_key', dept_number)[1])]/dept_number"/>
    </root>
</xsl:template>

</xsl:stylesheet>

Обратите внимание, что некоторые процессоры XSLT 1.0 поддерживают функцию расширения EXSLT set:distinct().Это может сократить код здесь.

...