XSLT-преобразование XML-документа в XHTML-документ - PullRequest
1 голос
/ 24 марта 2011

Вот мой шаблон:

<xsl:template name="rec">
  <xsl:for-each select="*">
    <div class="{local-name()}">
      <xsl:for-each select="@*">
        <xsl:attribute name="data-{local-name()}">
          <xsl:value-of select="."/>
        </xsl:attribute>
      </xsl:for-each>
      <xsl:value-of select="text()" />
      <xsl:call-template name="rec" />
    </div>
  </xsl:for-each>
</xsl:template>

Учитывая документ, подобный так:

<test>
  <item value="1">Item 1 Text</item>
  <item value="2">Item 2 Text</item>
</test>

Преобразование выше превратит его в:

<div class="test">
  <div class="item" data-value="1">Item 1 Text</div>
  <div class="item" data-value="2">Item 2 Text</div>
</div>

ПроблемаУ меня есть то, что это преобразование не уважает текстовые узлы должным образом, и у меня недостаточно фона с XSLT, чтобы выяснить, как это исправить.Вот проблема: учитывая xml, вот так:

<para>This is a <emphasis>paragraph</emphasis> people!</para>

Я хотел бы увидеть следующий вывод:

<div class="para">This is a <div class="emphasis">paragraph</div> people!</div>

Проблема в том, что я не получаю это - яполучить это:

<div class="para">This is a <div class="emphasis">paragraph</div></div>

Обратите внимание на пропавших "людей!"текстовый узел.Как я могу исправить мой XSLT выше, чтобы обеспечить мне вывод, который мне нужен?

1 Ответ

4 голосов
/ 24 марта 2011

Одна проблема заключается в том, что

  <xsl:value-of select="text()" />

просто выбирает значение первого дочернего текстового узла и выводит его.

Самый простой способ сделать это правильноВероятно, использовать <xsl:apply-templates> вместо <xsl:call-template>.

Тогда вместо

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

и

  <xsl:value-of select="text()" />

вы можете использовать

  <xsl:apply-templates />

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

Вот полная реализация:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="1.0">

   <xsl:template match="*">
      <div class="{local-name()}">
         <xsl:for-each select="@*">
            <xsl:attribute name="data-{local-name()}">
               <xsl:value-of select="."/>
            </xsl:attribute>
         </xsl:for-each>
         <xsl:apply-templates />
      </div>
   </xsl:template>

</xsl:stylesheet>

Обратите внимание на <xsl:apply-templates/>, который работает со всеми дочерними элементами узла контекста, включая текстовые узлы, по умолчанию при отсутствии явного атрибута select.

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

Пример ввода:

<test>
   <item value="1">Item 1 Text</item>
   <item value="2">Item 2 Text</item>
   <para>This is a <emphasis>paragraph</emphasis> people!</para>
</test>

производит желаемый вывод:

<div class="test">
   <div class="item" data-value="1">Item 1 Text</div>
   <div class="item" data-value="2">Item 2 Text</div>
   <div class="para">This is a <div class="emphasis">paragraph</div> people!</div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...