这是我的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>
现在,我想在<w:tbl><w:tr>
遇到我的全局变量时递增。对于我上面的xml文件,它在<w:tr>
内有两个<w:tbl>
个节点。
So, for example : 1. if my current node is Para8 then it's count will be 1. 2. if my current node is para11 then it's count will be 2.
我是怎么做到的?
答案 0 :(得分:2)
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>
</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>
</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
产生相同的正确结果:
0
1
2