我按照this post from StackOverflow
的说明生成了一个每行2个单元格的HTML表格但我想将数据分发到HTML表格中,每行三个单元格。我从帖子中更改了兄弟的数字和XSLT样式表中位置的计算,但它似乎不起作用。
这是我的XML源:
<?xml version="1.0" encoding="UTF-8"?>
<report>
<frontmatter>
<title>Relatório da 4ª Sessão Intercalar</title>
<subtitle>Projecto Integrado de Engenharia de Linguagens</subtitle>
<authors>
<author>
<name>Marina Mac</name>
<nident>pg999</nident>
<email>pg999@minho.pt</email>
<url>https://www.linkedin.com</url>
<affil>Universidade do Minho</affil>
<photo>source/img/authors/marina.png</photo>
</author>
<author>
<name>Nuno Vie</name>
<nident>pg998</nident>
<email>pg998@minho.pt</email>
<url>https://www.linkedin.com</url>
<photo>source/img/authors/nuno.jpg</photo>
<affil>Universidade do Minho</affil>
</author>
<author>
<name>Damien Va</name>
<nident>pg997</nident>
<photo>source/img/authors/damien.jpg</photo>
<url>https://www.linkedin.com</url>
<email>pg997@minho.pt</email>
<affil>Universidade do Minho</affil>
</author>
<author>
<name>Tiago Mach</name>
<nident>pg996</nident>
<email>pg996@minho.pt</email>
<url>https://www.linkedin.com</url>
<affil>Universidade do Minho</affil>
<photo>source/img/authors/marina.png</photo>
</author>
<author>
<name>Manuel Vie</name>
<nident>pg995</nident>
<email>pg995@minho.pt</email>
<url>https://www.linkedin.com</url>
<photo>source/img/authors/nuno.jpg</photo>
<affil>Universidade do Minho</affil>
</author>
<author>
<name>Damien Vim</name>
<nident>pg994</nident>
<photo>source/img/authors/damien.jpg</photo>
<url>https://www.linkedin.com</url>
<email>pg994@alunos.uminho.pt</email>
<affil>Universidade do Minho</affil>
</author>
</authors>
</frontmatter>
</report>
这是我的XSLT代码,它不能满足我的需求:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/report">
<html>
<head>
<meta charset="utf-8"/>
<title><xsl:value-of select="frontmatter/title"/></title>
</head>
<body>
<xsl:apply-templates select="frontmatter"/>
</body>
</html>
</xsl:template>
<xsl:template match="frontmatter" >
<table width="100%">
<tr align="center">
<td>
<h1><xsl:value-of select="title"/></h1>
</td>
</tr>
<xsl:if test="subtitle != '' ">
<tr align="center">
<td>
<xsl:value-of select="subtitle"/>
</td>
</tr>
</xsl:if>
</table>
<hr width="90%"/>
<h2>Autores</h2>
<table width="90%" align="center">
<xsl:apply-templates select="authors/author[position() mod 2 = 1]"/>
</table>
</xsl:template>
<xsl:template match="authors/author">
<tr>
<xsl:for-each select=". | following-sibling::author[1]" >
<td>
<p><xsl:value-of select="name"></xsl:value-of></p>
</td>
</xsl:for-each>
<xsl:if test="not(following-sibling::author)">
<td/>
<td/>
</xsl:if>
</tr>
</xsl:template>
</xsl:stylesheet>
如何修复样式表以便生成每行包含3个单元格的HTML表格?
答案 0 :(得分:3)
如果您有6位作者,我假设您期望得到这样的结果:
<table width="90%" align="center" border="1">
<tr>
<td>Marina Machado</td>
<td>Damien Vaz</td>
<td>Manuel Vieira</td>
</tr>
<tr>
<td>Nuno Vieira</td>
<td>Tiago Machado</td>
<td>Damien Vaz</td>
</tr>
</table>
如果您有三位或更多作者,那么您将始终拥有三列。如果您有零个,一个或两个作者,那么您将拥有少于三列的唯一情况。列将从从左到右填充,因此如果您有7位作者,则最后一行在第一列中只有一位作者。
这将是五位作者的结果:
<table width="90%" align="center" border="1">
<tr>
<td>Marina Machado</td>
<td>Damien Vaz</td>
<td>Manuel Vieira</td>
</tr>
<tr>
<td>Nuno Vieira</td>
<td>Tiago Machado</td>
</tr>
</table>
如果您有七个,则会创建一个新行:
<table width="90%" align="center" border="1">
<tr>
<td>Marina Machado</td>
<td>Damien Vaz</td>
<td>Manuel Vieira</td>
</tr>
<tr>
<td>Nuno Vieira</td>
<td>Tiago Machado</td>
<td>William Shakespeare</td>
</tr>
<tr>
<td>Heitor Villa-Lobos</td>
</tr>
</table>
使用此样式表(我将其缩减为代码的基本部分以处理分组问题),您可以生成满足这些要求的HTML表格(在给定源XML的情况下) - 您可以在以后使用重读你的代码):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="cols">3</xsl:param> <!-- set the number of rows here -->
<xsl:template match="frontmatter" >
<table width="90%" align="center" border="1">
<xsl:apply-templates select="authors/author[position() mod $cols = 1 or position() = 1]" mode="row"/>
</table>
</xsl:template>
<xsl:template match="authors/author" mode="row">
<tr>
<xsl:apply-templates select=". | following-sibling::author[position() < $cols]" mode="cell"/>
</tr>
</xsl:template>
<xsl:template match="authors/author" mode="cell">
<td>
<xsl:value-of select="name"/>
</td>
</xsl:template>
</xsl:stylesheet>
如果您决定使用不同数量的列分发作者,则可以传递具有不同值的cols
参数,也可以将参数<xsl:param name="cols">3</xsl:param>
中的值替换为其他值。例如,如果您将其更改为4列,它将按如下方式分发您的作者:
<table width="90%" align="center" border="1">
<tr>
<td>Marina Machado</td>
<td>Nuno Vieira</td>
<td>Damien Vaz</td>
<td>Tiago Machado</td>
</tr>
<tr>
<td>Manuel Vieira</td>
<td>Damien Vaz</td>
</tr>
</table>
在此模板中计算行数:
<xsl:template match="frontmatter" >
<table width="90%" align="center" border="1">
<xsl:apply-templates select="authors/author[position() mod $cols = 1 or position() = 1]" mode="row"/>
</table>
</xsl:template>
XPath表达式选择位置除以列数的余数为1的作者。对于三列,它将选择<author>
元素编号1,4,7,10,...它还将选择 last 元素(可能不是其中之一)。它会调用标有author
的第一个mode="row"
模板。
该模板选择将包含每行单元格数据的元素:
<xsl:template match="authors/author" mode="row">
<tr>
<xsl:apply-templates select=". | following-sibling::author[position() < $cols]" mode="cell"/>
</tr>
</xsl:template>
它将选择当前 author
(.
)以及距离为$cols
的以下兄弟姐妹 - 1.如果{{1} }是3,然后它将选择当前$cols
和下一个author
(如果存在)。这样,它将选择将放在一行中的所有元素。例如,如果前一个模板选择了元素1和4(对于3列),则此模板将为第一列选择元素1(当前),2和3,为第二列选择元素4(当前),5和6。此选择将用于应用authors
模板,该模板只会在mode="cell"
块中打印作者的name
子元素。
此解决方案适用于XSLT 1.0 或 2.0。
您可以在 XSLT Fiddle
中看到代码答案 1 :(得分:3)
您可以使用xsl:for-each-group
并使用group-ending-with
对作者元素进行分组,其中匹配作者元素的position() mod 3
等于0.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"></xsl:output>
<xsl:template match="/report">
<html>
<head>
<meta charset="utf-8"/>
<title><xsl:value-of select="frontmatter/title"/></title>
</head>
<body>
<xsl:apply-templates select="frontmatter"/>
</body>
</html>
</xsl:template>
<xsl:template match="frontmatter" >
<table width="100%">
<tr align="center">
<td>
<h1><xsl:value-of select="title"/></h1>
</td>
</tr>
<xsl:if test="subtitle != '' ">
<tr align="center">
<td>
<xsl:value-of select="subtitle"/>
</td>
</tr>
</xsl:if>
</table>
<hr width="90%"/>
<h2>Autores</h2>
<table width="90%" align="center">
<xsl:apply-templates select="authors"/>
</table>
</xsl:template>
<xsl:template match="authors">
<xsl:param name="cols" select="3" as="xs:integer"/>
<xsl:for-each-group select="author"
group-ending-with="author[position() mod $cols = 0]">
<tr>
<xsl:for-each select="current-group()">
<td>
<p><xsl:value-of select="name"></xsl:value-of></p>
</td>
</xsl:for-each>
<!--ensure that there are an equal number of columns for every row
by generating empty cols if there is a "remainder" -->
<xsl:for-each select="0 to ($cols - count(current-group())-1)">
<td></td>
</xsl:for-each>
</tr>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>