我试图理解为什么当我将定义更改为使用具有相同值的参数时,我的代码会产生不同的结果,因为我想从xls中的其他位置调用模板,提供路径作为参数,这样代码就可以重用,而不是根据XML 中的位置进行定制
<!-- Create SLA bar section -->
<xsl:template name="createBars">
<xsl:param name="varPath"/> <!-- Not used -->
<xsl:param name="varNode"/> <!-- Not used -->
<table id="tblgraph" align="center" width="100" cellpadding="0" cellspacing="0" border="0">
<tr style='width:100%'>
<td align="left" width="100%" height="10" colspan="12">
<table cellpadding="0" cellspacing="0" border="1" width="100%" style='color:black; font-weight:bold;'>
<xsl:for-each select="/page/workgroups/workgroup/queue/currentshift/servicelevels">
<xsl:for-each select="servicelevel">
<xsl:variable name="keyValue">
<xsl:value-of select="key"/>
</xsl:variable>
<xsl:variable name="valueContent">
<xsl:value-of select="value"/>
</xsl:variable>
<tr>
<td>
<xsl:value-of select="$keyValue"/>
</td>
<td>
<xsl:value-of select="$valueContent"/>..
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</td>
</tr>
</table>
</xsl:template>
创建表的预期输出
0..20 |-。。20..30|-。。30..40|-。。40.50 |-。。50.60|-。。60..70|-。。70+|-。。
然而,当我更改代码以使用已在模板调用部分设置的传递参数时,替换
<xsl:for-each select="/page/workgroups/workgroup/queue/currentshift/servicelevels">
带有
<xsl:for-each select="msxsl:node-set($varPath)">
和
<xsl:for-each select="servicelevel">
带有
<xsl:for-each select="msxsl:node-set($varNode)">
结果是空的
结果:
。。
在调用配置文件中,参数设置如下:
<!-- Set path and node for the information to be processed to build the bars -->
<xsl:variable name="tempPath">
<xsl:copy-of select="/page/workgroups/workgroup/queue/currentshift/servicelevels"/>
</xsl:variable>
<xsl:variable name="tempNode">
<xsl:copy-of select="servicelevel"/>
</xsl:variable>
<!-- Call the template to build the bars -->
<xsl:call-template name="createBars">
<xsl:with-param name="varPath" select="$tempPath"/>
<xsl:with-param name="varNode" select="$tempNode"/>
</xsl:call-template>
如何指定表示路径的参数,如:/page/workgroups/workgroup/queue/currentshift/servicelevels
和servicelevel
可以修改为例如:/page/workgroups/workgroup/queue/currentperiod/abandoneds
和abandoned
这一切都能够调用模板,根据统计信息中类似的条目创建条形值。
XML文件:
<?xml version="1.0"?>
<page id="7080959">
<name>Test Ruud</name>
<description/>
<server>reg6699cic01</server>
<created>2014/07/25 08:12:01 AM</created>
<workgroups>
<workgroup>
<name>ITSD_APAC_Windows_Manila</name>
<agents>2</agents>
<queue>
<longesttalktime>-</longesttalktime>
<longestwaiting>-</longestwaiting>
<currentperiod>
<numberabandoned>0</numberabandoned>
<periodlength>00:11:59</periodlength>
<servicelevels>
<servicelevel>
<key>0..20</key>
<value>98</value>
</servicelevel>
<servicelevel>
<key>20..30</key>
<value>100</value>
</servicelevel>
</servicelevels>
<abandoneds>
<abandoned>
<key>0..20</key>
<value>-</value>
</abandoned>
<abandoned>
<key>20..30</key>
<value>-</value>
</abandoned>
</abandoneds>
</currentperiod>
<currentshift>
<numberabandoned>4</numberabandoned>
<periodlength>21:11:59</periodlength>
<servicelevels>
<servicelevel>
<key>0..20</key>
<value>-</value>
</servicelevel>
<servicelevel>
<key>20..30</key>
<value>-</value>
</servicelevel>
</servicelevels>
<abandoneds>
<abandoned>
<key>0..20</key>
<value>1</value>
</abandoned>
<abandoned>
<key>20..30</key>
<value>-</value>
</abandoned>
</abandoneds>
</currentshift>
</queue>
</workgroup>
</workgroups>
</page>
所以条形模板的目标是:
/page/workgroups/workgroup/queue/currentshift/servicelevels
,具有用于ServiceLevel
的六个子节点/page/workgroups/workgroup/queue/currentshift/abandoneds
,具有用于abandoned
的六个子节点/page/workgroups/workgroup/queue/currentperiod/servicelevel
,具有用于servicelevel
的六个子节点/page/workgroups/workgroup/queue/currentperiod/abandoneds
,具有用于abandoned
的六个子节点每个节点都包含
Key
Value
期待您的回复
首先,我假设您获得空结果集的原因:您的具体问题源于您将空节点集传递给模板的第二个参数:
<xsl:variable name="tempNode">
<xsl:copy-of select="servicelevel"/>
</xsl:variable>
XSLT处理器评估此表达式时,会尝试查找当前节点的所有<servicelevel>
子级。最有可能的是,由于您使用第一个参数的完整路径,因此没有
<xsl:variable name="tempPath">
<xsl:copy-of select="/page/workgroups/workgroup/queue/currentshift/servicelevels"/>
</xsl:variable>
向我们表明,定义变量的上下文可能是而不是/page/workgroups/workgroup/queue/currentshift/servicelevels
。
现在修复:根据XSLT判断,您尝试定义位于tempPath
中的基节点集,然后在tempNode
中提供的相对路径所给出的这些节点的子节点上循环。正如@michael.hor257k已经指出的那样,这在XSLT中不起作用(至少不是1.0或2.0),尽管实际上您传递的不是字符串而是一个空节点。
然而,在您的特定情况下,您可以通过消除内部循环来简化模板。这应该是可能的,因为在外循环中没有不在内循环中的功能。因此,不使用两个参数调用模板,只使用一个包含内部循环所有节点的参数:
<xsl:variable name="tempNode">
<xsl:copy-of select="/page/workgroups/workgroup/queue/currentshift/servicelevels/servicelevel"/>
</xsl:variable>
<!-- Call the template to build the bars -->
<xsl:call-template name="createBars">
<xsl:with-param name="varNode" select="$tempNode"/>
</xsl:call-template>
您简化模板如下:
<!-- Create SLA bar section -->
<xsl:template name="createBars">
<xsl:param name="varNode"/>
<table id="tblgraph" align="center" width="100"
cellpadding="0" cellspacing="0" border="0">
<tr style='width:100%'>
<td align="left" width="100%" height="10" colspan="12">
<table cellpadding="0" cellspacing="0" border="1"
width="100%" style='color:black; font-weight:bold;'>
<xsl:for-each select="msxsl:node-set($varNode)">
... add here the contents of the !inner! loop
</xsl:for-each>
</table>
</td>
</tr>
</table>
</xsl:template>
这样就不需要评估相对路径了!
完整解决方案
以下XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:common="http://exslt.org/common"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<xsl:variable name="tempPath">
<xsl:copy-of select="/page/workgroups/workgroup/queue/currentshift/servicelevels/servicelevel"/>
</xsl:variable>
<tables>
<xsl:call-template name="createBars">
<xsl:with-param name="varNode" select="$tempPath"/>
</xsl:call-template>
<xsl:call-template name="createBars">
<xsl:with-param name="varNode" select="/page/workgroups/workgroup/queue/currentperiod/servicelevels/servicelevel"/>
</xsl:call-template>
<xsl:call-template name="createBars">
<xsl:with-param name="varNode" select="/page/workgroups/workgroup/queue/currentperiod/abandoneds/abandoned"/>
</xsl:call-template>
</tables>
</xsl:template>
<xsl:template name="createBars">
<xsl:param name="varNode"/>
<table id="tblgraph" align="center" width="100" cellpadding="0" cellspacing="0" border="0">
<tr style='width:100%'>
<td align="left" width="100%" height="10" colspan="12">
<table cellpadding="0" cellspacing="0" border="1" width="100%" style='color:black; font-weight:bold;'>
<xsl:for-each select="common:node-set($varNode)">
<tr>
<td><xsl:value-of select="key"/></td>
<td><xsl:value-of select="value"/>..</td>
</tr>
</xsl:for-each>
</table>
</td>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
从问题中的XML生成以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<tables xmlns:common="http://exslt.org/common">
<table id="tblgraph" align="center" width="100" cellpadding="0" cellspacing="0" border="0">
<tr style="width:100%">
<td align="left" width="100%" height="10" colspan="12">
<table cellpadding="0" cellspacing="0" border="1" width="100%" style="color:black; font-weight:bold;">
<tr>
<td/>
<td>..</td>
</tr>
</table>
</td>
</tr>
</table>
<table id="tblgraph" align="center" width="100" cellpadding="0" cellspacing="0" border="0">
<tr style="width:100%">
<td align="left" width="100%" height="10" colspan="12">
<table cellpadding="0" cellspacing="0" border="1" width="100%" style="color:black; font-weight:bold;">
<tr>
<td>0..20</td>
<td>98..</td>
</tr>
<tr>
<td>20..30</td>
<td>100..</td>
</tr>
</table>
</td>
</tr>
</table>
<table id="tblgraph" align="center" width="100" cellpadding="0" cellspacing="0" border="0">
<tr style="width:100%">
<td align="left" width="100%" height="10" colspan="12">
<table cellpadding="0" cellspacing="0" border="1" width="100%" style="color:black; font-weight:bold;">
<tr>
<td>0..20</td>
<td>-..</td>
</tr>
<tr>
<td>20..30</td>
<td>-..</td>
</tr>
</table>
</td>
</tr>
</table>
</tables>
注:
- 首先将XPath表达式分配给变量,然后将其作为参数传递,这在第一个模板调用中是不起作用的
- 我无法测试微软版本的
node-set()
,但xsltproc
中提供的common:node-set()
函数有望显示出相同的行为 - 添加
<tables></tables>
标记只是为了创建一个有效的目标XML文件 - 通过去除局部变量,
<td>
标签的输出被稍微简化