Re: how to prune subtrees in an XQuery result

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

Received on Monday, 21 March 2005 11:22:47 UTC