XSLT分组表行

时间:2014-03-02 15:15:04

标签: xslt

我有这个表(用CSS div {display:table;}完成)

     <div class="wl">
     <div><div><p>text 1</p></div><div><p>text a</p></div></div>
     <div><div><p>text 2</p></div><div><p>text b</p></div></div>
     <div><div><p>text 3</p></div><div><p>text c</p></div></div>
     <div class="indent"><div><p>text 4</p></div><div><p>text d</p></div></div>
     <div><div><p>text 5</p></div><div><p>text e</p></div></div>
     </div>

基于class =“indent”行紧跟前一行的事实,我希望这两行合并(和tabled)如下:

     <table>
     <tr><td><p>text 1</p></td><td><p>text a</p></td></tr>
     <tr><td><p>text 2</p></td><td><p>text b</p></td></tr>
     <tr><td><p>text 3</p><p>text 4</p></td><td><p>text b</p><p>text d</p></td></tr>
     <tr><td><p>text 5</p></td><td><p>text e</p></td></tr>
     </table>

试验让我走到这一步,这显然还不起作用:

    <xsl:template match="div[contains(@class, 'wl')]">
<table>
<xsl:copy-of select="@*"/>
    <xsl:for-each-group select="node()" group-adjacent="boolean(self::following-sibling/@class='indent1')" >
    <tr>
    <xsl:copy-of select="@*"/>
    <xsl:for-each select="div">
    <td>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </td>
    </xsl:for-each>
    </tr>
</xsl:for-each-group>
</table>
</xsl:template>

它给了我第一行。我觉得这不能用分组来完成,因为不能用一些键来识别组,只能通过以下元素的类名来识别。 任何建议都会受到欢迎。

4 个答案:

答案 0 :(得分:2)

第一眼明显错误:将self::following-sibling更改为following-sibling::div。您想要下一个<div>兄弟,而不是“此节点,如果它是<following-sibling>

答案 1 :(得分:1)

当我处理div转换为td元素时,我只需将节点推送到正确的模板中:

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

<xsl:output method="html" indent="no"/>

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

<xsl:template match="div[contains(@class, 'wl')]">
  <table>
    <xsl:apply-templates select="@* , node()"/>
  </table>
</xsl:template>

<xsl:template match="div[contains(@class, 'wl')]/div">
  <tr>
    <xsl:apply-templates/>
  </tr>
</xsl:template>

<xsl:template match="div[contains(@class, 'wl')]/div[@class = 'indent']" priority="5"/>

<xsl:template match="div[contains(@class, 'wl')]/div/div">
  <td>
    <xsl:apply-templates/>
  </td>
</xsl:template>

<xsl:template match="div[contains(@class, 'wl')]/div[following-sibling::*[1][self::div[@class = 'indent']]]/div" priority="5">
  <xsl:variable name="pos"><xsl:number/></xsl:variable>
  <td>
    <xsl:apply-templates select="node() , ../following-sibling::*[1][self::div[@class = 'indent']]/div[position() = $pos]/node()"/>
  </td>
</xsl:template>

</xsl:stylesheet>

正如托比亚斯在评论中正确指出的那样,可以删除一个模板并简单地推送任何后续兄弟的东西:

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

<xsl:output method="html" indent="no"/>

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

<xsl:template match="div[contains(@class, 'wl')]">
  <table>
    <xsl:apply-templates select="@* , node()"/>
  </table>
</xsl:template>

<xsl:template match="div[contains(@class, 'wl')]/div">
  <tr>
    <xsl:apply-templates/>
  </tr>
</xsl:template>

<xsl:template match="div[contains(@class, 'wl')]/div[@class = 'indent']" priority="5"/>

<xsl:template match="div[contains(@class, 'wl')]/div/div">
  <xsl:variable name="pos"><xsl:number/></xsl:variable>
  <td>
    <xsl:apply-templates select="node() , ../following-sibling::*[1][self::div[@class = 'indent']]/div[position() = $pos]/node()"/>
  </td>
</xsl:template>

</xsl:stylesheet>

答案 2 :(得分:1)

我认为这可以通过分组来完成,就像您当前正在尝试的那样,但 xsl:for-each-group 可能需要看起来像这样:

<xsl:for-each-group select="div" group-starting-with="div[not(@class='indent')]">

然后,要获取构成行中每个单元格的元素,您可以用以下内容替换当前的 xsl:apply-templates

<xsl:variable name="pos" select="position()" />
<xsl:apply-templates select="current-group()/div[position()=$pos]/*" />

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output indent="yes"/>

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

    <xsl:template match="div[contains(@class, 'wl')]">
        <table>
            <xsl:copy-of select="@*"/>
            <xsl:for-each-group select="div" group-starting-with="div[not(@class='indent')]">
                <tr>
                    <xsl:copy-of select="@*"/>
                    <xsl:for-each select="div">
                    <td>
                        <xsl:copy-of select="@*"/>
                        <xsl:variable name="pos" select="position()" />
                        <xsl:apply-templates select="current-group()/div[position()=$pos]/*" />
                    </td>
                    </xsl:for-each>
                </tr>
            </xsl:for-each-group>
        </table>
    </xsl:template>
</xsl:stylesheet>

答案 3 :(得分:0)

感谢您的精力。 我是XSLT的新手,因为你现在必须知道,并且像疯了一样阅读XSLT。 你的意见是教育。 在您的帮助下,我找到了这个解决方案:

<xsl:template match="div[contains(@class, 'wl')]">
  <table>
  <xsl:for-each-group select="node()" group-starting-with="node()[not(contains(@class , 'indent'))]" >
  <tr>
    <td>
    <xsl:for-each select="current-group()">
          <p><xsl:value-of select="node()[1]"/></p>
    </xsl:for-each>
    </td>
    <td>
        <xsl:for-each select="current-group()">
      <p><xsl:value-of select="node()[2]"/></p>
    </xsl:for-each>
    </td>
  </tr>
</xsl:for-each-group>
</table>
</xsl:template>