我对xslt比较新,并且一直在尝试使用xml结构创建一个表,但我发现很难限制每行中的字段数量。
<report>
<status>
<statuscheck>
<node>node1</node>
<RAG>red</RAG>
<url>http://www.google.com</url>
<area>area1</area>
</statuscheck>
<statuscheck>
<node>node2</node>
<RAG>red</RAG>
<url>http://www.google.com</url>
<area>area1</area>
</statuscheck>
<statuscheck>
<node>node3</node>
<RAG>red</RAG>
<url>http://www.google.com</url>
<area>area1</area>
</statuscheck>
<statuscheck>
<node>node4</node>
<RAG>red</RAG>
<url>http://www.google.com</url>
<area>area1</area>
</statuscheck>
<statuscheck>
<node>node5</node>
<RAG>red</RAG>
<url>http://www.google.com</url>
<area>area1</area>
</statuscheck>
<statuscheck>
<node>node1</node>
<RAG>red</RAG>
<url>http://www.google.com</url>
<area>area2</area>
</statuscheck>
</status>
<area>
<area_name>area1</area_name>
<area_name>area2</area_name>
</area>
我有以下xslt但有没有办法可以让它在每4个项目后开始一个新行?实际的xml每个区域最多包含20个组件。
<?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>
<head>
<style>
</style>
</head>
<body style="font-family: Sky Text;">
<xsl:for-each select="/report/area/area_name">
<div style="font-size: 20px; font-weight: bold; margin: 10px 0 10px 0;"><xsl:value-of select="."/></div>
<table style="font-family: Sky Text; border-collapse: collapse; width: 960px;">
<tbody>
<xsl:variable name="active_area" select="./text()"></xsl:variable>
<xsl:for-each select="/report/status/statuscheck[area/text() = $active_area]">
<td style="width: 240px; border: 1px solid black; text-align: center;" valign="middle">
<xsl:attribute name="class">
<xsl:value-of select="RAG"/>
</xsl:attribute>
<div style="margin: 10px; font-size: 16px;">
<a>
<xsl:attribute name="href">
<xsl:value-of select="url"/>
</xsl:attribute>
<xsl:value-of select="node"/>
</a>
</div>
</td>
</xsl:for-each>
</tbody>
</table>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
提前谢谢
加文
答案 0 :(得分:1)
我倾向于从风格的角度同意@Flynn1179的评论。应使用HTML表格来呈现表格数据,而不是严格用于布局目的。如果您的数据本身就是表格,那么将它们映射到列和行是很自然的。但这并不意味着XSLT无法完成所呈现的工作。
在讨论如何将XSLT应用于任务之前,我应首先指出您的XSLT编写过程程序,而不是XSLT的自然范例。即便在此范围内,它也无法利用一些可以使其更清晰,更简单的XSLT功能。一般建议:
xsl:for-each
使用xsl:apply-templates
,而是可以使用单独的模板。xsl:element
和xsl:attribute
的文字结果元素和属性。除非需要通过转换计算元素/属性名称,否则后者很少需要(如果有的话)。xsl:key
和key()
功能。这些比新人想象的要有用得多。除此之外,它们对于分组非常有用。然后,请考虑重构样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<!-- group the statuscheck elements by their areas -->
<xsl:key name="area" match="/report/status/statuscheck" use="area"/>
<!-- Provides the top-level document structure -->
<xsl:template match="/">
<html>
<head>
<style>
</style>
</head>
<body style="font-family: Sky Text;">
<!-- generate the body contents by transforming the area_name elements -->
<xsl:apply-templates select="report/area/area_name"/>
</body>
</html>
</xsl:template>
<!-- Transforms area_name elements to produce area information. Note that
The template is not restricted to drawing on the subtree rooted at the
context node. -->
<xsl:template match="area_name">
<xsl:variable name="active_area" select="string(.)"/>
<div style="font-size: 20px; font-weight: bold; margin: 10px 0 10px 0;"><xsl:value-of select="$active_area"/></div>
<table style="font-family: Sky Text; border-collapse: collapse; width: 960px;">
<tbody>
<!-- each row is generated by transforming a distinguished element;
specifically, the first -->
<xsl:apply-templates select="key('area', $active_area)[position() mod 4 = 1]" mode="row-head">
<!-- this is one way to tell the template we're about to apply which are
the other statuscheck element's in the context node's group: -->
<xsl:with-param name="area-checks" select="key('area', $active_area)"/>
</xsl:apply-templates>
</tbody>
</table>
</xsl:template>
<!-- transform a statuscheck node by emitting a <tr> element with a <td> child
for each item in the row -->
<xsl:template match="statuscheck" mode="row-head">
<xsl:param name="area-checks"/>
<xsl:variable name="row-start" select="position() * 4 - 3"/>
<tr>
<!-- the <td> elements are generated by a separate template -->
<xsl:apply-templates select="$area-checks[position() >= $row-start and position() < $row-start + 4]"/>
</tr>
</xsl:template>
<!-- This template and the other matching the same elements are distinguished
by their modes. -->
<xsl:template match="statuscheck">
<!-- Note how the value of the 'class' literal result attribute is expressed
via an XPath expression. You don't need xsl:attribute for that. -->
<td class="{RAG}" style="width: 240px; border: 1px solid black; text-align: center;" valign="middle">
<div style="margin: 10px; font-size: 16px;">
<a href="{url}"><xsl:value-of select="node"/></a>
</div>
</td>
</xsl:template>
</xsl:stylesheet>