我的XML是几百个电影元素,并且我试图为每个类型创建一个表,其中表的每一行都是SET元素,每个元素包含一个电影。
这是我的xml(大大简化和缩短,在我的真实交易中有100多个'电影'元素)
<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>
和我的样式表
<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
期望的输出:
<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>
我正在使用XSLT 2.0,但我会带走任何东西!我故意从一种类型中提取所有xml示例,但请确保真正的一部分有许多不同类型的电影
答案 0 :(得分:1)
如果您使用的是XSLT 2.0,那么就没有必要在这里使用Muenchian分组,虽然功能强大,但您可以使用 xsl:for-each-group
<xsl:for-each-group select="movie" group-by="genreWrap/genre">
然后,分开&#39;将每组电影分成6行,使用 xsl:for-each 选择电影元素,这些元素将作为每行的第一个单元格出现(即第1,第7,第13等职位)
<xsl:for-each select="current-group()[position() mod 6 = 1]">
要选择行中的元素,您可以执行此操作(因为在 xsl:for-each 的上下文中,position()
将设置为1,2,3等等,但你需要在实际位置的元素,这将是1,7,13等。)
<xsl:apply-templates
select="current-group()[position() >= ($pos - 1) * 6 + 1 and position() < ($pos - 1) * 6 + 7]" />
在XSLT 2.0中,如果你连续拍摄的电影少于6部,你甚至不需要递归。您只需使用 xsl:for-each 循环
即可<xsl:for-each select="1 to 6 - (count(current-group()) mod 6)">
<td></td>
</xsl:for-each>
试试这个XSLT
<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() < ($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(它还应考虑标题的区分大小写,但以大写字母对标题进行排序):
<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() < ($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>