Сортировка XSLT в сочетании с предыдущим братом::

В цикле foreach я хочу использовать Previous-Sibling::

<for-each..>
    <xsl:sort select="type"/>
    <xsl:when test="preceding-sibling::data[1]/type != type

проблема в том, что «тип» в foreach сравнивается с несортированным предшествующим братом, например.

data1/type = 1 
data2/type = 2
data3/type = 1

будет сравниваться во втором цикле silbling=2 (исходный несортированный) и type=1 (поскольку он отсортирован)

есть ли способ обойти это?

ОБНОВЛЕНИЕ: мое намерение следующее

before             after
data/type2         type1 value1
data/type1         type1 value2 
data/type1         and speaking in HTML a spacer here (I compare type2:value to preceding-sibling value
data/type2         type2 value1
                   type2 value2

У меня есть несортированный список адресов, где типом является город, и мне нужна таблица HTML, отсортированная по городам, и делать некоторые вещи в зависимости от значений и других полей (эта часть работает, но поскольку сравнение с предыдущим братом не работая в отсортированном для каждого, у меня возникла проблема


person RRZ Europe    schedule 12.05.2011    source источник


Ответы (4)


Вы пытаетесь сгруппировать элементы данных по типу? Дайте нам знать, что вы пытаетесь сделать, и мы, вероятно, сможем помочь (как сказал @Michael Kay).

Один из вариантов (в XSLT 2.0 или с расширением набора узлов) — отсортированное копирование элементов данных в новую переменную, а затем запуск xsl:for-each на наборе узлов в этой новой переменной. Тогда отношение предыдущего брата будет отражать порядок сортировки.

person LarsH    schedule 12.05.2011
comment
Я хотел бы отсортировать узлы по данным/типу и использовать их впоследствии. Как мне сделать отсортированную копию этого узла? - person RRZ Europe; 13.05.2011

Это решение теперь работает для меня:

    <xsl:variable name="sortedcopy">
      <xsl:for-each select="node1/node2/node3/data">
        <xsl:sort select="type" order="ascending"/>
        <xsl:copy-of select="current()"/>
      </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="relItems" select="MSXML:node-set($sortedcopy)" />
    <xsl:for-each select="$relItems/data">
      <xsl:if test="not(preceding-sibling::data[1]/id = id)">
        <hr/>
      </xsl:if>
      <xsl:value-of select="val"/>
    </xsl:for-each>
person RRZ Europe    schedule 13.05.2011
comment
Рад, что предложение помогло. Я действительно думаю, как указал каждый из ответивших, у вас была бы лучшая производительность, если бы вы использовали рекомендуемые функции группировки, такие как Meunchian. - person LarsH; 14.05.2011
comment
node-set() является проприетарной функцией и не является частью стандарта XSL 1.0, так что это не будет портативный. - person vallismortis; 02.10.2015

Отношения узлов друг к другу — родительский, дочерний, одноуровневый и т. д. — не изменяются при сортировке. Вы можете просмотреть сотрудников в порядке даты рождения, но у них все еще будут те же родители, дети и братья и сестры, что и в исходном дереве, потому что они все еще являются узлами в исходном дереве.

Итак, вы сказали, как хотите решить свою проблему, и это не сработает. Следующий шаг — сообщить нам, в чем проблема.

person Michael Kay    schedule 12.05.2011
comment
Это не дает ответа на вопрос. Чтобы подвергнуть критике или запросить разъяснения у автора, оставьте комментарий под его публикацией. - person Dijkgraaf; 05.10.2015
comment
Я бы сказал, что ваш вопрос бессвязен, и поэтому является ответом. Это не решение проблемы ОП, а ответ на их вопрос. - person Michael Kay; 05.10.2015
comment
Если кто-то еще, как и я, попадет сюда через Google, Майкл Кей предоставил ответ на аналогичный вопрос здесь. - person J. Roovers; 03.06.2021

Поскольку XSLT гарантирует, что элементы с одинаковыми ключами сортировки будут отображаться в порядке документа, вы можете заменить

<xsl:when test="preceding-sibling::data[1]/type != type">

с участием

<xsl:when test="not(preceding::data/type = type)">

чтобы проверить, является ли текущий узел первым узлом в документе (и, следовательно, в отсортированном наборе) с его типом. (Обратите внимание, что я использую preceding вместо preceding-sibling, так как я не знаю, будут ли все ваши элементы данных одноуровневыми в исходном документе.)

Если производительность является проблемой, вы также можете использовать xsl:key. Другим решением является группировка (с использованием мюнхианской группировки в XSLT 1.0 и xsl:for-each-group в XSLT 2.0).

person markusk    schedule 13.05.2011
comment
Замена мне не подошла. Первая группа создается, как и ожидалось (<group><data type="type1" value="v1"/><data type="type1" value="v2"/></group>), но остальные группы дублируются (<group><data type="type2" value="v1"/></group> <group><data type="type2" value="v2"/></group> вместо ожидаемого <group><data type="type2" value="v1"/><data type="type2" value="v2"/></group>). - person Julien Kronegg; 26.06.2013