12

我需要创建一个执行以下操作的 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())])

我听说过“贝克尔方法”,但我不确定当两个节点都存在时它是如何应用的。我是XPath 的新手,非常感谢可以提供的任何帮助。

4

3 回答 3

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()])]/*
于 2012-09-11T13:11:43.347 回答
4

正确的 XPath 表达式是

(//my:NodeB[node()] | //my:NodeA[not(//my:NodeB/node())])/node()

由于谓词中的条件是互斥的,因此只能是其中一个,true()这保证了括号内的表达式只能选择两个节点中的一个。

因此,上面的表达式选择任何一个子节点:my:NodeB如果它有子节点,或者my:NodeA-- 否则。

这里我们假设XML文档my:NodeA中最多存在一个named元素和一个named元素。my:NodeB

另一个假设是前缀my绑定到的名称空间已经使用 XPath 表达式求值器(您正在使用的特定 XPath 实现)“注册”。

请注意,在提供的 XML 文档中,既没有元素my:NodeAmy:NodeB没有任何子元素(它们都只有一个文本节点子节点)——所以我假设“元素”实际上是指“节点”。

于 2012-09-12T12:42:31.527 回答
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()
于 2012-09-11T13:29:07.203 回答