views:

64

answers:

2

Hello, I have XML for example:

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

Now, I have input string like: "A.B.A". I want get all ancestor and self node which has this string like value of "type" attribute. It means:

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

(Naturally the names of the types here just examples and not so simple, so I can't use substring function)
I have two XML Schemas: TypesTree.xsd and Ancestros.xsd.
In both there is elements "type" and "types".

So maybe, I can to use XPath with ancestors axis where $types holds the tree of types:

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

I'm new in XQuery, and I don't sure that this will work, but it is not matter, matter is that I have not the "ancestors" axis implemented in my XQuery processor (!) and I need to write code explicitly for this processor.

So I think to write some recursive function. Let "tre:" is prefix of TypesTree.xsd and "anc:" of Ancestors.xsd. The function will get tre:type element and will return sequence of anc:type elements.

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 :)
}

So, it is clear that it is not work. I even don't know how may I return sequence, add sequences, return null, check whether null is returned...

Any one know how I may get all ancestors?

Thank you for ahead.

A: 

The correct axis name is ancestor, not ancestors. Also, using the axis ancestor-or-self would be simpler.

svick
Sorry, my real code have ancestor:: and not ancestors::. Simply our development network has no access to inetrnet, so I may not to copy code. But I found the solution, I will post it. Thank you any way.
rodnower
A: 

Use:

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

If your XQuery processor is compliant to the W3C Specification, it probably implements the ancestor:: and the ancestor-or-self:: axes.

The error you get is most probably due to the typo -- the axis name is ancestor, not ancestors.

Dimitre Novatchev
Sorry, my real code have ancestor:: and not ancestors::. Simply our development network has no access to inetrnet, so I may not to copy code. But I found the solution, I will post it.Thank you any way.
rodnower