XSL:当路径作为参数提供时输出丢失

时间:2014-10-21 12:09:59

标签: xslt-1.0

我试着理解为什么在我的代码中更改定义以使用具有相同值的参数时产生不同的结果,因为我想从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/servicelevelsservicelevel
可以修改为例如:
 /page/workgroups/workgroup/queue/currentperiod/abandonedsabandoned

这一切都能够调用模板,根据统计信息中的相似条目创建条形值。

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

期待您的回复

1 个答案:

答案 0 :(得分:0)

首先,我假设您获取一个空结果集:您的具体问题来自于您将空节点集传递给模板的第二个参数:

<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()的Microsoft版本,但common:node-set()中提供的xsltproc函数有望显示相同的行为。
  • 刚刚添加<tables></tables>标记以创建有效的目标XML文件。
  • 通过删除局部变量,<td>标签的输出略有简化。