2012-01-26 5 views
0

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

<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 может думать, но все виды сортировки, используя режимы для применения нескольких шаблонов к одному узлу, копирования, создания переменных, содержащих узловые значения и т. д. - ничего не работает.

Любая помощь была бы действительно оценена.

+0

Не могли бы вы показать пример ввода XML? –

+0

@DevNull XML, действительно плоский и довольно проста: ' \t \t \t \t \t \t Площадь \t \t \t Северный \t \t \t \t \t \t \t \t \t Площадь \t \t \t Западный \t \t \t \t \t \t \t \t \t \t Площадь \t \t \t North \t \t \t 'с много больше, чем другие item43 и label43 на том же уровне узлов, которые я оставил из – DanH

ответ

0

EDIT вправо, после того, как немного определения и проверки, что именно following-sibling делает я думаю, что у меня есть свое решение:

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

Что вам нужно сделать, так это отсортировать список узлов перед применением вашего 4-строчного шаблона (см. Пример кода ниже).

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

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

<?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

спасибо за это. Это действительно работает, но, к сожалению, мои заполнители (т. Е. [HTML FOR PAGE END] имеют раскол html, поэтому верхний и верхний теги открыт вверх и закрыт внизу, и это не сработает, когда они заключены в IFs (и Я не могу придумать другой способ сделать это в XSLT, который хорошо сформирован) .Осторожное решение, хотя и простое, но умное. Спасибо, что нашли время для публикации. – DanH

+0

@DanH Вы правы, это довольно бесполезно для любого шаблона html. Я пересмотрел свой ответ, снова подумав об этом! – chrisn

+0

Это превосходно и делает именно то, что нам нужно. Я думаю, что вы можете быть каким-то гением ;-) Я знал, что мне нужно, но пару часов чтения didn «Даже поднимите меня, так что спасибо. Спасибо также за решение ошибки, которая значительно улучшила производительность (и результат). Я могу только начать понимать, как вы это решили, но это даст мне еще кое-что, о чем можно прочитать! Ты звезда ... – DanH

0

Вы должны быть в состоянии добавить 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-type и order в зависимости от вашего входа и желаемый результат.

+0

Спасибо DevNull, я пытался что-то подобное, но это сортирует элементы в группах, так что каждая группа из 4 сортируется по отношению друг к другу, но в пределах группы из 4 они все еще несортированы. То, что я пытался достичь, было все узлы (текст) отсортированы до разделения на группы по 4. – DanH

+0

Итак, вы на самом деле пытаетесь сортировать текстовые узлы? Пример XML-ввода с примером желаемого вывода будет очень полезен. –

+0

Yeahm thanks @DevNull лучшее объяснение, вероятно, поможет! – DanH

Смежные вопросы