Проблемы предварительной сортировки XML перед преобразованием - PullRequest
0 голосов
/ 26 января 2012

Используя другой пример кода для stackoverflow, у нас есть постраничный отчет о печати с верхними и нижними колонтитулами (да, этот старый каштан), работающий хорошо, делая что-то вроде этого (где RESULTS_ROW имеет несколько дочерних узлов):

<xsl:variable name="n" select="number(4)"/>

<xsl:template match="RESULTS">
<body>
<div id="page">
  <output>
    <xsl:apply-templates select="RESULTS_ROW"/>
  </output>
</div>      
</body>
</xsl:template>

<xsl:template match="RESULTS_ROW">              
    <p/>
        [HTML FOR PAGE START]
        <br/>
    <xsl:for-each select=". | following-sibling::RESULTS_ROW[position() &lt; $n]">
        <xsl:value-of select="ITEM43"/><!--Lots more goes in here -->
            <br/>
    </xsl:for-each>
    [HTML FOR PAGE END]
        <p/>
</xsl:template>

Проблема возникла из-за необходимости сортировки RESULTS_ROW по одному из значений его дочерних узлов (ITEM43) до происходит преобразование в куски из 4 элементов, иначе сортировка не учитывает все дочерние узлы .

На данный момент вывод выглядит примерно так:

[HTML FOR PAGE START]
North
West
North
River
[HTML FOR PAGE END]

[HTML FOR PAGE START]
West
North
River
North
[HTML FOR PAGE END]

В то время как я хочу, чтобы узлы были закончены отсортированы до того, как они будут разбиты на группы, что-то вроде:

[HTML FOR PAGE START]
North
North
North
North
[HTML FOR PAGE END]

[HTML FOR PAGE START]
River    
River    
West
West
[HTML FOR PAGE END]

Я перепробовал все, что мог придумать мой не очень способный мозг XSL, но все виды сортировки, использование режимов для применения нескольких шаблонов к одному узлу, копирование, создание переменных, содержащих узловые значения и т. Д., Похоже, ничего не работает.

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

Ответы [ 2 ]

0 голосов
/ 28 января 2012

РЕДАКТИРОВАТЬ Правильно, после небольшого определения и проверки того, что именно following-sibling я думаю, у меня есть ваше решение:

following-sibling всегда будет обрабатываться из исходного документа, а не в том порядке, в котором он может быть в данный момент отсортирован. Это означает, что при печати следующих 4 узлов он берет следующие 4 узла в исходном документе в соответствии с порядком сортировки.

Вам нужно отсортировать список узлов перед применением шаблона из 4 строк (см. Пример кода ниже).

Теперь переменная SortedResults заполняется строкой, содержащей новый документ, отсортированный по мере необходимости. Используя node-set(), вы можете затем преобразовать его обратно в XML и затем применить шаблон.

В исходном шаблоне RESULTS есть еще одна проблема, которая повлияла на ваши результаты. Вы вызывали apply-templates по каждой строке, поэтому выводили следующих четырех братьев и сестер после каждой строки в документе. Это можно решить с помощью оператора mod, показанного ранее, чтобы гарантировать, что результаты выводятся только для каждой четвертой строки.

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:exslt="http://exslt.org/common" extension-element-prefixes="exslt">

<xsl:variable name="n" select="number(4)"/>

<xsl:template match="RESULTS">
    <xsl:variable name="SortedResults">
        <xsl:apply-templates select="RESULTS_ROW" mode="sort">
            <xsl:sort select="ITEM43"/>
        </xsl:apply-templates>
    </xsl:variable>

    <xsl:variable name="SortedResultsNodeSet" select="exslt:node-set($SortedResults)" />

    <body>
        <div id="page">
            <output>
                <xsl:apply-templates select="$SortedResultsNodeSet/RESULTS_ROW[position() mod $n = 1]" />
            </output>
        </div>
    </body>
</xsl:template>

<xsl:template match="RESULTS_ROW" mode="sort">
    <xsl:copy-of select="current()"/>
</xsl:template>

<xsl:template match="RESULTS_ROW">

    <p/>
    [HTML FOR PAGE START]
    <br/>
    <xsl:for-each select=". | following-sibling::RESULTS_ROW[position() &lt; $n]">
        <xsl:value-of select="ITEM43"/>
        <br/>
    </xsl:for-each>
    [HTML FOR PAGE END]
    <p/>

</xsl:template>

</xsl:stylesheet>

Обратите внимание, что добавлено дополнительное пространство имен, чтобы можно было использовать метод расширения node-set().

0 голосов
/ 26 января 2012

Вы должны иметь возможность добавить xsl:sort к вашему xsl:apply-templates для "RESULTS_ROW":

  <xsl:template match="RESULTS">
    <body>
      <div id="page">
        <output>
          <xsl:apply-templates select="RESULTS_ROW">
            <xsl:sort select="someElem" data-type="text" order="ascending"/>
          </xsl:apply-templates>
        </output>
      </div>      
    </body>
  </xsl:template>

Вам потребуется изменить select, и вам может потребоваться изменить data-typeorder в зависимости от вашего входа и желаемого выхода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...