首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XSLT中表的递归

XSLT中表的递归
EN

Stack Overflow用户
提问于 2014-06-10 00:17:59
回答 1查看 157关注 0票数 0

我的XML是几个100个电影元素,我试图为每一种类型创建一个表,其中表的每一行都是一组元素,每个元素包含一部电影。

这里是我的xml (大大简化和缩短,在我的实际交易中有100个“电影”元素)

代码语言:javascript
复制
    <mediaList>
        <movie>
        <title>16 Blocks</title>
        <director>Richard Donner</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Action Thrillers</subGenre>
            <subGenre>Crime Action</subGenre>
        </genreWrap>
    </movie>

    <movie>
         <title>Armageddon</title>
        <director>Michael Bay</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Deadly Disasters</subGenre>
        </genreWrap>
    </movie>

    <movie>
        <title>African Queen, The</title>
        <director>John Huston</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Action Classics</subGenre>
            <subGenre>Adventures</subGenre>
        </genreWrap>
    </movie>

    <movie>
        <title>Assault on Precinct 13</title>
        <director>Jean-François Richet</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Action Thrillers</subGenre>
            <subGenre>Crime Action</subGenre>
        </genreWrap>
    </movie>
    <movie>
        <title>Back to the Future 3 (Box Set)</title>
        <director>Robert Zemeckis</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Westerns</subGenre>
        </genreWrap>
    </movie>

    <movie>
        <title>Billy Budd</title>
        <director>Peter Ustinov</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Action Classics</subGenre>
            <subGenre>Adventures</subGenre>
        </genreWrap>
    </movie>

    <movie>
        <title>Black Arrow</title>
        <director>Gordon Douglas</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Adventures</subGenre>
            <subGenre>Super Swashbucklers</subGenre>
        </genreWrap>
    </movie>

    <movie>
        <title>Black Cat Run</title>
        <director>D.J. Caruso</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Action Thrillers</subGenre>
        </genreWrap>
    </movie>

    <movie>
         <title>Captains Courageous</title>
        <director>Victor Fleming</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Action Classics</subGenre>
            <subGenre>Adventures</subGenre>
        </genreWrap>
    </movie>

    <movie>
       <title>Brothers Grimm, The</title>
        <director>Terry Gilliam</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Adventures</subGenre>
        </genreWrap>
    </movie>

    <movie>
        <title>Convoy</title>
        <director>Sam Peckinpah</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Action Comedies</subGenre>
        </genreWrap>
    </movie>

<movie>
 <title>Deliverance</title>
        <director>John Boorman</director>
        <genreWrap>
            <genre>Action and Adventure</genre>
            <subGenre>Action Classics</subGenre>
            <subGenre>Action Thrillers</subGenre>
            <subGenre>Adventures</subGenre>
        </genreWrap>
</movie>
</mediaList>

我的样式表

代码语言:javascript
复制
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html"/>

    <xsl:key name="genre" match="genre" use="."/>

    <xsl:template match="/">
        <xsl:for-each
            select="mediaList/movie/genreWrap/genre[local-name() = 'genre'][generate-id()=generate-id(key('genre', .)[1])]">
            <xsl:variable name="genre" select="."/>
            <xsl:result-document method="html" href="GenreHTML/{translate(.,' ','')}.html">
                <html>
                    <head>
                        <title>
                            <xsl:value-of select="translate(.,' ','')"/>
                        </title>
                    </head>
                    <body>
                        <table class="genre">
                            <tr>
                                <xsl:variable name="movies">
                                    <xsl:apply-templates select="key('genre', .)/ancestor::movie">
                                        <xsl:sort/>
                                    </xsl:apply-templates>
                                </xsl:variable>
                                <xsl:copy-of select="subsequence($movies/td,1,6)"/>
                            </tr>
                        </table>
                    </body>
                </html>
            </xsl:result-document>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="movie">
        <td>
                <xsl:value-of select="title"/>
        </td>
    </xsl:template>

</xsl:stylesheet>

我知道现在我使用的是这个序列函数,它将只打印前6,我正在试图找出如何递归地完成它,这样它就会在每一个上打印6

期望产出:

代码语言:javascript
复制
<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>ActionandAdventure</title>
</head>
   <body>
      <table class="genre">
         <tr>
            <td>16 Blocks</td>
            <td>African Queen, The</td>
            <td>Armageddon</td>
            <td>Assault on Precinct 13</td>
            <td>Back to the Future 3 (Box Set)</td>
            <td>Billy Budd</td>
         </tr>
<tr>
<td>Black Arrow</td>
<td>Black Cat Run</td>
<td>Brothers Grimm, The</td
<td>Captains Courageous</td>
<td>Convoy</td>
<td>Deliverance</td>
</tr>
      </table>
   </body>
</html>

我正在使用XSLT2.0,但是我会拿走您拥有的任何东西!我故意从一种类型中提取所有xml示例,但请放心,真正的xml示例有许多不同类型的电影。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-10 07:34:45

如果您正在使用XSLT2.0,那么这里没有真正的使用Muenchian分组的必要,尽管它功能强大,但是您可以使用xsl:for-each-group

代码语言:javascript
复制
<xsl:for-each-group select="movie" group-by="genreWrap/genre">

然后,将每组电影“拆分”为6行,使用xsl:for-来选择将作为每一行的第一个单元格的元素(即在第1、7、13等位置的单元格)。

代码语言:javascript
复制
<xsl:for-each select="current-group()[position() mod 6 = 1]">

要选择行中的元素,您可以这样做(因为在xsl:for-每个的上下文中,position()将被设置为1、2、3等,但您需要在其实际位置上的元素,即1、7、13等)。

代码语言:javascript
复制
<xsl:apply-templates 
     select="current-group()[position() >= ($pos - 1) * 6 + 1 and position() &lt; ($pos - 1) * 6 + 7]" />

在XSLT2.0中,如果连续放映的电影少于6部,甚至不需要递归。您可以只使用xsl:for-each循环

代码语言:javascript
复制
<xsl:for-each select="1 to 6 - (count(current-group()) mod 6)">
     <td></td>
</xsl:for-each>

试试这个XSLT

代码语言:javascript
复制
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html"/>

    <xsl:template match="/*">
        <xsl:for-each-group select="movie" group-by="genreWrap/genre">
            <xsl:variable name="genre" select="."/>
            <xsl:result-document method="html" href="GenreHTML/{translate(current-grouping-key(),' ','')}.html">
                <html>
                    <head>
                        <title>
                            <xsl:value-of select="translate(current-grouping-key(),' ','')"/>
                        </title>
                    </head>
                    <body>
                        <table class="genre">
                            <xsl:for-each select="current-group()[position() mod 6 = 1]">
                                <xsl:variable name="pos" select="position()" />
                                    <tr>
                                        <xsl:apply-templates select="current-group()[position() >= ($pos - 1) * 6 + 1 and position() &lt; ($pos - 1) * 6 + 7]" />
                                        <xsl:if test="not(current-group()[($pos - 1) * 6 + 6])">
                                            <xsl:for-each select="1 to 6 - (count(current-group()) mod 6)">
                                                <td></td>
                                            </xsl:for-each>
                                        </xsl:if>
                                    </tr>
                            </xsl:for-each>
                        </table>
                    </body>
                </html>
            </xsl:result-document>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="movie">
        <td>
            <xsl:value-of select="title"/>
        </td>
    </xsl:template>
</xsl:stylesheet>

编辑:在这个答案中,我没有考虑排序。如果您希望对电影进行排序,那么目前我所能想到的唯一方法就是对它们进行排序,并将结果存储在一个变量中,然后像以前一样迭代。

试试这个XSLT (它还应该考虑到标题上的大小写敏感性,但是要对标题进行大写排序):

代码语言:javascript
复制
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="html"/>

    <xsl:template match="/*">
        <xsl:for-each-group select="movie" group-by="genreWrap/genre">
            <xsl:variable name="genre" select="."/>
            <result-document method="html" href="GenreHTML/{translate(current-grouping-key(),' ','')}.html">
                <html>
                    <head>
                        <title>
                            <xsl:value-of select="translate(current-grouping-key(),' ','')"/>
                        </title>
                    </head>
                    <body>
                        <table class="genre">
                            <xsl:variable name="sorted-group">
                                <xsl:for-each select="current-group()">
                                    <xsl:sort select="upper-case(title)" />
                                    <xsl:copy-of select="." />
                                </xsl:for-each>
                            </xsl:variable>
                            <xsl:for-each select="$sorted-group/movie[position() mod 6 = 1]">
                                <xsl:variable name="pos" select="position()" />
                                <xsl:apply-templates select="$sorted-group/movie[6]" />
                                <tr>
                                    <xsl:for-each select="$sorted-group/movie[position() >= ($pos - 1) * 6 + 1 and position() &lt; ($pos - 1) * 6 + 7]">
                                        <td>
                                            <xsl:value-of select="title"/>
                                        </td>
                                    </xsl:for-each>
                                    <xsl:if test="not($sorted-group/movie[($pos - 1) * 6 + 6])">
                                        <xsl:for-each select="1 to 6 - (count($sorted-group/movie) mod 6)">
                                            <td></td>
                                        </xsl:for-each>
                                    </xsl:if>
                                </tr>
                            </xsl:for-each>
                        </table>
                    </body>
                </html>
            </result-document>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24131007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档