2012-12-20 128 views
2

我有一些XML,看起来像这样:XPath中,选择一个备用节点

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

编辑container S的顺序是不固定的。

我使用xPath(通过ruby的nokogiri)从本文档中选择文本。我希望能够在container,type为02,但textcontainertype为01,如果不存在。

我可以做

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

这将让我的两个元素,然后我可以使用一些红宝石进行排序,并采取正确的(因为这将首先返回01元),但这种感觉笨拙。

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

干杯!

+1

虽然纯xpath解决方案可能更清洁,但另一种方法是先单独尝试02,然后单独检查01。当然,这可能看起来像现在一样混乱 – Himanshu

+0

这就是我现在要做的,我正在寻找这个解决方案的唯一原因是我认为“02”记录更可能不存在,而我假设任何纯xpath解决方案比从ruby进行两个xpath查询要快。 –

回答

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']) 

拿过<text>从类型= 1,且仅当类型= 2不存在使用该返回它:

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

希望帮助它清除掉,我知道你正在寻找一些干净的东西,但是对于你想要使用XPath的东西来说,这有点麻烦。

+0

谢谢!它确实做我所需要的 - 但正如你所说,它的复杂程度可能混淆了我我试图去做 - 我会检查看看有什么更快,但它必须快得多,以保证这种复杂程度。 –

+0

Np,我会对你的结果感兴趣 – JWiley

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"]))] 

它是通过

相当缓慢
+0

我不能假定订单是固定的:(任何其他想法? –

+0

我更新了它... – BeniBela