我有以下XML数据:
<Activity>
<ObjectGroup type="default">
<Object id="1874" name="PR1010Date" type="reference label" index="10" columnNo="0" dynamic="true">
<Description>Date</Description>
<Value instance="0">30/06/2010</Value>
</Object>
<Object id="1875" name="PR1020LoggedBy" type="reference label" index="20" columnNo="1" dynamic="true">
<Description>Request Logged By</Description>
<Value>Site Administrator</Value>
</Object>
<Object id="1876" name="PR1030Comments" type="large text box" index="30" columnNo="0" dataType="Text">
<Description>Comments</Description>
<Value instance="0">Test</Value>
</Object>
<ObjectGroup>
</Activity>
我需要创建一个XSL,它将产生以下输出:
<html>
<table>
<tr>
<td width="50%">30/06/2010</td>
<td width="50%">Site Admin</td>
</tr>
<tr>
<td width="100%">Test</td>
</tr>
</table>
在上面的XML中,index属性和columnNo驱动生成了多少行和列。最终结果是在ColumnNo上确定的,因此如果ObjectGroup具有带有增量columnNo的对象,那么它们将全部呈现为一行,每列具有适当的宽度。
答案 0 :(得分:1)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kObjByCol" match="Object"
use="@columnNo"/>
<xsl:key name="kRow" match="Object[@columnNo != 0]"
use="generate-id(preceding-sibling::Object
[@columnNo = 0][1]
)"/>
<xsl:template match="/*">
<html>
<table border="1">
<xsl:apply-templates select=
"key('kObjByCol', 0)"/>
</table>
</html>
</xsl:template>
<xsl:template match="Object">
<xsl:variable name="vcellNodes"
select=".|key('kRow',generate-id())"/>
<tr>
<xsl:apply-templates mode="row" select=
"$vcellNodes">
<xsl:with-param name="pCount"
select="count($vcellNodes)"/>
</xsl:apply-templates>
</tr>
</xsl:template>
<xsl:template match="Object" mode="row">
<xsl:param name="pCount"/>
<td width="{100 div $pCount}%">
<xsl:value-of select="Value"/>
</td>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档(更正为格式良好):
<Activity>
<ObjectGroup type="default">
<Object id="1874" name="PR1010Date"
type="reference label" index="10"
columnNo="0" dynamic="true">
<Description>Date</Description>
<Value instance="0">30/06/2010</Value>
</Object>
<Object id="1875" name="PR1020LoggedBy"
type="reference label" index="20"
columnNo="1" dynamic="true">
<Description>Request Logged By</Description>
<Value>Site Administrator</Value>
</Object>
<Object id="1876" name="PR1030Comments"
type="large text box" index="30"
columnNo="0" dataType="Text">
<Description>Comments</Description>
<Value instance="0">Test</Value>
</Object>
</ObjectGroup>
</Activity>
生成想要的正确结果:
<html>
<table border="1">
<tr>
<td width="50%">30/06/2010</td>
<td width="50%">Site Administrator</td>
</tr>
<tr>
<td width="100%">Test</td>
</tr>
</table>
</html>
答案 1 :(得分:1)
根据Dimitre的出色回应,另一张没有按键的样式表。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="ObjectGroup">
<html>
<table border="1">
<xsl:apply-templates select="Object[@columnNo=0]"/>
</table>
</html>
</xsl:template>
<xsl:template match="Object">
<xsl:variable name="td"
select=".|following-sibling::*[@columnNo!=0][
count(current()|
preceding-sibling::*[@columnNo=0][1]
)=1]"/>
<tr>
<xsl:apply-templates select="$td/Value">
<xsl:with-param name="td-count" select="count($td)"/>
</xsl:apply-templates>
</tr>
</xsl:template>
<xsl:template match="Value">
<xsl:param name="td-count"/>
<td width="{100 div $td-count}%">
<xsl:value-of select="."/>
</td>
</xsl:template>
</xsl:stylesheet>
但是,大多数XSLT处理器允许使用密钥。
现在,对于colspan:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:variable name="td-max">
<xsl:call-template name="max">
<xsl:with-param name="nodes" select="/*/*/Object[@columnNo=0]"/>
</xsl:call-template>
</xsl:variable>
<xsl:template name="max">
<xsl:param name="nodes"/>
<xsl:if test="$nodes">
<xsl:variable name="head"
select="count($nodes[1]/following-sibling::*[@columnNo!=0][
count($nodes[1]|
preceding-sibling::*[@columnNo=0][1]
)=1])+1"/>
<xsl:variable name="tail">
<xsl:call-template name="max">
<xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$head > $tail or $tail=''">
<xsl:value-of select="$head"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$tail"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template match="ObjectGroup">
<html>
<table border="1">
<xsl:apply-templates select="Object[@columnNo=0]"/>
</table>
</html>
</xsl:template>
<xsl:template match="Object">
<xsl:variable name="td"
select=".|following-sibling::*[@columnNo!=0][
count(current()|
preceding-sibling::*[@columnNo=0][1]
)=1]"/>
<tr>
<xsl:apply-templates select="$td/Value">
<xsl:with-param name="td-count" select="count($td)"/>
</xsl:apply-templates>
</tr>
</xsl:template>
<xsl:template match="Value">
<xsl:param name="td-count"/>
<td width="{100 div $td-count}%">
<xsl:if test="position()=last() and $td-max > $td-count">
<xsl:attribute name="colspan">
<xsl:value-of select="$td-max - $td-count + 1"/>
</xsl:attribute>
</xsl:if>
<xsl:value-of select="."/>
</td>
</xsl:template>
</xsl:stylesheet>
修改:添加了动态colspan。如果你不关心多个colspan="1"
,它可能会更简洁。
编辑2 :更好的最大模式。