Re: how to prune subtrees in an XQuery result

Is this a better XQuery ..

<Results> {
   for $A in doc("data.xml")/ASet/A
   let $matches := $A[B = ("red","yellow")][C =
("chair","table")]/((B[.=("red","yellow")]
                     | C[.=("chair","table")]))   
   return
     if ($A/$matches)
       then
        <A> 
         {$A/@*}
         {$matches}
        </A>     
       else
         $A/$matches
}</Results>

I have one question.. Can we write if without else in
XQuery?

The XQuery grammer says:
IfExpr    ::=    "if" "(" Expr ")" "then" ExprSingle
"else" ExprSingle 

This probably implies that else is mandatory in if.
That is why I had to write a redundant..
else
  $A/$matches

Saxon is not allowing if without else..

If else is mandatory, then is'nt it a inconvenience..?

Regards,
Mukul

--- Sergio Andreozzi <sergio.andreozzi@cnaf.infn.it>
wrote:

> Hi Michael,
> 
> Michael Kay wrote:
> > Here's a solution that doesn't involve doing the
> comparisons twice.
> > 
> > <Results> {
> >    for $A in doc("data.xml")/ASet/A
> >    let $matches := $A/(B[.=("red","yellow")]
> >                      |C[.=("chair","table")])
> >    where ($matches)
> >    return <A>{$matches}</A>
> > }</Results>
> 
> I like your solution because does not require the
> expression of the 
> comparisons twice. But, it does not provide the
> exact solution I was 
> looking for.
> 
> This is what I get:
> 
> <Results>
> 	<A>
> 		<B>red</B>
> 		<B>yellow</B>
> 		<C>chair</C>
> 		<C>table</C>
> 	</A>
> 	<A>
> 		<B>red</B>
> 		<C>chair</C>
> 	</A>
> 	<A>
> 		<C>chair</C>
> 		<C>table</C>
> 	</A>
> </Results>
> 
> first, the attribute name in A is missing. Then, the
> third A element 
> does not match my predicate as I desire that only if
> there is at least 
> one "B" element and one "C" element matching the
> conditions, then the 
> "A" should be returned.
> 
> The solution from Mukul provides the expected
> result, but it seems that 
> you have to do first the filtering and then the
> pruning in two different 
> steps.
> 
> I'm interested in the pruning for the following use
> case: a user wants 
> to extracts the set of A elements that hold a
> certain set of 
> characteristics. For a certain characteristic, if
> there are many choices 
> (e.g., B has siblings with different values), then
> only the ones 
> matching the user request should be returned.
> 
> If there is no more compact solution than the
> Mukul's one, then I could 
> think about something like:
> 
> <Results>
> {
> 	for $A in doc("data.xml")/ASet/A
> 	where ($A/B = "red" or $A/B = "yellow")
>                 and ($A/C = "chair" or $A/C =
> "table")
> 	return pruned {$A}
> }
> </Results>
> 
> The "pruned" terminal adds the expected semantics to
> the result. This 
> could be rewritten in a standard XQuery query before
> to be run and the 
> problem moves to which is the best way to rewrite
> it.
> 
> 
> - Sergio
> 
> > 
> > Michael Kay
> > http://www.saxonica.com/
> > 
> > 
> >>Hi Sergio,
> >>  Probably this XQuery is required..
> >>
> >><Results>
> >>{
> >>      for $A in doc("data.xml")/ASet/A
> >>      where ($A/B = "red" or $A/B = "yellow")
> >>            and ($A/C = "chair" or $A/C = "table")
>    
> >> 
> >>      return 
> >>      <A>        
> >>        {$A/@*}
> >>        {$A/B[(. = 'red') or (. = 'yellow')]}
> >>        {$A/C[(. = 'chair') or (. = 'table')]}
> >>      </A>
> >>}
> >></Results>
> >>
> >>Regards,
> >>Mukul
> >>
> >>--- Sergio Andreozzi
> <sergio.andreozzi@cnaf.infn.it>
> >>wrote:
> >>
> >>>Dear all,
> >>>
> >>>I'm wondering what is the best way to prune
> subtrees
> >>>that did not match 
> >>>the where clause of a FLOWER expression.  See the
> >>>example below for 
> >>>clarification:
> >>>
> >>>SAMPLE DATA
> >>>
> >>><ASet>
> >>>	<A name="one">
> >>>		<B>red</B>
> >>>		<B>yellow</B>
> >>>		<B>green</B>
> >>>		<C>chair</C>
> >>>		<C>table</C>
> >>>		<C>sofa</C>
> >>>	</A>
> >>>	<A name="two">
> >>>		<B>red</B>
> >>>		<B>green</B>
> >>>		<C>chair</C>
> >>>		<C>sofa</C>
> >>>	</A>
> >>>	<A name="three">
> >>>		<B>green</B>
> >>>		<C>chair</C>
> >>>		<C>table</C>
> >>>		<C>sofa</C>
> >>>	</A>
> >>></ASet>
> >>>
> >>>QUERY: for each A, list all the name of A, their
> B
> >>>elements that are 
> >>>either "red" or "yellow" and their C elements
> that
> >>>are either "chair" or 
> >>>"table"
> >>>
> >>>EXPECTED RESULT:
> >>>
> >>><Results>
> >>>	<A name="one">
> >>>		<B>red</B>
> >>>		<B>yellow</B>
> >>>		<C>chair</C>
> >>>		<C>table</C>
> >>>	</A>
> >>>	<A name="two">
> >>>		<B>red</B>
> >>>		<C>chair</C>
> >>>	</A>
> >>></Results>
> >>>
> >>>
> >>>in practice what I would like to understand is
> how
> >>>to prune all the 
> >>>subtrees that do not contain any match with
> >>>components of the WHERE 
> >>>clause in the XQuery result.
> >>>
> >>>The general pruning rule is "if an element does
> not
> >>>participate in the 
> >>>satisfaction of the WHERE clause and all its
> >>>children elements (if any) 
> >>>don't participate as well, then prune it from the
> >>>result".
> >>>
> >>>A possible starting point is the following query,
> >>>but the pruning action 
> >>>is missing.
> >>>
> >>><Results>
> >>>{
> >>>      for $A in doc("data.xml")/ASet/A
> >>>      where ($A/B = "red" or $A/B = "yellow")
> >>>            and ($A/C = "chair" or $A/C =
> "table")
> >>>      return ...
> >>>}
> >>></Results>
> >>>
> >>>
> >>>
> >>>Thanks,
> >>>
> >>>	Sergio
> >>
> >>
> >>
> >>		
> >>__________________________________ 
> >>Do you Yahoo!? 
> >>Yahoo! Small Business - Try our new resources
> site!
> >>http://smallbusiness.yahoo.com/resources/ 
> >>
> >>
> > 
> > 
> > 
> > 
> 
> 
> -- 
> Sergio Andreozzi
> INFN-CNAF,                        Tel: +39 051 609
> 2860
> Viale Berti Pichat, 6/2           Fax: +39 051 609
> 2746
> 40126 Bologna (Italy)             Web:
> http://www.cnaf.infn.it/~sergio
> 



		
__________________________________ 
Do you Yahoo!? 
Yahoo! Small Business - Try our new resources site!
http://smallbusiness.yahoo.com/resources/ 

Received on Monday, 21 March 2005 13:49:45 UTC