将child-node的parent-attribute和text-value的值与单个xpath-query相结合

时间:2016-12-14 09:38:04

标签: xml xpath attributes extract

除了参数的值this question之外,我还试图提取节点的文本。

<parents name='Parents'>
  <Parent id='1' name='Parent_1'>
    <Children name='Children'>
      <child name='Child_1' id='1'>child1_Parent_1</child>
      <child name='Child_2' id='2'>child2_Parent_1</child>
      <child name='Child_3' id='3'>child3_Parent_1</child>
      <child name='Child_4' id='4'>child4_Parent_1</child>
    </Children>
  </Parent>
  <Parent id='2' name='Parent_2'>
    <Children name='Children'>
      <child name='Child_1' id='8'>child1_parent2</child>
      <child name='Child_2' id='7'>child2_parent2</child>
      <child name='Child_4' id='6'>child4_parent2</child>
      <child name='Child_3' id='5'>child3_parent2</child>
    </Children>
  </Parent>
</parents>

当我使用&#34; child1&#34;运行匹配查询时,我想获得此输出:

Parent_1
child1_Parent_1

一次查询两个值

此查询:

//Parent[@id='1']/Children/child[text()[matches(.,"^child1","i")]]/(text()|../../@name)

的产率:

{}name="Parent_1"
child1_Parent_1

接近我正在寻找的结果。但我想干净的属性值,没有属性名称。

使用xs清除属性值:字符串

这可以通过字符串转换完成:

//Parent[@id='1']/Children/child[text()[matches(.,"^child1","i")]]/xs:string(../../@name)

给了我一个干净的属性值:

Parent_1

两个查询的组合?

我认为应该可以将这两个查询结合起来:

//Parent[@id='1']/Children/child[text()[matches(.,"^child1","i")]]/(text()|xs:string(../../@name))

但这导致了一个我不明白的错误:

stdin:26: query failed, Error: Sequence does not match type node()* - found item of type {http://www.w3.org/2001/XMLSchema}string [err:XPTY0004]

我已经尝试了不同的方法来组合查询,但它们都不起作用。我在Berkeley DB XML中使用dbxml-shell进行测试。

3 个答案:

答案 0 :(得分:2)

要在XPath 1.0中选择多个节点,可以使用union运算符|

//Parent[@id='1']/@name | //Parent[@id='1']/Children/child[@name='Child_1']/text()

XPath 2.0(Berkeley DB XML支持)允许:

for $child in //Parent[@id='1']/Children/child[matches(.,"^child1","i")]
return ($child/text(), $child/../../string(@name))

两者都会为输入样本选择一个属性节点和一个文本节点。

规格:XPath 2.0, section 3.7: For Expressions

答案 1 :(得分:1)

虽然@Tomalak发布了正确答案,但这是如何在dbxml-shell中运行的:

dbxml> prepare "for $child in collection('test.dbxml')//Parent[@id='1']/Children/child[matches(.,'^child1','i')] return ($child/text(), $child/../../string(@name))"
Prepared expression 'for $child in collection('test.dbxml')//Parent[@id='1']/Children/child[matches(.,'^child1','i')] return ($child/text(), $child/../../string(@name))'

dbxml> query
2 objects returned for eager expression 'for $child in collection('test.dbxml')//Parent[@id='1']/Children/child[matches(.,'^child1','i')] return ($child/text(), $child/../../string(@name))'

dbxml> print
child1_Parent_1
Parent_1

答案 2 :(得分:0)

我不知道我是否理解正确,但以下concat() - 表达式会使用string()concat(string(//Parent[@id=1]/@name) ,'&#13;&#10;',string(//Parent[@id=1]/Children/child[@name='Child_1']/text())) 来读取然后找到您要查找的两个值:< / p>

'&#13;&#10;'

在中间你会找到{{1}},它应该插入一个换行符,但这取决于你的实际需要......

测试了此on this online tester