我有一个项目列表,已排序 我希望将它们显示在一个包含4列和多行的表中(取决于列表的大小,可能会有所不同)。
表中的每个单元格都填充了9个条目。第一个单元格应包含9个第一个条目,第二个单元格应包含从10到18开始的条目,第三个单元格从19到27,第四个单元格从28到36完成第一行。
第2行的第一个单元格应以条目37到45开头,依此类推......
为此,我使用for-each指令
创建了一个XSLT文件<xsl:for-each select="catalog/cd[position() < '10']">
我检查了position()参数。
在第二个单元格中,我使用语句:
<xsl:for-each select="catalog/cd[position() > '9' and position() < '19']">
但它根本不起作用,尽管这对我来说似乎是合乎逻辑的。 我是XML和XSLT的新手,所以如果有人可以帮助我吗?
我使用了W3schools的例子。
所以这是我的XML(标准示例)
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>Greatest Hits</title>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
<cd>
<title>Still got the blues</title>
<artist>Gary Moore</artist>
<country>UK</country>
<company>Virgin records</company>
<price>10.20</price>
<year>1990</year>
</cd>
<cd>
<title>Eros</title>
<artist>Eros Ramazzotti</artist>
<country>EU</country>
<company>BMG</company>
<price>9.90</price>
<year>1997</year>
</cd>
<cd>
<title>One night only</title>
<artist>Bee Gees</artist>
<country>UK</country>
<company>Polydor</company>
<price>10.90</price>
<year>1998</year>
</cd>
<cd>
<title>Sylvias Mother</title>
<artist>Dr.Hook</artist>
<country>UK</country>
<company>CBS</company>
<price>8.10</price>
<year>1973</year>
</cd>
<cd>
<title>Maggie May</title>
<artist>Rod Stewart</artist>
<country>UK</country>
<company>Pickwick</company>
<price>8.50</price>
<year>1990</year>
</cd>
<cd>
<title>Romanza</title>
<artist>Andrea Bocelli</artist>
<country>EU</country>
<company>Polydor</company>
<price>10.80</price>
<year>1996</year>
</cd>
<cd>
<title>When a man loves a woman</title>
<artist>Percy Sledge</artist>
<country>USA</country>
<company>Atlantic</company>
<price>8.70</price>
<year>1987</year>
</cd>
<cd>
<title>Black angel</title>
<artist>Savage Rose</artist>
<country>EU</country>
<company>Mega</company>
<price>10.90</price>
<year>1995</year>
</cd>
<cd>
<title>1999 Grammy Nominees</title>
<artist>Many</artist>
<country>USA</country>
<company>Grammy</company>
<price>10.20</price>
<year>1999</year>
</cd>
<cd>
<title>For the good times</title>
<artist>Kenny Rogers</artist>
<country>UK</country>
<company>Mucik Master</company>
<price>8.70</price>
<year>1995</year>
</cd>
<cd>
<title>Big Willie style</title>
<artist>Will Smith</artist>
<country>USA</country>
<company>Columbia</company>
<price>9.90</price>
<year>1997</year>
</cd>
<cd>
<title>Tupelo Honey</title>
<artist>Van Morrison</artist>
<country>UK</country>
<company>Polydor</company>
<price>8.20</price>
<year>1971</year>
</cd>
<cd>
<title>Soulsville</title>
<artist>Jorn Hoel</artist>
<country>Norway</country>
<company>WEA</company>
<price>7.90</price>
<year>1996</year>
</cd>
<cd>
<title>The very best of</title>
<artist>Cat Stevens</artist>
<country>UK</country>
<company>Island</company>
<price>8.90</price>
<year>1990</year>
</cd>
<cd>
<title>Stop</title>
<artist>Sam Brown</artist>
<country>UK</country>
<company>A and M</company>
<price>8.90</price>
<year>1988</year>
</cd>
<cd>
<title>Bridge of Spies</title>
<artist>T`Pau</artist>
<country>UK</country>
<company>Siren</company>
<price>7.90</price>
<year>1987</year>
</cd>
</catalog>
我将我的XSLT缩减为仅对前两列进行测试:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#D7BDE2">
<th>Blok1</th>
<th>Blok2</th>
<th>Blok3</th>
<th>Blok4</th>
</tr>
<td>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title1</th>
<th>Artist</th>
</tr>
<xsl:for-each select="catalog/cd[position() < '10']">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:for-each>
</table>
</td>
<td>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title2</th>
<th>Artist</th>
</tr>
<xsl:for-each select="catalog/cd[
position() > '9' AND position() < '19' ]">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:for-each>
</table>
</td>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
非常感谢你帮助我。
PS输出应该看起来像这样(见图)。第一列中的前9张CD,下一列中的以下9张,依此类推。 enter image description here
答案 0 :(得分:1)
xsl:for-each
的使用对我来说总是有一点代码味道。它有它的用途,我想,但我通常倾向于选择xsl:apply-templates
和一个单独的顶级模板。在几个地方你有高度重复的代码的事实有更糟糕的代码味道:这只是乞求合并到一个共同的模板。我还观察到你正在尝试的方法是基于能够为每组九张CD写一个单独的for-each
,但这不能扩展。
有多种方法可以解决这个问题,但我将建议基于将模板与各种元素分组对齐,并使用模式进行区分。首先是最高级别:
<xsl:template match="/catalog">
<html>
<body>
<table>
<tr><th>Block1</th><th>Block2</th><th>Block3</th><th>Block4</th></tr>
<xsl:apply-templates
select="cd[floor((position() - 1) div 36) = ((position() - 1) div 36)]"
mode="row"/>
</table>
</body>
</html>
</xsl:template>
设置外部框架,然后,在外部&lt; table&gt;内,它选择每组36 cd
中的第一个用于在模式“行”中进行转换。这些是每行第一个块的第一个元素,用作参考点。行转换如下所示:
<xsl:template match="cd" mode="row">
<tr><xsl:apply-templates
select="self::node()|following-sibling::cd[position() = 9 or position() = 18 or position = 27]"
mode="block"/></tr>
</xsl:template>
这很简单。它只是创建了所需的&lt; tr&gt;对于每个顶级行,然后根据模式“块”转换上下文节点及其兄弟9,18和27元素。这是与最后一个类似的交易:选择用于转换的元素是同一行中每个块的第一个,它们将作为其块的参考点。块转换沿着类似的路线:
<xsl:template match="cd" mode="block">
<td><table>
<tr><th>Title</th><th>Artist</th></tr>
<xsl:apply-templates
select="self::node()|following-sibling::cd[position() < 9]"
mode="album"/>
</table></td>
</xsl:template>
它有更多内容,因为我们需要设置内部每块表,但我们再次使用以下兄弟轴来选择上下文节点的对等体进行转换,这次是同一块中的其他节点。最终模板显示单个CD数据:
<xsl:template match="cd" mode="album">
<tr><td><xsl:value-of select="title"/></td><td><xsl:value-of select="artist"/></td></tr>
</xsl:template>
最后几行与您使用的相同,只是采用不同的方式打包。
请注意,这会发出结构良好的HTML(你的版本缺少一些&lt; tr&gt; s,虽然它很复杂,很容易错过),而且它很好且模块化。它不包括任何样式,因此,我的浏览器对它的再现与罪恶一样丑陋,但我建议通过添加适当的CSS,甚至是外部CSS样式表来纠正它。
答案 1 :(得分:0)
您可以使用以下模板实现9x4解决方案。有两个变量包含根级别的维度。它的模板使用mode
属性来区分两个维度,因此如果您想要添加更多维度(超过2个),则必须引入更多mode
s。
以下模板的构建如下:
apply-templates
($vertical*$horizontal)
cd
元素执行mode="hor"
<tr>
元素,并再次使用前{36} apply-templates
($vertical*$horizontal)
元素添加cd
position() mod $vertical = 1
)添加表格。这适用于当前cd
元素本身以及包含此表达式的以下8个元素:self::cd | following::cd[position() < $vertical]
。这是XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="vertical" select="9" /> <!-- count per table -->
<xsl:variable name="horizontal" select="4" /> <!-- horizontal count of tables -->
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#D7BDE2">
<th>Blok1</th>
<th>Blok2</th>
<th>Blok3</th>
<th>Blok4</th>
</tr>
<xsl:apply-templates select="catalog/cd[position() mod ($vertical*$horizontal) = 1]" mode="hor"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="cd" mode="hor">
<tr>
<xsl:apply-templates select="self::cd | following::cd[position() < ($vertical*$horizontal)]" />
</tr>
</xsl:template>
<xsl:template match="cd[position() mod $vertical = 1]">
<td>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title1</th>
<th>Artist</th>
</tr>
<xsl:for-each select="self::cd | following::cd[position() < $vertical]">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:for-each>
</table>
</td>
</xsl:template>
<xsl:template match="text()" />
</xsl:stylesheet>
输出应该是一个令人愉快的4x9矩阵。