XPath:默认为'节点A',选择'节点B'相反,如果节点B'不是空的

时间:2012-09-11 13:02:37

标签: xml xpath if-statement infopath

我需要创建一个执行以下操作的XPath表达式:

  • 默认情况下返回'NodeA'中的元素
  • 如果'NodeB'不为空,则返回其内部的元素。

这是一些示例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的新手,并感谢您提供的任何帮助。

3 个答案:

答案 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:NodeAmy: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()