我对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>
提前感谢Gavin
发布于 2017-06-29 22:36:39
我倾向于从文体的角度同意@Flynn1179的评论。HTML表格应该用来表示表格数据,而不是完全出于布局的目的。如果您的数据本质上是表格,那么将它们映射到列和行将是很自然的。但这并不意味着XSLT不能完成所给出的工作。
但是,在讨论如何将XSLT应用于任务之前,我应该首先指出,您的XSLT是像过程化程序一样编写的,这不是XSLT的自然范式。即使在这种情况下,它也不能利用一些XSLT特性来使它更清晰、更简单。一般建议:
xsl:for-each
,因为xsl:apply-templates
和一个单独的模板可以替代。xsl:element
和xsl:attribute
相比,xsl:key
和key()
函数的expressions.话虽如此,考虑一下样式表的重构:
<?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>
https://stackoverflow.com/questions/44823484
复制相似问题