Получить предков какого-либо узла с помощью рекурсии XQuery - PullRequest
0 голосов
/ 22 августа 2010

У меня есть XML, например:

<types>
  <type type="A">
    <type type="A.A"/>
    <type type="A.B">
      <type type="A.B.A"/>
    </type>
    <type type="A.C"/>
  </type>
</types>

Теперь у меня есть строка ввода, например: "ABA".Я хочу получить все предки и собственный узел, который имеет эту строку, как значение атрибута «тип».Это означает:

<types>
  <type type="A"/>
  <type type="A.B"/>
  <type type="A.B.A"/>
</types>

(Естественно, имена типов здесь только примеры и не так просто, поэтому я не могу использовать функцию подстроки)
У меня есть две схемы XML: TypesTree.xsd и Ancestros.xsd.
В обоих есть элементы "type" и "types".

Так что, возможно, я могу использовать XPath с осью предков, где $ types содержит дерево типов:

let $seq := $types//type[@type=$typeName]/ancestor::*
$seq := ($seq, $types//type[@type=$typeName])

Я новичок в XQuery, и я не уверен, что этобудет работать, но это не имеет значения, дело в том, что у меня не реализована ось "предков" в моем процессоре XQuery (!), и мне нужно явно написать код для этого процессора.

Так что я думаю написать какую-нибудь рекурсивную функцию.Пусть "tre:" является префиксом TypesTree.xsd и "anc:" Ancestors.xsd.Функция получит элемент tre: type и вернет последовательность элементов anc: type.

declare function BuildAncestors($type as element(tre:type), $typeName as xs:string) as element(anc:type)*
{
  for $currentType in $type/tre:type (: for each nested type node :)
  return
  if ($currentType[@type=$typeName]) (: if current type node's attribute's values is what we search for :)
  then ($currentType) (: return this node :)
  else (: if this node's attribute's value isn't what we search, check it's children :)
    let $retSeq := BuildAncestors($currentType, $typeName) (: get sequence of all ancestor's of this type till this node or null if $currentType has not searched node in it's descendants :)
    if ($retSeq) (: if not null returned :)
    then ($currentType, $retSeq) (: return new sequence built from this node and returned sequence :)
    else () (: return null :)
}

Итак, ясно, что это не работа.Я даже не знаю, как мне вернуть последовательность, добавить последовательности, вернуть ноль, проверить, возвращается ли ноль ...

Кто-нибудь знает, как я могу получить всех предков?

Спасибо за внимание.

Ответы [ 2 ]

1 голос
/ 22 августа 2010

Использование :

//type[@type=$pType]//ancestor-or-self::type[starts-with($pType, @type)]

Если ваш процессор XQuery соответствует спецификации W3C, он, вероятно, реализует ancestor:: и ancestor-or-self:: осей.

Ошибка, которую вы получите, скорее всего, связана с опечаткой - имя оси ancestor, а не ancestors.

0 голосов
/ 22 августа 2010

Правильное имя оси - ancestor, а не ancestors.Также было бы проще использовать ось ancestor-or-self.

...