XSLT Muenchian 分组在组内创建密钥 [英] XSLT Muenchian grouping create key inside group

查看:24
本文介绍了XSLT Muenchian 分组在组内创建密钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是首先按对节点进行分组,然后在每个组中,我想按<进行分组.ColumnBreak>.

My goal is to group the nodes first by <RowBreak>, then in each <RowBreak> group, I want to group by <ColumnBreak>.

这是我的 XML.

<?xml version="1.0" encoding="utf-8" ?>
<Tree>
  <Item>
    <Label>Item 1</Label>
  </Item>
  <Item>
    <Label>Item 2</Label>
  </Item>
  <ColumnBreak />
  <Item>
    <Label>Item 3</Label>
  </Item>
  <Item>
    <Label>Item 4</Label>
  </Item>
  <Item>
    <Label>Item 5</Label>
  </Item>
  <RowBreak />
  <Item>
    <Label>Item 6</Label>
  </Item>
  <Item>
    <Label>Item 7</Label>
  </Item>
  <ColumnBreak />
  <Item>
    <Label>Item 8</Label>
  </Item>
  <RowBreak />
  <Item>
    <Label>Item 9</Label>
  </Item>
  <Item>
    <Label>Item 10</Label>
  </Item>
</Tree>

输出应该是:

Item 1  Item 3
Item 2  Item 4
        Item 5

Item 6  Item 8
Item 7

Item 9
Item 10

我目前的 XSLT 是这样的:

My current XSLT is like this:

<?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" indent="yes"/>
  <xsl:key name="rowGroups" match="Tree/*[not(self::RowBreak)]" use="count(preceding-sibling::RowBreak)" />

  <xsl:template match="Tree">
    <xsl:variable name="rowGroupings" select="*[not(self::RowBreak)][generate-id() = generate-id(key('rowGroups', count(preceding-sibling::RowBreak))[1])]" />
    <xsl:variable name="position" select="position()" />
    <table>
      <xsl:for-each select="$rowGroupings">
        <xsl:variable name="rowId" select="generate-id()"/>
        <xsl:variable name="colGroupings" select="*[not(self::ColumnBreak)][generate-id()=$rowId][1]" />
        <tr>
            <xsl:for-each select="$colGroupings">
              <!--Do logic here to group by ColumnBreak-->
            </xsl:for-each>
        </tr>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>

但是,我在提取每个 中的 组时遇到问题(请参阅 colGroupings 变量).我想为循环中的每个 创建一个 (类似于 rowGroups),但根据我对 元素,它必须被声明为顶级并且匹配应该在实际节点上工作,而不是在变量上.

However, I'm getting problem with extracting the <ColumnBreak> groups in every <RowBreak> (see colGroupings variable). I want to create a <key> for every <RowBreak> in the loop (similar to rowGroups), but as per my understanding of <xsl:key> element, it has to be declared top-level and the match should work on actual nodes, not on variables.

推荐答案

这是我第一遍要做的:

XSLT 1.0

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

<xsl:template match="/Tree">
    <cells>
        <xsl:apply-templates select="Item[1]" mode="sibling">
            <xsl:with-param name="row" select="1"/>
            <xsl:with-param name="col" select="1"/>
        </xsl:apply-templates>  
    </cells>
</xsl:template>

<xsl:template match="Item" mode="sibling">
    <xsl:param name="row"/>
    <xsl:param name="col"/>
    <cell row="{$row}" col="{$col}">
        <xsl:value-of select="Label"/>
    </cell>
    <xsl:apply-templates select="following-sibling::*[1]" mode="sibling">
        <xsl:with-param name="row" select="$row"/>
        <xsl:with-param name="col" select="$col"/>
    </xsl:apply-templates>  
</xsl:template>

<xsl:template match="ColumnBreak" mode="sibling">
    <xsl:param name="row"/>
    <xsl:param name="col"/>
    <xsl:apply-templates select="following-sibling::*[1]" mode="sibling">
        <xsl:with-param name="row" select="$row"/>
        <xsl:with-param name="col" select="$col + 1"/>
    </xsl:apply-templates>  
</xsl:template>

<xsl:template match="RowBreak" mode="sibling">
    <xsl:param name="row"/>
    <xsl:param name="col"/>
    <xsl:apply-templates select="following-sibling::*[1]" mode="sibling">
        <xsl:with-param name="row" select="$row + 1"/>
        <xsl:with-param name="col" select="1"/>
    </xsl:apply-templates>  
</xsl:template>

</xsl:stylesheet>

应用于您的示例输入,这将产生:

Applied to your example input, this would produce:

结果

<?xml version="1.0" encoding="UTF-8"?>
<cells>
  <cell row="1" col="1">Item 1</cell>
  <cell row="1" col="1">Item 2</cell>
  <cell row="1" col="2">Item 3</cell>
  <cell row="1" col="2">Item 4</cell>
  <cell row="1" col="2">Item 5</cell>
  <cell row="2" col="1">Item 6</cell>
  <cell row="2" col="1">Item 7</cell>
  <cell row="2" col="2">Item 8</cell>
  <cell row="3" col="1">Item 9</cell>
  <cell row="3" col="1">Item 10</cell>
</cells>

这是可以实际使用的东西.

which is something that can be actually worked with.

这是一个完整的样式表,它分两遍处理输入:

Here's a complete stylesheet that processes the input in two passes:

  • 第一遍使用同级递归,如上所述;
  • 第二遍按行和列进行 Muenchian 分组,以生成原始文档描述的表格:

XSLT 1.0(带有 EXSLT node-set() 扩展函数)

XSLT 1.0 (with EXSLT node-set() extension function)

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="cell-by-row" match="cell" use="@row" />
<xsl:key name="cell-by-col" match="cell" use="concat(@row, '|', @col)" />

<xsl:template match="/Tree">
    <!-- first-pass -->
    <xsl:variable name="cells">
        <xsl:apply-templates select="Item[1]" mode="sibling">
            <xsl:with-param name="row" select="1"/>
            <xsl:with-param name="col" select="1"/>
        </xsl:apply-templates>  
    </xsl:variable>
    <!-- output -->
    <table border = "1">
        <!-- for each distinct row -->
        <xsl:for-each select="exsl:node-set($cells)/cell[count(. | key('cell-by-row', @row)[1]) = 1]">
            <tr>
                <!-- for each distinct cell in the current row -->
                <xsl:for-each select="key('cell-by-row', @row)[count(. | key('cell-by-col', concat(@row, '|', @col))[1]) = 1]">
                    <td>
                        <!-- get the values in the current cell -->
                        <xsl:for-each select="key('cell-by-col', concat(@row, '|', @col))">
                            <xsl:value-of select="."/>
                            <br/>
                        </xsl:for-each>
                    </td>
                </xsl:for-each>
            </tr>
        </xsl:for-each>
    </table>
</xsl:template>

<xsl:template match="Item" mode="sibling">
    <xsl:param name="row"/>
    <xsl:param name="col"/>
    <cell row="{$row}" col="{$col}">
        <xsl:value-of select="Label"/>
    </cell>
    <xsl:apply-templates select="following-sibling::*[1]" mode="sibling">
        <xsl:with-param name="row" select="$row"/>
        <xsl:with-param name="col" select="$col"/>
    </xsl:apply-templates>  
</xsl:template>

<xsl:template match="ColumnBreak" mode="sibling">
    <xsl:param name="row"/>
    <xsl:param name="col"/>
    <xsl:apply-templates select="following-sibling::*[1]" mode="sibling">
        <xsl:with-param name="row" select="$row"/>
        <xsl:with-param name="col" select="$col + 1"/>
    </xsl:apply-templates>  
</xsl:template>

<xsl:template match="RowBreak" mode="sibling">
    <xsl:param name="row"/>
    <xsl:param name="col"/>
    <xsl:apply-templates select="following-sibling::*[1]" mode="sibling">
        <xsl:with-param name="row" select="$row + 1"/>
        <xsl:with-param name="col" select="1"/>
    </xsl:apply-templates>  
</xsl:template>

</xsl:stylesheet>

结果

<?xml version="1.0" encoding="utf-8"?>
<table border="1">
  <tr>
    <td>Item 1<br/>Item 2<br/></td>
    <td>Item 3<br/>Item 4<br/>Item 5<br/></td>
  </tr>
  <tr>
    <td>Item 6<br/>Item 7<br/></td>
    <td>Item 8<br/></td>
  </tr>
  <tr>
    <td>Item 9<br/>Item 10<br/></td>
  </tr>
</table>

渲染

这篇关于XSLT Muenchian 分组在组内创建密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆