XQuery如何过滤节点&它的子节点

时间:2014-07-29 13:06:45

标签: xml xquery

如何从“for”

中循环的节点中仅选择前2个子节点

e.g。我有这个xml,我需要选择具有合格'是'的人,我只想要他的前2个关联。我的输出应该是与过滤节点相同的XML结构。我知道这是XSLT的简单任务,但只是想知道XQuery是否有一个简单的方法。

    <?xml version="1.0" encoding="UTF-8"?>
<Persons>
    <Person>
        <Name>Sam</Name>
        <DOB>12-2-1981</DOB>
        <Qualified>Yes</Qualified>
        <Assosiation>
            <Code>1</Code>
            <Descreption>Assosiatoin1</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>2</Code>
            <Descreption>Assosiatoin2</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>3</Code>
            <Descreption>Assosiatoin3</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>4</Code>
            <Descreption>Assosiatoin4</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>5</Code>
            <Descreption>Assosiatoin5</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>6</Code>
            <Descreption>Assosiatoin6</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>7</Code>
            <Descreption>Assosiatoin7</Descreption>
        </Assosiation>
        <DynamicElement>Unkown</DynamicElement>
    </Person>
    <Person>
        <Name>James</Name>
        <DOB>12-2-1975</DOB>
        <Qualified>No</Qualified>
        <Assosiation>
            <Code>1</Code>
            <Descreption>Assosiatoin1</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>2</Code>
            <Descreption>Assosiatoin2</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>3</Code>
            <Descreption>Assosiatoin3</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>4</Code>
            <Descreption>Assosiatoin7</Descreption>
        </Assosiation>
        <DynamicElement>Unkown</DynamicElement>
    </Person>
    <Person>
        <Name>Jon</Name>
        <DOB>12-2-1983</DOB>
        <Qualified>Yes</Qualified>
        <Assosiation>
            <Code>1</Code>
            <Descreption>Assosiatoin1</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>2</Code>
            <Descreption>Assosiatoin2</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>3</Code>
            <Descreption>Assosiatoin3</Descreption>
        </Assosiation>
        <Assosiation>
            <Code>4</Code>
            <Descreption>Assosiatoin7</Descreption>
        </Assosiation>
        <DynamicElement>Unkown</DynamicElement>
    </Person>
</Persons>

2 个答案:

答案 0 :(得分:1)

非XQuery更新解决方案:

element Persons {
  for $person in $xml/Persons/Person
  where $person/Qualified = 'Yes'
  return element Person {
    $person/Name,
    $person/DOB,
    $person/Qualified,
    $person/Assosiation[position() = (1,2)],
    $person/DynamicElement
  }
}

如果你想对其他元素的名称不那么具体:

element Persons {
  for $person in $xml/Persons/Person
  where $person/Qualified = 'Yes'
  return element Person {
    for $element in $person/*
    return
      $element[
        local-name($element) != 'Assosiation' or
        count($element/preceding-sibling::Assosiation) < 2
      ]
  }
}

答案 1 :(得分:0)

自Oracle 11.2.0.3.0起,Oracle还支持XQuery Update,这是在这种情况下使用的正确工具。

XQuery本身不会操纵XML数据,因此您需要重新构建完整的树,并且只需省略不需要的节点。使用XQuery Update,您可以修改XML,从而仅删除不需要的节点:

copy $c := .
modify
  for $p in $c//Person[Qualified = "Yes"][position() > 2]
  return delete node $p
return $c

但是,在您的示例数据中,只有两个<Person />元素的Qualified设置为Yes,因此不会删除任何内容。如果你想说你想要两个第一个元素,但只有那些Qualified设置为Yes的元素,你就必须交换谓词,即$c//Person[position() > 2][Qualified = "Yes"]