2015-02-23 4 views
0

Я хочу сделать sipmle 'Muenchian grouping' в xslt 1.0, но также с добавлением поиска подстановки из другого узла.Группировка с подстановочным знаком в XSLT 1.0

Я знаком с методом группировки, и это хорошо работает, но у меня проблемы с шаблоном, поскольку он всегда показывает заголовки групп, которые не имеют подстановочного поиска.

Вот мой XML:

<objects> 
<object> 
    <output_title>This is a title</output_title> 
    <output_year>2011</output_year> 
</object> 
<object> 
    <output_title>This is my title</output_title> 
    <output_year>2012</output_year> 
</object> 
<object> 
    <output_title>This is also my title</output_title> 
    <output_year>2012</output_year> 
</object> 
<object> 
    <output_title>This is another my title</output_title> 
    <output_year>2012</output_year> 
</object> 
<object> 
    <output_title>This is my title</output_title> 
    <output_year>2014</output_year> 
</object> 
<object> 
    <output_title>This is our title</output_title> 
    <output_year>2015</output_year> 
</object> 
</objects> 

Я хочу, чтобы вывести следующие данного подстановочные Seach строки 'мое':

<h4>2012</h4> 
<ol> 
<li>This is my title</li> 
<li>This is also my title</li> 
<li>This is another my title</li> 
</ol> 

<h4>2014</h4> 
<ol> 
<li>This is my title</li> 
</ol> 

Так заголовки '2011' и '2015' не должны появляться (но они делают, и это проблема)

Вот мой XSLT 1.0:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" version="1.0"> 
<xsl:param name="search"/> 

<!--Key for unique years--> 
<xsl:key name="uniqueOutputYearHeading" 
    match="contains(translate(objects/object/output_title,$uppercase,$lowercase),translate($search,$uppercase,$lowercase))" 
    use="output_year"/> 

<xsl:template match="/"> 

<!-- Generate the unique year headings--> 
<xsl:for-each select="//object[generate-id(.)=generate-id(key('uniqueOutputYearHeading',output_year))]"> 
<xsl:sort select="output_year" data-type="number" order="descending"/> 
<h4> 
<xsl:value-of select="output_year"/> 
</h4> 
<ol> 
<xsl:for-each select="key('uniqueOutputYearHeading',output_year)"> 
<xsl:for-each select="output_citation"> 
<xsl:if test="contains(translate(current(),$uppercase,$lowercase),translate($search,$uppercase,$lowercase))"> 
<li class="margin-bottom"> 
<xsl:copy-of select="current()"/> 
</li> 
</xsl:if> 
</xsl:for-each> 
</xsl:for-each> 
</ol>    
</xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

Но я получаю:

<h4>2011</h4> 

<h4>2012</h4> 
<ol> 
<li>This is my title</li> 
<li>This is also my title</li> 
<li>This is another my title</li> 

<h4>2014</h4> 
<ol> 
<li>This is my title</li> 
</ol> 

<h4>2015</h4> 

Я не могу показаться, чтобы получить «содержит» условие для работы на годы, только фактическое название. Я пробовал перемещать и дублировать его до заголовка года, но он ничего не возвращает. Также я не могу включить переменную поиска в исходную ключевую структуру, которая исправит проблему (я думаю).

ответ

1

Вы должны сделать это в два прохода. Сначала найдите узлы, которые соответствуют вашим критериям поиска. Затем примените Muenchian группировку к результату:

XSLT 1,0

<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:param name="search" /> 

<xsl:key name="object-by-year" match="object" use="output_year"/> 

<xsl:template match="/objects"> 
    <!-- first pass --> 
    <xsl:variable name="found-objects"> 
     <xsl:copy-of select="object[contains(., $search)]"/> 
    </xsl:variable> 
    <xsl:variable name="found-objects-set" select="exsl:node-set($found-objects)" /> 
    <!-- second (final) pass --> 
    <html> 
     <!-- switch context to the variable --> 
     <xsl:for-each select="$found-objects-set"> 
      <!-- for each distinct year ... --> 
      <xsl:for-each select="object[generate-id(.)=generate-id(key('object-by-year', output_year))]"> 
       <xsl:sort select="output_year" data-type="number"/> 
       <h4> 
        <xsl:value-of select="output_year"/> 
       </h4> 
       <!-- ... list the found objects in this year --> 
       <ol> 
        <xsl:for-each select="key('object-by-year', output_year)"> 
         <li><xsl:value-of select="output_title" /></li> 
        </xsl:for-each> 
       </ol> 
      </xsl:for-each> 
     </xsl:for-each> 
    </html> 
</xsl:template> 

</xsl:stylesheet> 

Применительно к вашему входному примеру, с параметром является строка "мой", то результат является:

<html> 
    <h4>2012</h4> 
    <ol> 
     <li>This is my title</li> 
     <li>This is also my title</li> 
     <li>This is another my title</li> 
    </ol> 
    <h4>2014</h4> 
    <ol> 
     <li>This is my title</li> 
    </ol> 
</html> 

Примечание: вы не можете использовать переменную в шаблоне соответствия ключа.

0

Это будет делать, я считаю:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="xml" indent="yes"/> 
<xsl:param name="search">my</xsl:param> 

<xsl:key name="uniqueOutputYearHeading" match="object" use="output_year"/> 

<xsl:template match="objects"> 
    <xsl:copy> 
     <xsl:for-each select="object[contains(output_title,$search)][generate-id() = generate-id(key('uniqueOutputYearHeading', output_year)[contains(output_title,$search)][1])]"> 
      <h4> 
       <xsl:value-of select="output_year"/> 
      </h4> 
      <ol> 
       <xsl:for-each select="key('uniqueOutputYearHeading', output_year)[contains(output_title,$search)]"> 
        <li> 
         <xsl:value-of select="output_title"/> 
        </li> 
       </xsl:for-each> 
      </ol> 
     </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
+0

Оба метода работали. Большое спасибо – kevmull