我需要创建一个执行以下操作的XPath表达式:
这是一些示例XML,以便可以清楚地看到我的目标结构(我正在使用MS InfoPath):
<?xml version="1.0" encoding="UTF-8"?><?mso-infoPathSolution solutionVersion="1.0.0.10" productVersion="14.0.0" PIVersion="1.0.0.0" href="file:///C:\Documents%20and%20Settings\Chris\Local%20Settings\Application%20Data\Microsoft\InfoPath\Designer3\9016384cab6148f6\manifest.xsf" ?><?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.3"?>
<my:myFields xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-09-07T14:19:10" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xml:lang="en-us">
<my:NodeASection>
<my:NodeA>2012-09-13</my:NodeA>
</my:NodeASection>
<my:NodeBSection>
<my:NodeBGroup>
<my:NodeB>2012-09-14</my:NodeB>
</my:NodeBGroup>
</my:NodeBSection>
</my:myFields>
此XPath表达式可用于评估NodeB是否存在文本:boolean(//my:NodeB[(text())])
我听说过“Becker方法”,但我不确定当两个节点都存在时它是如何应用的。我是非常 XPath的新手,并感谢您提供的任何帮助。
答案 0 :(得分:17)
如果NodeB存在(并且具有文本内容),则此XPath表达式返回NodeB,而在另一种情况下,返回NodeA:
//my:NodeB[text()] | //my:NodeA[text() and not(//my:NodeB[text()])]
如果您想获取所有子元素,可以在所选节点之后附加/*
,如下所示
//my:NodeB[text()]/* | //my:NodeA[text() and not(//my:NodeB[text()])]/*
答案 1 :(得分:4)
正确的XPath表达式是:
(//my:NodeB[node()] | //my:NodeA[not(//my:NodeB/node())])/node()
由于谓词中的条件是互斥的,因此只有其中一个可以是true()
,这可以保证括号内的表达式只选择其中一个节点。
因此,上面的表达式选择任何子节点:my:NodeB
如果它有子节点,或者my:NodeA
- otherwize。
这里我们假设至少有一个名为my:NodeA
的元素,并且XML文档中至多存在一个名为my:NodeB
的元素。
另一个假设是前缀my
绑定到的命名空间已经“注册”了XPath表达式求值程序(您正在使用的特定XPath实现)。
请注意,在提供的XML文档中,my:NodeA
和my:NodeB
元素都没有任何元素子元素(它们都只有一个文本节点子元素) - 所以我假设通过“元素”你实际上意味着“节点”。
答案 2 :(得分:1)
如果可以安全地依赖于任何NodeA将以文档顺序出现在NodeB之前(如您的示例所暗示的那样),那么选择所需元素的更简单且更高效的XPATH表达式是......
(//my:NodeA[text()]|//my:NodeB)[1]
以上选择元素。如果要选择元素的文本节点,请改为使用...
(//my:NodeA[text()]|//my:NodeB)[1]/text()
如果NodeA和NodeB之间没有位置关系(它们可以按任何相对顺序排列),并且您使用的是XPATH 2.0,则以下表达式将选择所需的文本节点。
(//my:NodeA[text()],//my:NodeB)[1]/text()