[XQZone General] RE: passing sequences to xdmp:eval( )

Howard Katz howardk at fatdog.com
Wed Dec 7 11:31:37 PST 2005


It turns out there's another downside to my workaround. Given the example
below, invoking

     eval-node-test( $nodes, "starts-with( ., 'ca' )" )

returns all the nodes that pass the "starts-with() test". However, I also
want to be able to see which nodes *don't* pass the test and had expected to
be able to use the "except" operator to extract the difference, ie the "bad"
ones. In other words, I had expected this to work:

    let $nodes:= ( <a>cat</a>, <b>dog</b>, <c>catalog</c> )

    let $good-nodes := eval-node-test( $nodes, "starts-with( ., 'ca' )" )
    return
    <both>
        <good-nodes>{ $good-nodes }</good-nodes>
        <bad-nodes>{ $nodes except $good-nodes }</bad-nodes>
    </both>

This fails however, with <bad-nodes> always turning out to be equal to the
original node sequence, not some subset of it. What is happening apparently
is that the $good-nodes being returned no longer have their original
identity, and the difference of the two simply returns the original node
sequence, because there's nothing in common any longer between $nodes and
$good-nodes.

So it looks like I'm doubly in need of another way of doing this. I could
stick unique @id identifiers on all nodes and generate the difference of the
two sequences using those, but that doesn't seem anywhere near as attractive
as using "except".

Any thoughts?
Howard

 > -----Original Message-----
 > From: Howard Katz [mailto:howardk at fatdog.com] 
 > Sent: December 7, 2005 9:18 AM
 > To: 'General XQZone Discussion'
 > Subject: passing sequences to xdmp:eval( )
 > 
 > I have a series of boolean-returning query tests that are 
 > stored as strings, and I need to be able to apply these 
 > tests against a variety of node sequences, getting back the 
 > nodes that passed. Since the queries are strings, I'm using 
 > xdmp:eval(). This works ok, but I have to do a slight 
 > workaround to satisfy eval(), and I'm concerned about 
 > performance  issues when I scale up to run the tests against 
 > very large sequences, say on the order of hundreds of 
 > thousands of nodes.
 > 
 > Assume that one of the stored tests I want to run is 
 > 'starts-with( ., "ca" )'. If I was directly applying this 
 > test against the sequence, "(<a>cat</a>, <b>dog</b>, 
 > <c>catalog</c>)" (ie, not eval'ing it), I could say:
 > 
 >     let $seq := ( <a>cat</a>, <b>dog</b>, <c>catalog</c> )
 >     return
 >     $seq[ starts-with( ., "ca" ) ]
 > 
 > and I'd get back the node sequence, ( <a>cat</a>, 
 > <c>catalog</c> ). So far so good.
 > 
 > If the same query is now stored as a string and I'm using 
 > eval(), I'd similarly like to be able to say:
 > 
 > 
 >    define function eval-node-test( $nodes as element()+, 
 > $test as xs:string ) as element()*
 >    {
 >         let $query := concat(  "define variable $seq as 
 > element() external ", "$seq[ ", $test, " ]" )
 >         return
 >         xdmp:eval( $query, ( xs:QName("seq"), $nodes ) )
 >    }
 > 
 >    let $nodes:= ( <a>cat</a>, <b>dog</b>, <c>catalog</c> )
 >    return
 > 
 >    eval-node-test( $nodes, "starts-with( ., 'ca' )" )
 > 
 > 
 > This won't work however because the $nodes argument passed 
 > in '( xs:QName("seq"), $nodes )' can't be a sequence, only a 
 > singleton. This means that in order to use eval(),
 > 
 > (1) I have to wrap the $nodes sequence in a temporary 
 > <temp-root/> wrapper, and
 > (2) construct the last part of the query inside concat() as 
 > "$seq/* [ ", $test, ... ", rather than "$seq [ ", $test ... ".
 > 
 > In other words,
 > 
 > 1) To satisfy eval(), I have to hoist all my nodes into a 
 > temporarily constructed super-element, and
 > 2) dereference every one of them again inside my query
 > 
 > Since I potentially need to be able to run these tests 
 > against hundreds of thousands of nodes, I'm concerned about 
 > performance. Is that concern justified? And if is, is there 
 > a more efficient way of doing this? 
 > 
 > Howard 
 > 




More information about the General mailing list