one more xquery

I have a document like this

<level1>
<p>some text</p>
<li>some list</li>
<level2>some nodes</level2>
</level1>

  



How can I make a xquery so that I get all nodes in level1 except for level2 node and all in it
hope some one can help me here

Hi DBB,

as your question suggests the first idea is to use the ‘except’ operator as in the following query :

let $input := doc(‘level.xml’)
return
$input//level1//node()
except
$input//level1//level2/descendant-or-self::node()

This is however not possible in Tamino since it does not yet support ‘except’. Presuming that the ‘level2’ elements reside directly below the ‘level1’ ones as in your example the following works :

for $x in input()//level1/node()[local-name() != ‘level2’]
return $x/descendant-or-self::node()

Regards,
Juliane.

I kinda get what you mean and I look forwared to the new tamino whit more of the xquery functions

But whit this query I dont get it to work so can you maby point out where I am going wrong in this

[code]

declare namespace tf = ‘http://namespaces.softwareag.com/tamino/TaminoFunction
declare namespace ft = ‘http://www.w3.org/2002/04/xquery-operators-text
declare namespace xs = ‘http://www.w3.org/2001/XMLSchema

for $bib in input()/dtbook[tf:getInoId(.)=46]
let $x:=$bib//h1
let $z :=
for $y in $x
where ft:text-contains($y, '12. L
AllTags.xml (10.4 KB)

Hi DBB,

just replace local-name()
by local-name(.) and it will work
(empty result because your sample document does not include a h1 with
where ft:text-contains($y, '12. L

A couple of comments.

Firstly, Juliane answered your question very literally. You said you wanted all the nodes “in” level1 except for level2 and its descendants, and that’s what her query gives you. But it gives you a copy of each of these nodes separately, each one containing a copy of the ones underneath it. I suspect what you really wanted was a copy of the subtree rooted at level1, with the subtree rooted at level2 removed. In the completely general case the only way to achieve this is using a recursive function, though if you know something about your schema it is probably easier. For example, it might be


{ doc(‘level.xml’)//level1/*[local-name(.) != ‘level2’] }


This is essentially what you have done, and your query works for me, after changing a few Tamino-specific things and trying it in Saxon.

I would personally have written it a bit differently, for example instead of

let $x:=$bib//h1
let $z :=
for $y in $x
where contains($y, ‘ABCDE’)
return $y


I would have written:

let $z := $bib//h1[contains(., ‘ABCDE’)]

but that’s a matter of personal style.

Michael Kay

Thanks for the tip Michael I might rewrite the query now.
I also have a problem whit this query that makes a xml document that is to be used whit C# I want to remove the chapter nodes in the answere but when I do that I cant get the query to work Here is the query.

declare namespace tf = 'http://namespaces.softwareag.com/tamino/TaminoFunction'
	declare namespace ft = 'http://www.w3.org/2002/04/xquery-operators-text' 
	declare namespace xs = 'http://www.w3.org/2001/XMLSchema'
	<TREENODES>{
		for $bib in input()/dtbook
		let $x:=$bib/descendant::p
		let $z := 
		for $y in $x 
		where ft:text-contains($y, 'java') 
	return  $y 
		where $z 
		return <TreeNode> { attribute
				inoId{tf:getInoId($bib)}, 
				attribute docname{tf:getDocname(root($bib))}, 
				attribute matchCount{count($z)}, 
				attribute Text{$bib/head/title},  
					<chapter>{ 
					for $f in $z/parent::*[self::level1]
						let $j:=$f/descendant::p
						let $h :=
						for $g in $j
						where ft:text-contains($g, 'java')
						return $g 
						where $h
						return 	<TreeNode>{
								
								attribute matchCountP{count($h)},
								attribute Ancestor{local-name($f/parent::node())},
								attribute Level{local-name($f)},
								attribute Text{$f/h1/text()},
								<chapter2>{
							
								for $a in $h/parent::*[self::level2]
										let $u :=$a/descendant::p
										let $i :=
										for $l in $u
										where ft:text-contains($l, 'java')
										return $l 
										where $i
										return 	<TreeNode>{
												
												attribute matchCountP{count($i)},
												attribute Ancestor{local-name($a/parent::node())},
												attribute Level{local-name($a)},
												attribute Text{$a/h2/text()},												
								<chapter3>{							
								for $q in $i/parent::*[self::level3]
										let $t :=$q/descendant::p
										let $e :=
										for $c in $t
										where ft:text-contains($c, 'java')
										return $c 
										where $e
										return 	<TreeNode>
												{
												attribute matchCountP{count($e)},
												attribute Ancestor{local-name($q/parent::node())},
												attribute Level{local-name($q)},
												attribute Text{$q/h3/text()}
								}</TreeNode>
								}</chapter3>								
								}</TreeNode>
								}</chapter2>							
								}</TreeNode>							
					}</chapter>				
			}</TreeNode> 
		sort by( xs:int(@matchCount) descending)
		}</TREENODES>  


And also I am kinda thinking that this query could be done better but This ia what I have come up whit by now Do you got any suqestion to how I could optimaze this query.
Thanks for any help.

I got it to work whit out the node now But still is there some way to make this query faster