XSLT分组表行

XSLT分组表行,xslt,Xslt,我有这个表(用CSS div{display:table;}完成) 正文1正文a 文本2文本b 文本3文本c 文本4文本d 文本5文本e 基于class=“indent”行紧跟在前一行之后的事实,我希望这两行合并(并以表格形式显示),如下所示: <table> <tr><td><p>text 1</p></td><td><p>text a</p></td>

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


正文1

正文a

文本2

文本b

文本3

文本c

文本4

文本d

文本5

文本e

基于class=“indent”行紧跟在前一行之后的事实,我希望这两行合并(并以表格形式显示),如下所示:

     <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>

正文1

正文a

文本2

文本b

正文3

正文4

正文b

正文d

文本5

文本e

实验让我走了这么远,但显然还不起作用:

    <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>

它只给我第一排。我觉得这不能用分组来完成,因为不能用某个键来标识组,只能通过下面元素的类名来标识。
欢迎任何建议。

第一眼看到的明显错误:将
self::following sibling
更改为
following sibling::div
。您想要的是下一个
同级节点,而不是“如果它是
,则此节点”

第一眼看到的明显错误:将
self::following sibling
更改为
following sibling::div
。您想要的是下一个
同级节点,而不是“如果它是
,则此节点”

当我处理
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>

正如Tobias在一篇评论中正确指出的那样,可以消除一个模板,并简单地推送任何以下同级内容(如果存在):

<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>

当我处理
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>

正如Tobias在一篇评论中正确指出的那样,可以消除一个模板,并简单地推送任何以下同级内容(如果存在):

<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>

谢谢你的精力。 我是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>

谢谢你的精力。 我是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>


我认为这可以通过分组来实现,按照您当前尝试的方式,但是您的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>

我认为这可以通过分组来实现,按照您当前尝试的方式,但是您的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>


您不需要最后一个模板,只需将其内容放入
中即可。如果没有直接跟随的带有缩进的div,它无论如何都不会应用。@TobiasKlevenz,你是对的,我已经编辑并提供了实现该更改的第二个示例。你不需要最后一个模板,只需将其内容放在
中即可。如果没有直接跟随的带有缩进的div,它无论如何都不会应用。@TobiasKlevenz,你是对的,我已经编辑并提供了实现该更改的第二个示例。你的示例输出有两次“文本b”,而完全没有“文本c”。第二个“文本b”应该是“文本c”吗?是的。很抱歉,您的示例输出有两次“文本b”,而“文本c”根本没有。第二个“文本b”应该是“文本c”吗?是的。很抱歉输入了+1。不仅如此,您只需要下一个
同级元素(单数),而不是下面的所有同级::div元素。所以,
下面的兄弟::div[1]
+1。不仅如此,您只需要下一个
同级元素(单数),而不是下面的所有同级::div元素。所以,
下面的兄弟::div[1]
。很好。柜台有点难看,但我看不到消除它的方法。下一件事是给文本4

和文本d

都class='indent'。但也许在CSS中做得更好(而不是(第一个孩子))。很好。柜台有点难看,但我看不到消除它的方法。下一件事是给文本4

和文本d

都class='indent'。但也许在CSS中做得更好(而不是(第一个孩子))。