Как получить XSL для отображения результатов в нескольких столбцах? - PullRequest
2 голосов
/ 23 февраля 2012

Я создаю приложение, которое создает XML следующим образом:

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="MyCDCatalog.xsl"?>
<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd>
        <title>Greatest Hits</title>
        <artist>Dolly Parton</artist>
        <price>9.90</price>
        <year>1982</year>
    </cd>
    <cd>
        <title>One night only</title>
        <artist>Bee Gees</artist>
        <price>10.90</price>
        <year>1998</year>
    </cd>
    <cd>
        <title>Sylvias Mother</title>
        <artist>Dr.Hook</artist>
        <price>8.10</price>
        <year>1973</year>
    </cd>
    <cd>
        <title>Maggie May</title>
        <artist>Rod Stewart</artist>
        <price>8.50</price>
        <year>1990</year>
    </cd>
</catalog>

Я также XSL-файл с именем MyCDCatalog.xsl (ниже), который преобразует вышеуказанный XML-файл.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
      <xsl:for-each select="catalog/cd">
      <tr>
        <td><xsl:value-of select="artist" />'s <xsl:value-of select="title" /> (<xsl:value-of select="year" />):   $<xsl:value-of select="price" /></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

В настоящее время файл XSL возвращает все записи в одном столбце. Как получить вывод в 3 или более столбцах?

Я хочу вывод следующим образом:

[cd1] [cd2] [cd3]
[cd4] [cd5] [cd6]....

, где

cd1 = Bob Dylan's Empire Burlesque (1985): $10.90
cd2 = Bonnie Tyler's Hide your heart (1988): $9.90
etc.

Спасибо за помощь.

Ответы [ 3 ]

3 голосов
/ 23 февраля 2012

Другой способ сделать это - сопоставить cd в первой, четвертой, седьмой (и т. Д.) Позиции.

<xsl:apply-templates select="cd[(position() - 1) mod $columns = 0]" mode="first"/>

Где $ столбцы параметр, содержащий количество столбцов

. Затем вы можете сопоставить элементы cd в строке, посмотрев соответствующее число следующих братьев и сестер:

<xsl:apply-templates select=".|following-sibling::cd[position() &lt; $columns]"/>

Вотполный XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html" indent="yes" omit-xml-declaration="yes" />
   <xsl:param name="columns" select="3"/>

   <xsl:template match="/catalog">
      <html>
         <body>
            <h2>My CD Collection</h2> 
            <table>
               <xsl:apply-templates select="cd[(position() - 1) mod $columns = 0]" mode="first"/>
            </table>
         </body>
      </html>
   </xsl:template>

   <xsl:template match="cd" mode="first">
      <tr>
         <xsl:apply-templates select=".|following-sibling::cd[position() &lt; $columns]"/>
         <xsl:if test="count(following-sibling::cd) &lt; ($columns - 1)">
            <xsl:call-template name="emptycell">
               <xsl:with-param name="cells" select="$columns - 1 - count(following-sibling::cd)"/>
            </xsl:call-template>
         </xsl:if>
      </tr>
   </xsl:template>

   <xsl:template match="cd">
      <td>
         <xsl:value-of select="concat(title, &apos; &apos;, artist)"/>
      </td>
   </xsl:template>

   <xsl:template name="emptycell">
      <xsl:param name="cells"/>
      <td/>
      <xsl:if test="$cells &gt; 1">
         <xsl:call-template name="emptycell">
            <xsl:with-param name="cells" select="$cells - 1"/>
         </xsl:call-template>
      </xsl:if>
   </xsl:template>
</xsl:stylesheet>

При применении к вашему образцу XML выводится следующее:

<html>
   <body>
      <h2>My CD Collection</h2>
      <table>
         <tr>
            <td>Empire Burlesque Bob Dylan</td>
            <td>Hide your heart Bonnie Tyler</td>
            <td>Greatest Hits Dolly Parton</td>
         </tr>
         <tr>
            <td>One night only Bee Gees</td>
            <td>Sylvias Mother Dr.Hook</td>
            <td>Maggie May Rod Stewart</td>
         </tr>
      </table>
   </body>
</html>

(я вывожу только name и Artist здесь, но я уверен, что вы можете увидеть, как изменить его, чтобы показать больше информации)

Обратите внимание, что есть немного неприятного рекурсивного шаблона для вывода пустых ячеек, если количество оставшихся cd элементов должно быть меньше количества столбцов в строке.

Например, измените значение параметра на 4, после чего вы получите следующее:

<table>
  <tr>
    <td>Empire Burlesque Bob Dylan</td>
    <td>Hide your heart Bonnie Tyler</td>
    <td>Greatest Hits Dolly Parton</td>
    <td>One night only Bee Gees</td>
  </tr>
  <tr>
    <td>Sylvias Mother Dr.Hook</td>
    <td>Maggie May Rod Stewart</td>
    <td />
    <td />
  </tr>
</table>
2 голосов
/ 23 февраля 2012

В XSLT 1.0 используйте следующее:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes"/>
    <xsl:key name="grp" use="floor(count(preceding-sibling::cd) div 3)" match="catalog/cd"/>
    <xsl:template match="/">
        <html>
            <body>
                <h2>My CD Collection</h2>
                <table border="1">
                    <xsl:apply-templates
                        select="catalog/cd[generate-id() =
                            generate-id(key('grp',floor((position() - 1) div 3))[1])]"
                        mode="group"/>
                    <!-- note: index [1] is superfluous, because generate-id applied on node-set returns the id of the first element in the set -->
                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="catalog/cd" mode="group">
      <xsl:variable
          name="groupitems"
          select="key('grp', floor(count(preceding-sibling::cd) div 3))"/>
        <tr>
            <xsl:for-each select="$groupitems">
                <td>
                    <xsl:value-of select="artist" />'s <xsl:value-of select="title" /> (<xsl:value-of select="year" />): $<xsl:value-of select="price" />
                </td>
            </xsl:for-each>
        </tr>
    </xsl:template>
</xsl:stylesheet>

Пояснение: мюнхенская группировка. Создание ключа доставило мне небольшую головную боль, потому что сначала я пытался присвоить атрибуту use значение, относящееся к position (), но это не работает должным образом. На этом сайте я нашел другую ветку, объясняющую, что вместо этого использовать: ключ и позиция () проблема .

Выход желаемый:

<html>
    <body>
        <h2>My CD Collection</h2>
        <table border="1">
            <tr>
                <td>Bob Dylan's Empire Burlesque (1985): $10.90</td>
                <td>Bonnie Tyler's Hide your heart (1988): $9.90</td>
                <td>Dolly Parton's Greatest Hits (1982): $9.90</td>
            </tr>
            <tr>
                <td>Bee Gees's One night only (1998): $10.90</td>
                <td>Dr.Hook's Sylvias Mother (1973): $8.10</td>
                <td>Rod Stewart's Maggie May (1990): $8.50</td>
            </tr>
        </table>
    </body>
</html>
0 голосов
/ 23 февраля 2012

Edit3:

Два шаблона table_format и table_format2 сделают эту работу .. установить количество в глобальной переменной:

  <xsl:variable name="col_count" select="'3'"/>

col_count определяет количество столбцов:)

также помните, что я использовал

    <xsl:for-each select="catalog/cd[1]">

в первом шаблоне ..

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:variable name="col_count" select="'3'"/>

  <xsl:template match="/">
    <html>
      <body>
        <h2>My CD Collection</h2>
        <table border="1">
        <xsl:for-each select="catalog/cd[1]">
          <xsl:call-template name="table_format"/>
        </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template name="table_format">
    <xsl:param name="count" select="'1'"/>
      <tr>
        <xsl:call-template name="table_format2"/>
      </tr>
      <xsl:for-each select="../cd[$col_count + $count]">
        <xsl:call-template name="table_format">
          <xsl:with-param name="count" select="$count + $col_count"/>
        </xsl:call-template>
      </xsl:for-each>
  </xsl:template>

  <xsl:template name="table_format2">
    <xsl:param name="col_count2" select="1"/>
    <xsl:if test="$col_count2 &lt;= $col_count">
      <td>
        <xsl:value-of select="artist" />'s <xsl:value-of select="title" /> (<xsl:value-of select="year" />): $<xsl:value-of select="price" />
      </td>
      <xsl:for-each select="following-sibling::cd[1]">
        <xsl:call-template name="table_format2">
          <xsl:with-param name="col_count2" select="$col_count2 + 1"/>
        </xsl:call-template>
      </xsl:for-each>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...