Используйте XSLT для форматирования элементов XML в HTML в наборах из двух - PullRequest
2 голосов
/ 30 марта 2011

У меня есть следующий набор данных XML (упрощенный), где я могу иметь от нуля до бесконечных элементов (обычно их будет 2-10):

<item template="event_element">
   <mytitle>This is the first title</mytitle>
   <mydate>20110330T143004</mytitle>
   <mydescription>This is the first description</mytitle>
   <mylink>www.example.com</mytitle>
</item>
.
.
<item template="event_element">
   <mytitle>This is the Tenth title</mytitle>
   <mydate>20110330T143004</mytitle>
   <mydescription>This is the tenth description</mytitle>
   <mylink>www.example.com</mytitle>
</item>

Мой конечный результат должен быть таким, где я могу получить несколько наборов элементов (которые будут поворачиваться при помощи javascript):

<div class="body">
<div class="rel" id="arrangement">

    // First set of items goes here
    <div class="item">
        <div class="itm">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>MY DATE</span>
                        <strong>MY FIRST TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="itm last">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>30. mar 2011</span>
                        <strong>MY SECOND TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="clr"></div>
    </div>

    // Second set of items goes here
    <div class="item">
        <div class="itm">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>MY DATE</span>
                        <strong>MY THIRD TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="itm last">
            <div class="in">
                <p>
                    <a href="MY LINK" title="MY LINK DESCRIPTION">
                        <span>30. mar 2011</span>
                        <strong>MY FORTH TITLE</strong>
                        MY SHORT DESCRIPTION...
                    </a>
                </p>
            </div>
        </div>
        <div class="clr"></div>
    </div>

    <div class="clr"></div>
</div>

Моя проблема состоит в том, чтобы пройтись по моим элементам (которые должны быть даже отсортированы по дате desc) и сгруппировать их в наборы по два.

Как и сегодня, я был вынужден жестко закодировать такие наборы (переменные $ eventfolder, $ totalevents были предопределены):

<pre><code><div class="body">
  <div class="rel" id="arrangement">
    <xsl:if test="$totalevents &gt; 0">
      <div class="item">
        <xsl:for-each select="$eventfolder/item[@template='event_element' and position() &gt; 0 and position() &lt; 3]">
          <xsl:choose>
            <xsl:when test="position() &lt; $eventsperpage">        
          <div class="itm">
            <xsl:call-template name="renderEvent" />    
              </div>
            </xsl:when>
            <xsl:otherwise>
          <div class="itm last">
            <xsl:call-template name="renderEvent" />    
              </div>
              <div class="clr"></div>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each>     
      </div>
    </xsl:if>

    <xsl:if test="$totalevents &gt; 2">
      <div class="item">
        <xsl:for-each select="$eventfolder/item[@template='event_element' and position() &gt; 2 and position() &lt; 5]">
          <xsl:choose>
            <xsl:when test="position() &lt; $eventsperpage">        
          <div class="itm">
            <xsl:call-template name="renderEvent" />    
              </div>
            </xsl:when>
          <xsl:otherwise>
        <div class="itm last">
          <xsl:call-template name="renderEvent" />  
            </div>
            <div class="clr"></div>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>       
    </div>
  </xsl:if>

   <div class="clr"></div>
 </div>
</div>

Шаблон renderElement просто отображает внутреннее событие HTML.

Но этот способ не очень практичен, если я хотел показать больше наборов, чем 2 - или даже показать больше элементов в каждом наборе ... Файл xslt был бы большим и нечитаемым ...

Любая помощь в том, как я могу решить эту проблему, поскольку я не могу понять, как вставить HTML-теги, поскольку компилятор XSLT не может видеть их закрывающимися - т.е. (когда test="position() = 1 вставить начальный тег html, а затем позже, когда test="position() = X закрыть тег).

Заранее спасибо

Ответы [ 3 ]

1 голос
/ 30 марта 2011

Относительно:

Любая помощь в том, как я могу решить эту проблему, так как я не могу понять, как вставить HTML-теги, поскольку компилятор XSLT не может видеть их закрытыми - т.е.(когда test="position() = 1 вставьте html начальный тег, а затем, когда test="position() = X закройте тег).

Вы думаете о проблеме неправильно.XSLT генерирует деревья, а не теги.Вы создаете элементы, а не их половины.

Следующая таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--  the number of items to include in each group -->
    <xsl:variable name="group" select="2" />
    <xsl:template match="/">
        <xsl:apply-templates
            select="events/item[@template='event_element']
                               [(position() - 1)  mod $group = 0]" />
    </xsl:template>
    <xsl:template match="item[@template='event_element']" mode="inner">
        <div class="itm">
            <div class="in">
                <p>
                    <a href="{mylink}" title="{mydescription}">
                        <span><xsl:value-of select="mydate" /></span>
                        <strong><xsl:value-of select="mytitle" /></strong>
                        <xsl:value-of select="mydescription" />
                    </a>
                </p>
            </div>
        </div>
    </xsl:template>
    <xsl:template match="item[@template='event_element']">
        <div class="item">
            <xsl:apply-templates
                select=".|following-sibling::item[@template='event_element']
                                                 [position() &lt; $group]"
                mode="inner" />
            <div class="clr" />
        </div>
    </xsl:template>
</xsl:stylesheet>

Применяется к этому входу:

<events>
<item template="event_element">
   <mytitle>This is the first title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the first description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the second title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the third title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the fourth title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
<item template="event_element">
   <mytitle>This is the fifth title</mytitle>
   <mydate>20110330T143004</mydate>
   <mydescription>This is the tenth description</mydescription>
   <mylink>www.example.com</mylink>
</item>
</events>

Создает следующий вывод:

<div class="item">
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the first description">
                    <span>20110330T143004</span>
                    <strong>This is the first title</strong>
                    This is the first description
                </a>
            </p>
        </div>
    </div>
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the second title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="clr" />
</div>
<div class="item">
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the third title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the fourth title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="clr" />
</div>
<div class="item">
    <div class="itm">
        <div class="in">
            <p>
                <a href="www.example.com" title="This is the tenth description">
                    <span>20110330T143004</span>
                    <strong>This is the fifth title</strong>
                    This is the tenth description
                </a>
            </p>
        </div>
    </div>
    <div class="clr" />
</div>

Измените количество элементов, включаемых в каждую группу, изменив значение переменной group.

1 голос
/ 30 марта 2011

Не вдаваясь в более крупные проблемы, возникающие при вашем подходе, в XSLT способ группировки списка элементов по n элементов за раз заключается в следующем:

<xsl:apply-templates select="*[(position()-1) mod $n = 0]" mode="group"/>

..., который будет применять групповуюшаблон режима для первого, n + 1-го, 2n + 1-го и т. д. дочерних элементов текущего элемента.Шаблон группового режима выглядит следующим образом:

<xsl:template match="*" mode="group">
   <group>
      <xsl:apply-templates 
           select=".|following-sibling::*[position() &lt; $n]"/>
   </group>
</xsl:template>

Это создает элемент group и в этом элементе применяет шаблоны к текущему элементу и его n-1 следующим братьям и сестрам.

Чистый эффект состоит в том, что до тех пор, пока n является положительным целым числом, приведенное выше будет создавать group элементов, содержащих n последовательных элементов из исходного дерева.В вашем примере вы бы создали div вместо group, среди других изменений.

0 голосов
/ 30 марта 2011
<xsl:template match="items">
<div>
<xsl:apply-template select="item"/>
</div>
</xsl:template>

<xsl:apply-templates match="item">
do stuff here
</xsl:apply-templates>

Вы используете что-то похожее на это?

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