Таблица, сгенерированная повторением XSLT - PullRequest
3 голосов
/ 26 января 2012

У меня проблемы с таблицей, которую я генерирую из XSLT.

Мой XML - это рецепт.Любая строка, выделенная жирным шрифтом, будет отформатирована в виде таблицы.Моя проблема в том, что таблица дублируется на выходе.Я пробовал разные сценарии группировки, но мне не удалось решить проблему.У кого-нибудь есть понимание того, что мне не хватает?Спасибо.

XML:

<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Ingredients</p>
<p><b>1 cup of flour</b></p>
<p><b>2 eggs</b></p>
<p><b>1/4 stick of butter</b></p>
<p><b>1/4 cup of sugar</b></p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>

Код:

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

<xsl:strip-space elements="*" />

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
</xsl:template>

<xsl:template match="*/p/b" >
    <table>
      <xsl:apply-templates  select="//b" mode="test"/>
    </table>
</xsl:template>

<xsl:template match="//b" mode="test">
 <tr>
<td>
  <xsl:value-of select="substring-before(., ' ')" />
</td>
<td>
  <xsl:value-of select="substring-after(., ' ')" />
</td> 
</tr>
</xsl:template>

</xsl:stylesheet>

Выход:

<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>

<p>Ingredients</p>
<p><table><tr><td>1</td><td>cup of flour</td></tr>
<tr><td>2</td><td>eggs</td></tr>
<tr><td>1/4</td><td>stick of butter</td></tr>
<tr><td>1/4</td><td>cup of sugar</td></tr>
</table></p>

<p><table><tr><td>1</td><td>cup of flour</td></tr>
<tr><td>2</td><td>eggs</td></tr>
<tr><td>1/4</td><td>stick of butter</td></tr>
<tr><td>1/4</td><td>cup of sugar</td></tr>
</table></p>

<p><table><tr><td>1</td><td>cup of flour</td></tr>
<tr><td>2</td><td>eggs</td></tr>
<tr><td>1/4</td><td>stick of butter</td></tr>
<tr><td>1/4</td><td>cup of sugar</td></tr>
</table></p>

<p><table><tr><td>1</td><td>cup of flour</td></tr>
<tr><td>2</td><td>eggs</td></tr>
<tr><td>1/4</td><td>stick of butter</td></tr>
<tr><td>1/4</td><td>cup of sugar</td></tr>
</table></p>

<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>
<p>Some text goes here</p>

Ответы [ 2 ]

2 голосов
/ 26 января 2012

Это простое преобразование (нет xsl:if, нет count(), нет preceding-sibling:: ось) является лишь небольшой модификацией предоставленного кода :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="p[b][1]/b" >
        <table>
          <xsl:apply-templates  select="//b" mode="test"/>
        </table>
    </xsl:template>

    <xsl:template match="//b" mode="test">
     <tr>
    <td>
      <xsl:value-of select="substring-before(., ' ')" />
    </td>
    <td>
      <xsl:value-of select="substring-after(., ' ')" />
    </td>
    </tr>
    </xsl:template>

    <xsl:template match="p[b][position() > 1]"/>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<t>
    <p>Some text goes here</p>
    <p>Some text goes here</p>
    <p>Some text goes here</p>
    <p>Some text goes here</p>
    <p>Ingredients</p>
    <p><b>1 cup of flour</b></p>
    <p><b>2 eggs</b></p>
    <p><b>1/4 stick of butter</b></p>
    <p><b>1/4 cup of sugar</b></p>
    <p>Some text goes here</p>
    <p>Some text goes here</p>
    <p>Some text goes here</p>
    <p>Some text goes here</p>
</t>

дает желаемый результат :

<t>
   <p>Some text goes here</p>
   <p>Some text goes here</p>
   <p>Some text goes here</p>
   <p>Some text goes here</p>
   <p>Ingredients</p>
   <p>
      <table>
         <tr>
            <td>1</td>
            <td>cup of flour</td>
         </tr>
         <tr>
            <td>2</td>
            <td>eggs</td>
         </tr>
         <tr>
            <td>1/4</td>
            <td>stick of butter</td>
         </tr>
         <tr>
            <td>1/4</td>
            <td>cup of sugar</td>
         </tr>
      </table>
   </p>
   <p>Some text goes here</p>
   <p>Some text goes here</p>
   <p>Some text goes here</p>
   <p>Some text goes here</p>
</t>
1 голос
/ 26 января 2012

Ты почти у цели!

Ваша проблема заключается в том, как вы обрабатываете b [старые] узлы. Используя // b, вы эффективно выбираете не ту ось, чтобы вы выбрали все 4 узла b (отсюда и повторение).

Следующее преобразование выводит следующий результат на моей машине:

    <?xml version="1.0" encoding="utf-8"?>
        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html"/>
  <xsl:strip-space elements="*" />

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*/p[b]" >
    <xsl:if test="count(preceding-sibling::p[b]) = 0">
      <table>
          <xsl:apply-templates  select="parent::node()//b" mode="test"/>
      </table>
    </xsl:if>
  </xsl:template>

  <xsl:template match="b" mode="test">
    <tr>
      <td>
        <xsl:value-of select="substring-before(., ' ')" />
      </td>
      <td>
        <xsl:value-of select="substring-after(., ' ')" />
      </td>
    </tr>
  </xsl:template>

        </xsl:stylesheet>

Результат:

<Recipe>
  <p>Some text goes here</p>
  <p>Some text goes here</p>
  <p>Some text goes here</p>
  <p>Some text goes here</p>
  <p>Ingredients</p>
  <table>
    <tr>
      <td>1</td>
      <td>cup of flour</td>
    </tr>
    <tr>
      <td>2</td>
      <td>eggs</td>
    </tr>
    <tr>
      <td>1/4</td>
      <td>stick of butter</td>
    </tr>
    <tr>
      <td>1/4</td>
      <td>cup of sugar</td>
    </tr>
  </table>
  <p>Some text goes here</p>
  <p>Some text goes here</p>
  <p>Some text goes here</p>
  <p>Some text goes here</p>
</Recipe>

(Обратите внимание, что ваш оригинальный фрагмент XML заключен в узел для создания правильно сформированного документа)

Как это работает? Дело в том, сколько раз мы сопоставляем шаблон p / b - хотя он существует четыре раза, нам нужна только одна таблица со всеми последующими узлами b как дочерними.

Итак, мы проверяем первый p с дочерним элементом b p[b], подсчитывая, сколько раз этот шаблон встречался раньше - count(preceding-sibling::p[b]) = 0 дает мне первый. Затем мы поднимаемся обратно на узел и выбираем отсюда всех детей b.

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