【问题标题】:XSLT: Split Ungrouped Data into chunksXSLT:将未分组的数据拆分为块
【发布时间】:2011-10-19 10:34:19
【问题描述】:

我要转

   <question>
      <static><![CDATA[Static Data]]></static>

      <debit-row />
      <debit-row />
      <credit-row />

      <header><![CDATA[Header HTML 1]]></header>
      <debit-row />
      <debit-row />
      <credit-row />
   </question>

进入

<p>Static Data</p>
<ul>
   <li>
      <table>
         <tr><td> debit row </td></tr>
         <tr><td> credit row </td></tr>
         <tr><td> credit row </td></tr>
      </table>
   </li>
   <li> Header HTML 1
      <table>
         <tr><td> debit row </td></tr>
         <tr><td> debit row </td></tr>
         <tr><td> credit row </td></tr>
      </table>
   </li>
</ul>

本质上,标题或借记行表示新块的开始。每个块都是一个列表项。每组或每行都是一个表格(通常,信用行总是排在最后,因此很容易判断何时开始表格)。

XSLT 和 XPATH 似乎非常困难,而且我很难查找我想做的任何事情,所以如果有人有很好的参考,我也会很感激。

我已经开始使用这个 xsl:

<xsl:template match="question">
   <xsl:apply-templates select="static|header|debit-row[preceding-sibling::*[1] != header]" />
</xsl:template>

这不是一个好的开始,因为模板根本不应用于任何借记行,但它们应该应用于第一个借记行(它前面没有标题元素)。那个表达有问题吗?

即使我让它发挥作用,我也需要找到一种方法来说“如果这是第一个标题或借记行,则打开 &lt;ul&gt;”,我不知道在申请时该怎么做标题/借记行模板。 debit-row 每个都有自己的 xml 来应用(它需要一个表行和 td)。我还必须在第一个借记行之前和最后一个贷记行之后适当地打开和关闭表格。

我非常感谢任何帮助,因为我什至无法让上面的简单 xpath 表达式正常工作。

【问题讨论】:

    标签: xslt xslt-2.0


    【解决方案1】:

    我。 XSLT 1.0 解决方案

    <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:key name="kFollowing"
      match="*[not(self::static or self::header)]"
      use="generate-id(preceding-sibling::*
                                  [self::static
                                  or
                                   self::header
                                  ][1]
                      )"/>
    
     <xsl:template match="/*[static]">
      <p><xsl:value-of select="static"/></p>
      <ul>
        <xsl:apply-templates select="static|header"/>
      </ul>
     </xsl:template>
    
     <xsl:template match="static|header">
      <li>
        <xsl:value-of select=
         "concat(self::header, '&#xA;')"/>
        <table>
         <xsl:apply-templates
           select="key('kFollowing', generate-id())"/>
        </table>
      </li>
     </xsl:template>
    
     <xsl:template match=
      "*/*[not(self::static or self::header)]">
      <tr>
        <td>
         <xsl:value-of select=
          "translate(name(),'-', ' ')"/>
        </td>
      </tr>
     </xsl:template>
    </xsl:stylesheet>
    

    应用于提供的 XML 文档时

    <question>
        <static><![CDATA[Static Data]]></static>
        <debit-row />
        <debit-row />
        <credit-row />
        <header><![CDATA[Header HTML 1]]></header>
        <debit-row />
        <debit-row />
        <credit-row />
    </question>
    

    产生想要的正确结果

    <p>Static Data</p>
    <ul>
       <li>
    
          <table>
             <tr>
                <td>debit row</td>
             </tr>
             <tr>
                <td>debit row</td>
             </tr>
             <tr>
                <td>credit row</td>
             </tr>
          </table>
       </li>
       <li>Header HTML 1
    <table>
             <tr>
                <td>debit row</td>
             </tr>
             <tr>
                <td>debit row</td>
             </tr>
             <tr>
                <td>credit row</td>
             </tr>
          </table>
       </li>
    </ul>
    

    解释:位置分组使用一个键来定义属于一个组的所有元素。


    二。 XSLT 2.0 解决方案

    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
    
     <xsl:template match="/*[static]">
      <p><xsl:value-of select="static"/></p>
      <ul>
        <xsl:for-each-group select="*"
             group-starting-with="static|header">
          <li>
            <xsl:value-of separator="&#xA;" select=
             "current-group()[1][self::header], ''"/>
            <table>
             <xsl:apply-templates
               select="current-group()[position() gt 1]"/>
            </table>
          </li>
        </xsl:for-each-group>
      </ul>
     </xsl:template>
    
     <xsl:template match=
      "*/*[not(self::static or self::header)]">
      <tr>
        <td>
         <xsl:value-of select=
          "translate(name(),'-', ' ')"/>
        </td>
      </tr>
     </xsl:template>
    </xsl:stylesheet>
    

    当这个 XSLT 2.0 转换应用于同一个 XML 文档(上图)时,同样会产生相同的正确结果

    <p>Static Data</p>
    <ul>
       <li>
          <table>
             <tr>
                <td>debit row</td>
             </tr>
             <tr>
                <td>debit row</td>
             </tr>
             <tr>
                <td>credit row</td>
             </tr>
          </table>
       </li>
       <li>Header HTML 1
    <table>
             <tr>
                <td>debit row</td>
             </tr>
             <tr>
                <td>debit row</td>
             </tr>
             <tr>
                <td>credit row</td>
             </tr>
          </table>
       </li>
    </ul>
    

    说明:使用带有group-starting-with 属性的XSLT 2.0 &lt;xsl:for-each-group&gt; 指令。也使用标准的 XSLT 2.0 函数current-group()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-06
      • 2013-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多