XSLT Muenchian 分组到 HTML Table

XSLT Muenchian Grouping to HTML Table

这是我的 XML:

<Tree All="False">
  <Menu Type="Leaf">
    <Label>Menu 1</Label>
  </Menu>
  <Menu>
    <Label>Menu 2</Label>
  </Menu>
  <Menu>
    <Label>Menu 3</Label>
  </Menu>
  <Break />
  <Menu>
    <Label>Menu 4</Label>
  </Menu>
  <Menu>
    <Label>Menu 5</Label>
  </Menu>
  <Menu>
    <Label>Menu 6</Label>
  </Menu>
  <Menu>
    <Label>Menu 7</Label>
  </Menu>
  <Break />
  <Menu>
    <Label>Menu 8</Label>
  </Menu>
</Tree>

我正在尝试将节点转换为 HTML table,以 <Break /> 节点作为分隔符。预期的 HTML 输出是:

我能够使用 XSLT 1.0 通过 Muenchian 方法对节点进行分组。但现在我坚持将它们转换为 HTML table。这是我当前的 XSLT:

<xsl:key name="groups" match="Tree*[not(self::Break)]" use="count(preceding-sibling::Break)" />

<xsl:template match="Tree">
  <xsl:variable name="groupings" select="*[not(self::Break)][generate-id() = generate-id(key('groups', count(preceding-sibling::Break))[1])]" />
  <xsl:for-each select="$groupings">
    <xsl:sort select="count(key('groups', count(preceding-sibling::Break)))" order="descending" />
    <xsl:if test="position() = 1">
      <xsl:variable name="rows" select="count(key('groups', count(preceding-sibling::Break)))" />
      <xsl:call-template name="GroupTemplate">
        <xsl:with-param name="rows" select="$rows" />
        <xsl:with-param name="groupings" select="$groupings" />
      </xsl:call-template>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

<xsl:template name="GroupTemplate">
  <xsl:param name="rows" />
  <xsl:param name="groupings" />
  <table>
    <xsl:for-each select="$groupings">
      <xsl:variable name="group" select="key('groups', count(preceding-sibling::Break))" />
      <xsl:for-each select="$group[position() &lt;= $rows]">
        <xsl:value-of select="." />
      </xsl:for-each>
      <br></br>
    </xsl:for-each>
  </table>
</xsl:template>

我当前的代码给出了这个不正确的结果:

Menu 1 Menu 2 Menu 3

Menu 4 Menu 5 Menu 6 Menu 7

Menu 8

您已经正确地开始了,通过识别具有最大行数的组。您真正需要做的是在您的模板中添加一个 "for 1 to $maxorw",这在 XSLT 2.0 中可以做到,但在 1.0 中并不容易。不过,您可以做的是,不是传入最大行的值,而是传入具有最大行的组,然后从 select 开始。 'position' 然后为您提供所需的“1 到 4”。

试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" version="5.0" />
<xsl:key name="groups" match="Tree/*[not(self::Break)]" use="count(preceding-sibling::Break)" />

<xsl:template match="Tree">
  <xsl:variable name="groupings" select="*[not(self::Break)][generate-id() = generate-id(key('groups', count(preceding-sibling::Break))[1])]" />
  <xsl:for-each select="$groupings">
    <xsl:sort select="count(key('groups', count(preceding-sibling::Break)))" order="descending" />
    <xsl:if test="position() = 1">
      <xsl:variable name="maxRows" select="key('groups', count(preceding-sibling::Break))" />
      <xsl:call-template name="GroupTemplate">
        <xsl:with-param name="maxRows" select="$maxRows" />
        <xsl:with-param name="groupings" select="$groupings" />
      </xsl:call-template>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

<xsl:template name="GroupTemplate">
  <xsl:param name="maxRows" />
  <xsl:param name="groupings" />
  <table>
    <xsl:for-each select="$maxRows">
      <xsl:variable name="position" select="position()" />
      <tr>
        <xsl:for-each select="$groupings">
          <xsl:variable name="group" select="key('groups', count(preceding-sibling::Break))" />
          <td>
            <xsl:value-of select="normalize-space($group[position() = $position])" />
          </td>
        </xsl:for-each>
      </tr>
    </xsl:for-each>
  </table>
</xsl:template>
</xsl:stylesheet>