Xpath,选择一个后备节点

时间:2012-12-20 11:59:27

标签: xpath

我有一些看起来像这样的XML:

<container>
  <type>01</type>
  <text>one</text>
</container>
<container>
  <type>02</type>
  <text>two</text>
</container>

编辑 container s的顺序不固定。

我正在使用xPath(通过ruby的nokogiri)从本文档中选择文本。我希望text中的container能够使用type 02,但是text的{​​{1}}带container如果不存在,则为01。

我能做到

type

哪个会给我两个元素,然后我可以使用一些ruby来排序并选择正确的元素(因为这将首先返回01元素),但这感觉很笨拙。

我已经搜索了stackoverflow并且没有什么可以立即显示允许我使用简单的xpath对元素输出进行排序,但是有没有办法命令xpath获取一个元素,但如果它不存在则回退到另一个?

干杯!

3 个答案:

答案 0 :(得分:2)

不确定你是否喜欢它,但它可以做你想要的:

concat(substring(//container[type/text() = '02']/text,1,string-length(//container[type/text()='02'])*boolean(//container[type/text()='02']/text())),substring(//container[type/text() = '01']/text,1,string-length(//container[type/text()='01'])*number(boolean(//container[type/text()='01']/text())and not(boolean(//container[type/text()='02']/text())))))

我会在一秒钟内将其分解......


好的,所以这部分:

的concat(

substring(//container[type/text() = '02']/text,1,string-length(//container[type/text()='02'])*boolean(//container[type/text()='02']/text())),

如果存在,则从类型= 2中抓取<text>

这部分:

substring(//container[type/text() = '01']/text,1,string-length(//container[type/text()='01'])

从type = 1中获取<text>,并且只有在使用此类型不存在type = 2时才返回它:

*number(boolean(//container[type/text()='01']/text())and not(boolean(//container[type/text()='02']/text())))))

希望有助于清理它,我知道你在寻找干净的东西,但是对于你想要使用XPath的东西,它有点乱。

答案 1 :(得分:0)

如果订单已修复,您可以选择两个,然后选择最后一个。它将是02,如果只有02,则02,如果文档中有一个01 ......

 (/container/type[text() = "02" or text() = "01"]/parent::container)[last()]

或更短,因为节点的值是其文本,并且比较只查找匹配对:

 (/container[type = ("01", "02")])[last()]

(至少在XPath 2中有效,不确定在XPath 1中是否相同)

-

编辑:

实际上这很容易。您可以查看//container[type = "02"],如果有一个类型为02的容器,那么您可以获取所有02个容器和所有01个容器,如果没有类型02容器,则导致:

 //container[type = "02" or (type = "01" and not(//container[type = "02"]))]

它很慢

答案 2 :(得分:0)

var wdata = [];
$(document).on('click', '.is-accordion-submenu-parent > a', function (e) {
    if (Foundation.MediaQuery.is('small only')) {
        var href = $(this).attr('href'),
            date = new Date(),
            diff = date - wdata.parentClickDate;
        if (wdata.parentHref == href && diff < 1000) {
            window.location.href = href
        }
        wdata.parentHref = href;
        wdata.parentClickDate = date;
    }
});

外部括号从具有文本值(//container/type[.='02'], //container/type[.='01'])[1]/.. 的type元素开始,然后由具有文本值02的类型构成一个序列。 01运算符会忽略所有未定义的值,因此,如果缺少一个值,则该序列仅由另一个组成,并且如果两个都缺失,则为空序列。

,从该序列中选择第一项

[1]/..的缩写语法,在这种情况下等同于您的parent::node()

您可能希望它能起作用:

parent::container

但是(至少在撒克逊语中)这给了您两个容器;或这样:

//container/(type[.='02'],type[.='01'])[1]/..

但这会为您提供(//container/(type[.='02'],type[.='01']))[1]/.. 容器,因为括号的结果是两个节点均以文档顺序