Проблема с XSL 1.0 <xsl: for-each> и <call-template> - PullRequest
0 голосов
/ 11 июня 2009

Пожалуйста, просмотрите мой код и дайте мне совет по этому вопросу:

XML-файл: content.xml:

<content>
<page id="page-1">
<!-- ... -->
<block-center>
  <block-center-row id="block-center-row-1">
    <cd>
      <title>Empire Burlesque</title>
      <artist>Bob Dylan</artist>
      <country>USA</country>
      <company>Columbia</company>
      <price>10.90</price>
      <year>1985</year>
    </cd>
    <cd>
      <title>Hide your heart</title>
      <artist>Bonnie Tyler</artist>
      <country>UK</country>
      <company>CBS Records</company>
      <price>9.90</price>
      <year>1988</year>
    </cd>
  </block-center-row>
  <block-center-row id="block-center-row-2">
    <block-center-colunm id="block-center-2-1">
      <book>
        <title>Book Title1</title>
        <author>Book Author1</author>
      </book>
      <book>
        <title>Book Title2</title>
        <author>Book Author2</author>
      </book>
      <book>
        <title>Book Title3</title>
        <author>Book Author3</author>
      </book>
    </block-center-colunm>
    <block-center-colunm id="block-center-2-2">
      <seminar>
        <author>Seminar author1</author>
        <durable>3</durable>
      </seminar>
      <seminar>
        <author>Seminar author2</author>
        <durable>1.5</durable>
      </seminar>
      <seminar>
        <author>Seminar author3</author>
        <durable>2</durable>
      </seminar>
      <seminar>
        <author>Seminar author4</author>
        <durable>3</durable>
      </seminar>
    </block-center-colunm>
  </block-center-row>
</block-center>
</page>
<!-- ... -->
</content>

XSL-файл: block-center-1-1.xsl:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template name="block-center-row-1">
    <div class="block-center-row">
      <h2>My CD Collection</h2>
      <table border="1" width="100%">
        <tr bgcolor="#9acd32">
          <th>Title</th>
          <th>Artist</th>
        </tr>
        <xsl:for-each select="
          content/page[@id=$pageId]/block-center/
          block-center-row[@id='block-center-row-1']/cd
        ">
          <tr>
            <td>
              <xsl:value-of select="title" />
            </td>
            <xsl:choose>
              <xsl:when test="price &gt; 10">
                <td bgcolor="#ff00ff">
                  <xsl:value-of select="artist" />
                </td>
              </xsl:when>
              <xsl:when test="price &gt; 9">
                <td bgcolor="#cccccc">
                  <xsl:value-of select="artist" />
                </td>
              </xsl:when>
              <xsl:otherwise>
                <td>
                  <xsl:value-of select="artist" />
                </td>
              </xsl:otherwise>
            </xsl:choose>
          </tr>
        </xsl:for-each>
      </table>
    </div>
  </xsl:template>
</xsl:stylesheet>

XSL-файл block-center.xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="block-center-1-1.xsl" />
  <xsl:template name="block-center">
    <!-- if put here. It work properly -->
    <div class="block-center"> 
      <xsl:for-each select="content/page[@id=$pageId]/block-center/block-center-row">
        <xsl:choose>
          <!-- // I does not work here --> 
          <xsl:when test="@id='block-center-row-1'">
            <xsl:call-template name="block-center-row-1" />
          </xsl:when>
        </xsl:choose>
      </xsl:for-each>
    </div>
  </xsl:template>
</xsl:stylesheet>

Я не знаю, почему это не работает (если не положить данные), если я вызываю <xsl:call-template> внутри <xsl:for-each> цикла. В остальном все нормально.

Ответы [ 3 ]

2 голосов
/ 11 июня 2009

У меня есть несколько замечаний. Во-первых, плохая идея использовать формат в XML. Наличие элементов, которые называются <block-center> или <block-center-colunm>, не только неоправданно многословно, но и заставит вашу голову болеть, как только их содержимое больше не будет отображаться в блоке в центре.

Во-вторых, отпустите <xsl:call-template> и <xsl:for-each>. Они могут показаться удобными, если у вас есть опыт процедурного программирования, но это неправильный выбор. Вместо этого используйте <xsl:apply-templates>, это приведет к тому, что код станет чище и проще для понимания.

Теперь к вашему XSL. Ваш второй XSL (block-center.xsl) - что он делает? Почему у вас есть два отдельных файла XSL? Также отсутствует объявление переменной или параметра. Я использовал:

<xsl:variable name="pageId" select="'page-1'" />

для моих тестов. У него также есть только один шаблон (<xsl:template name="block-center">), который фактически никогда не вызывается, поэтому он ничего не сделал для меня. Я добавил

<xsl:template match="/">
  <xsl:call-template name="block-center" />
</xsl:template>

так что он хотя бы что-нибудь сделает.

Ваш другой XSL-файл (block-center-1-1.xsl) имеет цикл for-each, который не смотрит в нужный контекст. Вы уже находитесь в следующем контексте при вводе шаблона "block-center-row-1 ":

content/page[@id=$pageId]/block-center/block-center-row

, поэтому все, что вам нужно сделать в цикле for-each:

<xsl:for-each select="cd">

и он начнет выводить все <cd> узлы.

0 голосов
/ 11 июня 2009

Большое спасибо за ваш эйтузиазм! Это теперь работает правильно, если я изменяю в файле block-center-1-1.xsl К

ИЛИ

0 голосов
/ 11 июня 2009

Может измениться:

<xsl:for-each select="content/page[@id=$PageId]/block-center/block-center-row">

в

<xsl:for-each select="/content/page[@id=$PageId]/block-center/block-center-row">

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

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