xslt传递位置作为参数产生奇怪的结果?

时间:2012-07-05 17:52:56

标签: xml xslt xpath position

我有一个xml文件,如下所示:

<section>
  <title> title of section </title>
  <table>
     <title> title of table</title>
     <tableData columns = 2>
     <column width ="50"/>
     <column width ="100"/>
     <tableHead>
        <row>
             <entry>column 1</entry>
        </row> 
        <row>
             <entry>column 2</entry>
        </row>
     </tableHead>
     <tableBody>
       <row>
             <entry>text</entry>
             <entry>abc</entry>
       </row> 
       <row>
             <entry>text</entry>
             <entry>dbe</entry>
      </row> 
       <row>
             <entry>text</entry>
             <entry>fgh</entry>
       </row> 
     </tableBody>
   </table>
 </section>

我需要处理tableHead / row / entry中的每个条目,并以包含columnWidth的某种格式将其吐出。所以,我的输出必须看起来像 {“name”:“第1列”,“宽度”:“50px”},{“名称”:“第2列”,“宽度”:“100px”}

我的转换看起来像这样

 <xsl:template match="//table/tableHead/row/entry">
    <xsl:text>{"name": "</xsl:text><xsl:value-of select"."/>
    <xsl:text>", "width":"</xsl:text>

    <xsl:call-template name="get_column_width">
       <xsl:with-param name ="rowNum">
          <xsl:value-of sellect"position()"/>
       </xsl:with-param>
    </xsl:call-template>
  </xsl:template>


 <xsl:template name ="get_column_width">
     <xsl:param-name="rowNum">
     <xsl:value-of select="../../../columnWidth[$rowNum]/@width"/>
     <xsl:text>px"}</xsl:text>
 </xsl:template>

奇怪的是,这会产生{“name”:“第1列”,“宽度”:“50 100px”},{“name”:“第2列”,“宽度”:“50 100px”}

但是,当我只输出rowNum参数时,我得到了我期望的结果:

{“name”:“第1列”,“宽度”:1px“},{”名称“:”第2列“,”宽度“:”2px“}

因此,rowNum为1和2,因此select语句将使用columnWidth [1]和columnWidth [2],但无论出于何种原因,它只输出它们。我尝试在select中使用columnWidth [1]并输出50,正如我所料。 columnWidth [2]输出100.我真的很困惑。使用previous-sibling给出了相同的结果。我的模板匹配有问题吗?

不幸的是,更改xml格式不是一种选择。

2 个答案:

答案 0 :(得分:2)

而不是

<xsl:value-of select="../../../columnWidth[$rowNum]/@width"/>

使用

<xsl:value-of select="../../../columnWidth[position() = $rowNum]/@width"/>

<强>解释

在XPath中:

someExpression[someInteger]

是:

的简写
someExpression[position() = someInteger]

然而,如果:

someExpression[$someVariableReference]

XPath 1.0处理器通常不知道变量中包含的值和类型。因此,它将此变量转换为布尔值(true()false())以执行完整评估。

根据定义:

boolean(someNumber)

相当于:

not(somenumber = 0)

由于数字1和2均不为零,因此在两种情况下谓词[$rowNum]均为true()

因此:

../../../columnWidth[$rowNum]/@width

选择width元素的columnWidth属性。

答案 1 :(得分:1)

$ rowNum的值是结果树片段(或在XSLT 2.0中,文档节点)。结果树片段(或节点)的有效布尔值始终为true。你可能想象这个值是一个整数。但是要将变量设置为整数,您应该编写

<xsl:with-param name="x" select="position()"/>

<xsl:with-param name="x">
  <xsl:value-of select="position()"/>
</xsl:with-param>

可悲的是,后一种结构看起来非常普遍,考虑到它的冗长和低效,以及偶尔(如此处)给出了错误的答案。