关于在XSLT中将节点序列渲染为M x N表,存在一个5年前的问题(下面链接)。答案很好,我在几个项目中都使用过它。
Rendering a node sequence as M x N table
我现在遇到需要排序输出的情况。新项目将添加到序列的末尾,我不能简单地重新生成XML。
在我看来,使用此代码作为起点,必须在调用任何模板之前对列表进行排序。我无法提出解决方案,并希望其中一位大师可以提供帮助。
一些补充资料以供澄清。这适用于仅支持XSLT 1.0版的SharePoint 2010网站。我从列表中呈现数据,这些数据可以添加到但不重新排序而不删除和重新输入数据。由于我无法对列表进行重新排序,因此我希望使用XSLT对输出进行排序。
这是输入xml;
<root>
<CRMData>
<Rows>
<Row Name1="1 test customer" Title="ACC-011636"/>
<Row Name1="7 test customer" Title="ACC-011618"/>
<Row Name1="14 test customer" Title="ACC-011635"/>
<Row Name1="6 test customer" Title="ACC-011610"/>
<Row Name1="22 test customer" Title="ACC-011627"/>
<Row Name1="12 test customer" Title="ACC-011748"/>
<Row Name1="3 test customer" Title="ACC-011607"/>
<Row Name1="9 test customer" Title="ACC-011628"/>
<Row Name1="45 test customer" Title="ACC-011754"/>
<Row Name1="16 test customer" Title="ACC-011774"/>
<Row Name1="10 test customer" Title="ACC-011632"/>
<Row Name1="7 test customer" Title="ACC-011606"/>
<Row Name1="19 test customer" Title="ACC-012275"/>
<Row Name1="59 test customer" Title="ACC-011634"/>
<Row Name1="33 test customer" Title="NONE-001"/>
<Row Name1="2 test customer" Title="ACC-011617"/>
<Row Name1="64 test customer" Title="ACC-011629"/>
<Row Name1="15 test customer" Title="ACC-011633"/>
<Row Name1="26 test customer" Title="ACC-011612"/>
<Row Name1="38 test customer" Title="ACC-011608"/>
<Row Name1="21 test customer" Title="ACC-011749"/>
<Row Name1="8 test customer" Title="ACC-011611"/>
<Row Name1="17 test customer" Title="ACC-011613"/>
<Row Name1="20 test customer" Title="ACC-011714"/>
<Row Name1="4 test customer" Title="ACC-011616"/>
<Row Name1="62 test customer" Title="ACC-011601"/>
<Row Name1="11 test customer" Title="ACC-012918"/>
</Rows>
</CRMData>
<KenData>
<Rows>
<Row Title="KEN-3336" Date1="12/15/2009" Date2="6/23/2014" Version="10.1" CustomerID="ACC-011636"/>
<Row Title="KEN-3338" Date1="10/30/2006" Date2="8/9/2012" Version="8.4.5" CustomerID="ACC-011618"/>
<Row Title="KEN-3337" Date1="2/10/2014" Date2="2/10/2014" Version="9.3" CustomerID="ACC-011635"/>
<Row Title="Ken-3339" Date1="3/10/2010" Date2="6/13/2013" Version="10" CustomerID="ACC-011610"/>
<Row Title="KEN-3340" Date1="11/22/2010" Date2="9/24/2014" Version="10.1" CustomerID="ACC-011627"/>
<Row Title="KEN-3341" Date1="1/21/2013" Date2="1/30/2015" Version="10.3" CustomerID="ACC-011748"/>
<Row Title="KEN-3342" Date1="10/1/2008" Date2="10/1/2008" Version="8.4" CustomerID="ACC-011607"/>
<Row Title="KEN-3344" Date1="6/17/2008" Date2="6/17/2008" Version="9.2" CustomerID="ACC-011628"/>
<Row Title="KEN-3345" Date1="12/23/2008" Date2="11/25/2014" Version="10.2" CustomerID="ACC-011754"/>
<Row Title="KEN-3347" Date1="11/17/2010" Date2="11/17/2010" Version="8.4.5" CustomerID="ACC-011774"/>
<Row Title="KEN-3349" Date1="Pending" Date2="Pending" Version="10.1" CustomerID="ACC-011632"/>
<Row Title="KEN-3350" Date1="4/2/2012" Date2="1/17/2012" Version="8.4.5" CustomerID="ACC-011606"/>
<Row Title="KEN-3351" Date1="8/10/2015" Date2="8/10/2015" Version="10.3" CustomerID="ACC-012275"/>
<Row Title="KEN-3353" Date1="Pending" Date2="Pending" Version="9.3" CustomerID="ACC-011634"/>
<Row Title="KEN-3346" Date1="3/7/2011" Date2="3/15/2011" Version="8.4.5" CustomerID="NONE-001"/>
<Row Title="KEN-3354" Date1="7/2/2013" Date2="10/12/2015" Version="10.3" CustomerID="ACC-011617"/>
<Row Title="KEN-3355" Date1="8/15/2013" Date2="8/15/2013" Version="9.3" CustomerID="ACC-011629"/>
<Row Title="KEN-3356" Date1="8/18/2014" Date2="8/18/2014" Version="9.3" CustomerID="ACC-011633"/>
<Row Title="KEN-3357" Date1="3/25/2003" Date2="10/18/2011" Version="8.4" CustomerID="ACC-011612"/>
<Row Title="KEN-3358" Date1="9/15/2007" Date2="11/18/2014" Version="10.2" CustomerID="ACC-011608"/>
<Row Title="KEN-3359" Date1="8/1/2006" Date2="6/1/2015" Version="10.3" CustomerID="ACC-011749"/>
<Row Title="KEN-3360" Date1="9/20/2010" Date2="9/20/2010" Version="8.4" CustomerID="ACC-011611"/>
<Row Title="KEN-3361" Date1="7/14/2014" Date2="8/5/2014" Version="10.2" CustomerID="ACC-011613"/>
<Row Title="KEN-3362" Date1="1/20/2005" Date2="8/21/2012" Version="9.2" CustomerID="ACC-011714"/>
<Row Title="KEN-3363" Date1="3/15/2007" Date2="4/25/2008" Version="8.4" CustomerID="ACC-011616"/>
<Row Title="KEN-3364" Date1="7/10/2014" Date2="7/10/2014" Version="10" CustomerID="ACC-011601"/>
<Row Title="KEN-3875" Date1="7/10/2015" Date2="7/10/2015" Version="10.3" CustomerID="ACC-012918"/>
</Rows>
</KenData>
<OtherData>
<Rows>
<Row Title="OTH-001" CustomerID="ACC-011636" Data1="Yes" Data2="Yes" Data3="No"/>
<Row Title="OTH-002" CustomerID="ACC-011618" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-003" CustomerID="ACC-011635" Data1="No" Data2="Yes" Data3="No"/>
<Row Title="OTH-004" CustomerID="ACC-011610" Data1="Yes" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-005" CustomerID="ACC-011627" Data1="No" Data2="No" Data3="Yes"/>
<Row Title="OTH-006" CustomerID="ACC-011748" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-007" CustomerID="ACC-011607" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-008" CustomerID="ACC-011628" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-009" CustomerID="ACC-011754" Data1="Yes" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-010" CustomerID="ACC-011774" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-011" CustomerID="ACC-011632" Data1="Yes" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-012" CustomerID="ACC-011606" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-013" CustomerID="ACC-012275" Data1="Yes" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-014" CustomerID="ACC-011634" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-015" CustomerID="NONE-001" Data1="No" Data2="No" Data3="Yes"/>
<Row Title="OTH-016" CustomerID="ACC-011617" Data1="Yes" Data2="No" Data3="Yes"/>
<Row Title="OTH-017" CustomerID="ACC-011629" Data1="No" Data2="No" Data3="Yes"/>
<Row Title="OTH-018" CustomerID="ACC-011633" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-019" CustomerID="ACC-011612" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-020" CustomerID="ACC-011608" Data1="No" Data2="Yes" Data3="No"/>
<Row Title="OTH-021" CustomerID="ACC-011749" Data1="Yes" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-022" CustomerID="ACC-011611" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-023" CustomerID="ACC-011613" Data1="Yes" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-024" CustomerID="ACC-011714" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-025" CustomerID="ACC-011616" Data1="Yes" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-026" CustomerID="ACC-011601" Data1="No" Data2="Yes" Data3="Yes"/>
<Row Title="OTH-027" CustomerID="ACC-012918" Data1="No" Data2="Yes" Data3="Yes"/>
</Rows>
</OtherData>
<NPSData>
<Rows>
<Row Title="NPS-0001" CustomerID="ACC-011636" Type1="LDS" Score="4.00" Year="2014"/>
<Row Title="NPS-0002" CustomerID="ACC-011636" Type1="LDS" Score="6.00" Year="2015"/>
<Row Title="NPS-0003" CustomerID="ACC-011636" Type1="PS" Score="3.00" Year="2014"/>
<Row Title="NPS-0004" CustomerID="ACC-011618" Type1="LDS" Score="7.00" Year="2014"/>
<Row Title="NPS-0005" CustomerID="ACC-011618" Type1="LDS" Score="8.00" Year="2015"/>
<Row Title="NPS-0006" CustomerID="ACC-011635" Type1="LDS" Score="6.00" Year="2014"/>
<Row Title="NPS-0007" CustomerID="ACC-011635" Type1="LDS" Score="2.50" Year="2015"/>
<Row Title="NPS-0008" CustomerID="ACC-011610" Type1="LDS" Score="7.50" Year="2014"/>
<Row Title="NPS-0009" CustomerID="ACC-011610" Type1="LDS" Score="7.50" Year="2015"/>
<Row Title="NPS-0010" CustomerID="ACC-011610" Type1="PS" Score="7.67" Year="2015"/>
<Row Title="NPS-0011" CustomerID="ACC-011627" Type1="LDS" Score="5.50" Year="2014"/>
<Row Title="NPS-0012" CustomerID="ACC-011627" Type1="LDS" Score="8.67" Year="2015"/>
<Row Title="NPS-0013" CustomerID="ACC-011748" Type1="LDS" Score="7.00" Year="2014"/>
<Row Title="NPS-0014" CustomerID="ACC-011748" Type1="LDS" Score="8.00" Year="2015"/>
<Row Title="NPS-0015" CustomerID="ACC-011748" Type1="PS" Score="6.00" Year="2015"/>
<Row Title="NPS-0016" CustomerID="ACC-011628" Type1="LDS" Score="7.00" Year="2015"/>
<Row Title="NPS-0017" CustomerID="ACC-011754" Type1="LDS" Score="7.50" Year="2015"/>
<Row Title="NPS-0018" CustomerID="ACC-011754" Type1="PS" Score="5.00" Year="2014"/>
<Row Title="NPS-0019" CustomerID="ACC-011774" Type1="LDS" Score="7.50" Year="2014"/>
<Row Title="NPS-0020" CustomerID="ACC-011606" Type1="LDS" Score="8.00" Year="2014"/>
<Row Title="NPS-0021" CustomerID="ACC-012275" Type1="LDS" Score="8.00" Year="2014"/>
<Row Title="NPS-0022" CustomerID="ACC-012275" Type1="LDS" Score="7.00" Year="2015"/>
<Row Title="NPS-0023" CustomerID="ACC-011634" Type1="LDS" Score="3.67" Year="2014"/>
<Row Title="NPS-0024" CustomerID="ACC-011617" Type1="LDS" Score="10.0" Year="2014"/>
<Row Title="NPS-0025" CustomerID="ACC-011617" Type1="LDS" Score="10.0" Year="2015"/>
<Row Title="NPS-0026" CustomerID="ACC-011629" Type1="LDS" Score="8.00" Year="2014"/>
<Row Title="NPS-0027" CustomerID="ACC-011629" Type1="LDS" Score="8.00" Year="2015"/>
<Row Title="NPS-0028" CustomerID="ACC-011633" Type1="LDS" Score="7.67" Year="2014"/>
<Row Title="NPS-0029" CustomerID="ACC-011633" Type1="LDS" Score="7.50" Year="2015"/>
<Row Title="NPS-0030" CustomerID="ACC-011633" Type1="PS" Score="7.00" Year="2014"/>
<Row Title="NPS-0031" CustomerID="ACC-011612" Type1="LDS" Score="6.00" Year="2014"/>
</Rows>
</NPSData>
</root>
我希望能够根据CRMData的Name1字段对列表进行排序。
我使用的样式表是;
<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
<xsl:output method="html" indent="no"/>
<!--<xsl:strip-space elements="*"/> SharePoint doesn't like this -->
<xsl:decimal-format NaN=""/>
<xsl:param name="dvt_apos">'</xsl:param>
<xsl:param name="ManualRefresh"></xsl:param>
<xsl:variable name="dvt_1_automode">0</xsl:variable>
<xsl:variable name="perRow" select="3" />
<xsl:template match="/root/CRMData/Rows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:SharePoint="Microsoft.SharePoint.WebControls">
<table>
<xsl:apply-templates
mode = "tr"
select = "Row[position() mod $perRow = 1]" />
</table>
</xsl:template>
<xsl:template match="Row" mode="tr">
<tr>
<xsl:call-template name="blank" />
<xsl:variable name="td" select=". | following-sibling::Row[position() < $perRow]" />
<xsl:apply-templates mode="td" select="$td" />
<xsl:if test="count($td) < $perRow">
<xsl:call-template name="filler">
<xsl:with-param name="rest" select="$perRow - count($td)" />
</xsl:call-template>
</xsl:if>
<xsl:call-template name="blank" />
</tr>
</xsl:template>
<xsl:template match="Row" mode="td">
<xsl:variable name="id" select="@Title" />
<xsl:variable name="Kendata" select="/root/KenData/Rows/Row[@CustomerID=$id]" />
<xsl:variable name="Otherdata" select="/root/OtherData/Rows/Row[@CustomerID=$id]" />
<xsl:variable name="NPSdata" select="/root/NPSData/Rows/Row[@CustomerID=$id and @Type1='LDS' and @Year='2015']" />
<xsl:variable name="bgcolor">
<xsl:choose>
<xsl:when test="$NPSdata/@Score >'7.0'">
<xsl:value-of select="'#00ff00'" />
</xsl:when>
<xsl:when test="$NPSdata/@Score >'5.0'">
<xsl:value-of select="'#ffff00'" />
</xsl:when>
<xsl:when test="$NPSdata/@Score >'0'">
<xsl:value-of select="'#ff0000'" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'#ffffff'" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<td valign="top">
<table frame="box" style="border-collapse: collapse">
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px;text-align:center">
<xsl:value-of select="@Name1"/>
</td>
</tr>
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px;text-align:center;background-color:{$bgcolor}">NPS -
<xsl:value-of select="$NPSdata/@Score"/>
</td>
</tr>
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px;text-align:center">Data1 -
<xsl:value-of select="$Otherdata/@Data1"/>
</td>
</tr>
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px;text-align:center">Data2 -
<xsl:value-of select="$Otherdata/@Data2"/>
</td>
</tr>
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px;text-align:center">
<xsl:value-of select="$Kendata/@Version"/>
-
<xsl:value-of select="$Kendata/@Date1"/>
</td>
</tr>
</table>
</td>
</xsl:template>
<xsl:template name="filler">
<xsl:param name="rest" select="0" />
<xsl:if test="$rest">
<xsl:call-template name="blank" />
<xsl:call-template name="filler">
<xsl:with-param name="rest" select="$rest - 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="blank">
<td valign="top">
<table style="border-collapse: collapse">
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px"></td>
</tr>
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px"></td>
</tr>
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px"></td>
</tr>
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px"></td>
</tr>
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px"></td>
</tr>
<tr>
<td class="ms-rteTableOddCol-0" style="width:335px"></td>
</tr>
</table>
</td>
</xsl:template>
</xsl:stylesheet>
这产生输出为;
1测试客户7测试客户14测试客户
6测试客户22测试客户12测试客户
我希望将输出分类为生成;
1测试客户2测试客户3测试客户
4测试客户5测试客户6测试客户
提前致谢
答案 0 :(得分:0)
您可以使用xsl:sort和micro-pipe-lining来实现排序表格化。例如,如果输入文档是......
<recordset name="resId" >
<record n="1">B</record>
<record n="2">C</record>
<record n="0">A</record>
<record n="4">E</record>
<record n="3">D</record>
</recordset>
...应用此XSLT 2.0样式表...
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="html" version="5" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:variable name="num-cols" select="2" />
<xsl:template match="/">
<hmtl>
<head>
<title>Records in tabular format</title>
</head>
<body>
<h1>Records in a <xsl:value-of select="$num-cols"/> table</h1>
<xsl:apply-templates/>
</body>
</hmtl>
</xsl:template>
<xsl:template match="recordset">
<table>
<thead>
<tr>
<xsl:for-each select="1 to $num-cols">
<td>record</td>
</xsl:for-each>
</tr>
</thead>
<tbody>
<xsl:variable name="records">
<!-- Hold the records in a variable, so we can sort them. -->
<xsl:apply-templates select="record" mode="copy">
<xsl:sort select="@n" data-type="number" stable="yes" />
</xsl:apply-templates>
</xsl:variable>
<xsl:for-each-group select="$records/record" group-adjacent="count(preceding-sibling::*) idiv $num-cols">
<!-- Normal tabularisation technique. Our data is already sorted. -->
<tr>
<xsl:apply-templates select="current-group()" />
<xsl:for-each select="count(current-group()) + 1 to $num-cols">
<!-- The input document is ragged. So fill in the empty cells. -->
<td> </td>
</xsl:for-each>
</tr>
</xsl:for-each-group>
</tbody>
</table>
</xsl:template>
<xsl:template match="record" mode="copy">
<xsl:copy-of select="." />
</xsl:template>
<xsl:template match="record">
<td>
<xsl:value-of select="." />
</td>
</xsl:template>
</xsl:transform>
...将产生此输出html页面......
<!DOCTYPE HTML>
<hmtl>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Records in tabular format</title>
</head>
<body>
<h1>Records in a 2 table</h1>
<table>
<thead>
<tr>
<td>record</td>
<td>record</td>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
<tr>
<td>E</td>
<td> </td>
</tr>
</tbody>
</table>
</body>
</hmtl>
答案 1 :(得分:0)
简短回答:您需要在两次通过中执行此操作。首先对记录进行排序,然后将它们分成行和列。
现在,为了简化手头问题的示例,请考虑以下样式表:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="columns" select="3"/>
<xsl:template match="/root">
<!-- first pass -->
<xsl:variable name="sorted-rows">
<xsl:for-each select="CRMData/Rows/Row">
<xsl:sort select="@Name1" data-type="text" order="ascending"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:variable>
<!-- output -->
<table border="1">
<xsl:for-each select="exsl:node-set($sorted-rows)/Row[position() mod $columns = 1]" >
<tr>
<xsl:apply-templates select=". | following-sibling::Row[position() < $columns]"/>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="Row">
<td>
<xsl:value-of select="@Name1"/>
</td>
</xsl:template>
</xsl:stylesheet>
应用于您的示例输入,此处的结果将如下所示:
请注意,这与您发布的预期输出略有不同,因为记录按字母顺序排序 - 因此19
位于2
之前。我认为是正确的顺序,并且您的实际数据实际上并不包含数字前缀。否则,您必须将排序指令更改为:
<xsl:sort select="substring-before(@Name1, ' ')" data-type="number" order="ascending"/>
与您的问题无关:我建议您使用 keys 从其他行组中获取数据。