XSLT到HTML,使用模板(而不是每个模板)对XML数据进行简单分组
自从我成为sharepoint管理员以来,我一直在断断续续地处理xslt,它经常使用xslt来显示列表数据。我最近开始使用它来转换我使用扩展方法转换为xml的数据库结果。我正在尝试生成干净的html 我的第一次尝试,效果很好。然而,我在各地都用过,从那以后,我读到这是一件不好的事情。我读了一大堆关于使用钥匙的东西,但我不明白这一点,也无法让它发挥作用。所以我重写了这个样式表,下面是它下面的样式表。它使用的每个模板都没有XSLT到HTML,使用模板(而不是每个模板)对XML数据进行简单分组,xml,xslt,xpath,msxml,xslt-1.0,Xml,Xslt,Xpath,Msxml,Xslt 1.0,自从我成为sharepoint管理员以来,我一直在断断续续地处理xslt,它经常使用xslt来显示列表数据。我最近开始使用它来转换我使用扩展方法转换为xml的数据库结果。我正在尝试生成干净的html 我的第一次尝试,效果很好。然而,我在各地都用过,从那以后,我读到这是一件不好的事情。我读了一大堆关于使用钥匙的东西,但我不明白这一点,也无法让它发挥作用。所以我重写了这个样式表,下面是它下面的样式表。它使用的每个模板都没有 <?xml version="1.0" encoding="utf-8
<?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>
<link rel="Stylesheet" type="text/css" href="../styles/BoxReportStyle.css" />
</head>
<body>
<span class="BoxReport">
<h2>Checked Out Boxes by Department with Transaction History</h2>
Count=<xsl:value-of select="count( /CheckedOutBoxes/row ) "/>
<!-- Get the divisions, since we are groing to group by division-->
<xsl:variable name="DivisionList" select="/CheckedOutBoxes/row[ not( Division = preceding-sibling::row/Division ) ]/Division" />
<xsl:for-each select="$DivisionList">
<xsl:variable name="DivisionName" select="." />
<h3>
<xsl:value-of disable-output-escaping="yes" select="$DivisionName "/>
</h3>
<!-- Get the list of departments, so we can group by department -->
<xsl:variable name="DepartmentList" select="/CheckedOutBoxes/row[ Division = $DivisionName and not( Department = preceding-sibling::row/Department) ]/Department" />
<xsl:for-each select="$DepartmentList">
<xsl:variable name="DepartmentName" select="." />
<h4>
<xsl:value-of disable-output-escaping="yes" select="$DepartmentName"/>
</h4>
<xsl:variable name="Rows" select="/CheckedOutBoxes/row[ Division = $DivisionName and Department = $DepartmentName ]" />
<!-- Start displaying the checked out box information for this division and department -->
<table>
<th>Box Number</th>
<th>Status Name</th>
<th>Entry Date</th>
<th>Description</th>
<xsl:for-each select="$Rows">
<tr>
<td>
<xsl:value-of select="BoxNumber"/>
</td>
<td>
<xsl:value-of select="StatusName"/>
</td>
<td>
<xsl:value-of select="EntryDate"/>
</td>
<td width="200px">
<xsl:value-of disable-output-escaping="yes" select="Description"/>
</td>
</tr>
<!-- Now display the transaction history if there is any-->
<xsl:if test=" count( Transaction ) > 0 ">
<tr>
<td></td> <!-- One blank row to shift things over-->
<td colspan="3">
<!-- Display transaction table-->
<table class="SubTable">
<th>Transaction Date</th>
<th>Requestor</th>
<th>Comments</th>
<xsl:for-each select="Transaction" >
<tr>
<td>
<xsl:value-of select="TransactionDate"/>
</td>
<td>
<xsl:value-of select="Requestor"/>
</td>
<td width="200px">
<xsl:value-of disable-output-escaping="yes" select="Comments"/>
</td>
</tr>
</xsl:for-each>
</table>
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:for-each>
</span>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
按具有交易历史记录的部门列出的签出框
计数=
箱号
状态名
参赛日期
描述
交易日期
请求者
评论
我现在将其改写为:
<?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>
<link rel="Stylesheet" type="text/css" href="../styles/BoxReportStyle.css" />
</head>
<body>
<span class="BoxReport">
<h2>Checked Out Boxes by Department with Transaction History</h2>
Count=<xsl:value-of select="count( /CheckedOutBoxes/row ) "/>
<xsl:apply-templates mode="Division" select="/CheckedOutBoxes/row[ not( Division = preceding-sibling::row/Division ) ]"></xsl:apply-templates>
</span>
</body>
</html>
</xsl:template>
<xsl:template mode="Division" match="row">
<h3>
<xsl:value-of select="Division" disable-output-escaping="yes"/>
</h3>
<xsl:variable name="DivisionName" select="Division" />
<xsl:apply-templates mode="Department" select="/CheckedOutBoxes/row[ Division = $DivisionName and not( Department = preceding-sibling::row/Department ) ]"></xsl:apply-templates>
</xsl:template>
<xsl:template mode="Department" match="row">
<h4>
<xsl:value-of select="Department" disable-output-escaping="yes"/>
</h4>
<xsl:variable name="DivisionName" select="Division" />
<xsl:variable name="DepartmentName" select="Department" />
<table>
<th>Box Number</th>
<th>Status Name</th>
<th>Entry Date</th>
<th>Description</th>
<xsl:apply-templates mode="row" select="/CheckedOutBoxes/row[ Division = $DivisionName and Department = $DepartmentName ]" ></xsl:apply-templates>
</table>
</xsl:template>
<xsl:template mode="row" match="row">
<tr>
<td>
<xsl:value-of select="BoxNumber"/>
</td>
<td>
<xsl:value-of select="StatusName"/>
</td>
<td>
<xsl:value-of select="EntryDate"/>
</td>
<td width="200px">
<xsl:value-of disable-output-escaping="yes" select="Description"/>
</td>
</tr>
<!-- Display Transaction stuff as another row if we have any -->
<xsl:if test=" count( Transaction ) > 0 ">
<tr>
<td></td><!-- Shift the transaction over-->
<td colspan="3">
<!-- Start Transaction Table -->
<table class="SubTable">
<th>Transaction Date</th>
<th>Requestor</th>
<th>Comments</th>
<xsl:apply-templates select="Transaction">
<xsl:sort order="descending" select="TransactionDate"/>
</xsl:apply-templates>
</table>
</td>
</tr>
</xsl:if>
</xsl:template>
<xsl:template match="Transaction">
<tr>
<td>
<xsl:value-of select="TransactionDate"/>
</td>
<td>
<xsl:value-of select="Requestor"/>
</td>
<td width="200px">
<xsl:value-of disable-output-escaping="yes" select="Comments"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
按具有交易历史记录的部门列出的签出框
计数=
箱号
状态名
参赛日期
描述
交易日期
请求者
评论
我没有包括示例输入和输出,因为它们都是自动生成的。如果需要的话,我可以花很多时间,试着生产一些东西
我的问题是,这是更好的方法吗?另外,如果关键方法更好,是否有人可以解释它,或者提供一个链接到一个好的解释?基本上,对每个使用
与模板的问题归结为创建可重用的、更通用的转换
通过使用模板,所有匹配的节点(不仅仅是在for each中明确使用的节点)都可以从模板中受益,这有助于避免重复代码,同时将工作表拆分为更易于管理的较小单元。实际上,这与在命令式编程中有一个或多个大型或小型过程相互调用几乎相同
虽然有些人认为在某些引擎中使用模板可能会表现得更好,但我相信这并不会产生真正的影响
也就是说,您可能希望了解(使用键的)用于对具有重复键的数据进行实际分组的方法。在某些发动机上使用前面的同级轴
速度非常慢,因此在不绝对需要时最好避免使用
类似这样的操作应该可以实现分区(未经测试):
for each模板是XSLT的一个很好的特性
使用“模板”而不是“for each”的建议主要是关于XSLT处理模型的可能误用
在您的示例中很清楚:一个简单的“模板”和许多指导流程的“for each”
XSLT本身的关键用法与性能有关。它的用处在于替换涉及到输入树的许多节点的重复遍历的XPath表达式。Muenchian分组方法是键的特殊用途。无需使用键即可优化简单分组
另一方面,人口是转型的特例。我认为维护最好将XHTML语义与XSLT转换分开。以www.aranedabienesraices.com.ar为例。key是否获得所有非重复分区?如果这就是它所做的,也许我能更好地理解它。然后我可以为部门制作另一个基本上与部门相同的键。然后,apply模板的select语句将确保我为当前部门而不是所有部门创建部门。本例中的key()
函数基本上返回一个包含所有匹配部门的节点集。这里的“魔术”是generate-id()
函数,它返回传入节点集中第一个节点的唯一标识id。因此,将每个分区
节点ID与具有相同内容的第一个节点的ID进行比较(这就是为什么我们使用key()
函数),因此,每个不同的内容只匹配一次。我想,在对模板做了一点工作之后,使其成为部门模板匹配部门而不是行,并实现了我得到的关键内容,从而使其工作,而不是前面的兄弟。我现在只懂一点,但希望在学习之后我能更好地理解它。为什么在
中使用绝对XPath表达式作为匹配模式?请更正一些更值得推荐的内容。@Dimitre,我采用了该模式,以便可以识别与原始源的关系。我想我看到了模板的位置,确实可以分解这些内容。差不多了
<xsl:key name="divisions" match="/CheckedOutBoxes/row/Division" use="." />
<xsl:apply-templates mode="Division" select="/CheckedOutBoxes/Division[generate-id(.)=generate-id(key('divisions', .))]" />