【问题标题】:How do i increment a global variable while reading my specific tag using xslt2.0?如何在使用 xslt2.0 读取特定标签时增加全局变量?
【发布时间】:2011-11-26 19:14:42
【问题描述】:

这是我的 xml 文档。

<w:document xmlns:w="w">
 <w:body>
   <w:p>
        <w:r>
           <w:t>
               Para1
            </w:t>
        </w:r>
     </w:p>
   <w:p>
        <w:r>
           <w:t>
               Para2
            </w:t>
        </w:r>
     </w:p>
   <w:p>
        <w:r>
           <w:t>
               Para3
            </w:t>
        </w:r>
     </w:p>
   <w:p>
        <w:r>
           <w:t>
               Para4
            </w:t>
        </w:r>
     </w:p>
   <w:p>
        <w:r>
           <w:t>
               Para5
            </w:t>
        </w:r>
     </w:p>

   <w:tbl>
         <w:tr>
            <w:tc>
               <w:p>
                  <w:r>
                    <w:t>
                         Para6
                    </w:t>
                   </w:r>
                </w:p>
              </w:tc>
            <w:tc>
               <w:p>
                  <w:r>
                    <w:t>
                         Para7 
                    </w:t>
                   </w:r>
                </w:p>
              </w:tc>
           </w:tr>
        </w:tbl>
     <w:p>
        <w:r>
           <w:t>
               Para8
            </w:t>
        </w:r>
     </w:p>
  <w:tbl>
         <w:tr>
            <w:tc>
               <w:p>
                  <w:r>
                    <w:t>
                         Para9
                    </w:t>
                   </w:r>
                </w:p>
              </w:tc>
            <w:tc>
               <w:p>
                  <w:r>
                    <w:t>
                         Para10
                    </w:t>
                   </w:r>
                </w:p>
              </w:tc>
           </w:tr>
        </w:tbl>
    <w:p>
        <w:r>
           <w:t>
               Para11
            </w:t>
        </w:r>
     </w:p>
</w:body>
</w:document>

现在,我想在遇到&lt;w:tbl&gt;&lt;w:tr&gt; 时增加我的全局变量。对于我上面的xml 文件,它在&lt;w:tbl&gt; 中有两个&lt;w:tr&gt; 节点。

所以,例如:
                1. 如果我当前的节点是 Para8 那么它的计数将是 1。
                2. 如果我当前的节点是 para11,那么它的计数将是 2。
   

我是怎么做到的?

【问题讨论】:

  • 这篇文章应该回答你的问题:[in-xslt-how-do-i-increment-a-global-variable-from-a-different-scope][1] [1]: @ 987654321@

标签: xml xslt xpath


【解决方案1】:

XSLT 是一种函数式语言,在任何函数式语言中,一个变量(一组)的值都无法更新。人们需要一种“范式转变”——开始以一种功能性的方式思考——以理解更新变量的“能力”根本不是必需的。对于任何命令式算法(使用变量更新),都有相应的函数式算法(不需要更新任何变量)。

与命令式编程风格相比,使用函数式编程风格有许多优势——主要是函数式程序更易于阅读、理解、维护甚至证明是正确的。由于变量是不可变的,编译器的优化器可以执行更积极的优化,从而产生更高效、高度优化的编译程序。

在这种特殊情况下,无需更新变量即可获得所需的计数

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:w="w">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:for-each select=
      "//w:t
         [contains(., 'Para8')
         or
          contains(., 'Para11')
         ]
     ">
       <xsl:number level="any" count="w:tbl/w:tr"/>
       <xsl:text>&#xA;</xsl:text>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时

 <w:document xmlns:w="w">
    <w:body>
        <w:p>
            <w:r>
                <w:t>                Para1             </w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:r>
                <w:t>                Para2             </w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:r>
                <w:t>                Para3             </w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:r>
                <w:t>                Para4             </w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:r>
                <w:t>                Para5             </w:t>
            </w:r>
        </w:p>
        <w:tbl>
            <w:tr>
                <w:tc>
                    <w:p>
                        <w:r>
                            <w:t>                          Para6                     </w:t>
                        </w:r>
                    </w:p>
                </w:tc>
                <w:tc>
                    <w:p>
                        <w:r>
                            <w:t>                          Para7                      </w:t>
                        </w:r>
                    </w:p>
                </w:tc>
            </w:tr>
        </w:tbl>
        <w:p>
            <w:r>
                <w:t>                Para8             </w:t>
            </w:r>
        </w:p>
        <w:tbl>
            <w:tr>
                <w:tc>
                    <w:p>
                        <w:r>
                            <w:t>                          Para9                     </w:t>
                        </w:r>
                    </w:p>
                </w:tc>
                <w:tc>
                    <w:p>
                        <w:r>
                            <w:t>                          Para10                     </w:t>
                        </w:r>
                    </w:p>
                </w:tc>
            </w:tr>
        </w:tbl>
        <w:p>
            <w:r>
                <w:t>                Para11             </w:t>
            </w:r>
        </w:p>
    </w:body>
</w:document>

产生想要的正确结果

1
2

如果这个值应该包含在一个变量中——稍后在其范围内的某个地方使用,只需将变量定义为

 <xsl:variable name="vMyCount">
   <xsl:number level="any" count="w:tbl/w:tr"/>
 </xsl:variable>

您可以使用此变量,如下面的转换:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:w="w">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:for-each select=
      "//w:t
         [contains(., 'Para5')
         or
          contains(., 'Para8')
         or
          contains(., 'Para11')
         ]
     ">
     <xsl:variable name="vMyCount">
       <xsl:number level="any" count="w:tbl/w:tr"/>
     </xsl:variable>
     <xsl:value-of select=
      "concat($vMyCount,
              substring('0', 1 + boolean(string($vMyCount)))
              )"/>
       <xsl:text>&#xA;</xsl:text>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

产生相同的正确结果

0
1
2

【讨论】:

  • @_Dimitre Novatchev :它工作正常。但是,例如,如果我当前的节点是 Para5,那么它的计数显示为 Nan。因为当时没有 计数。所以,这个新案例可以返回 0 吗?
  • @Saravanan:我需要阅读&lt;xsl:number&gt; 上的规范——这很复杂。您可以使用替代方法:` ' - 这可以正常工作。
  • @_Dimitre Novatchev: 它适用于Para5的新案例,但不在旧案例之上。实际上,它没有计算旧案例的。有没有检查 vMyCount 是否为数字的方法?
  • @Saravan:“旧案子”是什么意思?
  • @Saravan:我的评论是正确的。为了您的方便和易于理解,我更新了我的答案(在最后)——生成了所有案例的正确答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多