2

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

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

编辑s的顺序container不固定。

我正在使用 xPath(通过 ruby​​ 的 nokogiri)从该文档中选择文本。我希望能够从text02中获取,但如果不存在,container则从01 中获取。typetextcontainertype

我可以

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

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

我已经搜索了stackoverflow,没有任何明显的东西可以让我使用简单的xpath对元素输出进行排序,但是有没有办法命令xpath获取一个元素,但如果它不存在则回退到另一个?

干杯!

4

3 回答 3

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())))))

我会在一秒钟内分解它...


好的,所以这部分:

连接(

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

<text>如果存在,则从 type=2 获取。

这部分:

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

从type <text>=1 中获取,只有在 type=2 不存在时才返回它:

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

希望这有助于清除它,我知道您正在寻找一些干净的东西,但是对于您想要使用 XPath 的东西,它有点混乱。

于 2012-12-20T16:03:48.933 回答
0

如果顺序是固定的,您可以选择两者,然后取最后一个。如果文档中只有 02,则为 02,如果文档中之前有 01,则为 02...

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

它的速度很慢

于 2012-12-20T12:49:59.187 回答
0
(//container/type[.='02'], //container/type[.='01'])[1]/..

外括号从带有 text value 的 type 元素构造一个序列02,然后是带有 text value 的类型01。运算符省略任何未定义的,值,因此如果缺少一个,则序列仅包含另一个,如果两者都缺少,则为空序列。

[1]从该序列中选择第一个项目

/..是 的缩写语法,在这种情况下parent::node()相当于你的。parent::container

您可能希望这会起作用:

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

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

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

但这给了你01容器,因为括号的结果是文档顺序中的两个节点。

于 2018-07-19T10:37:50.083 回答