XQuery to Filter Elements

Z

Zach Brown

I'm totally stuck on this... I've got an xml fragment that looks like:

<profile id="1">
<meta>
<groupID>100</groupID>
</meta>
<data>
<field id="businessStage" date="8/15/2007">Shipping Product</field>
<field id="businessStage" date="8/14/2007">Development</field>
<field id="businessStage" date="8/13/2007">Research</field>
<field id="ticker" date="8/15/2007">MyTICK</field>
<field id="ticker" date="5/15/2005>TICK</field
</data>
</profile>

And, i was hoping that i could write an xquery expression that would select
basically the whole document minus any fields whose date didn't match
"8/15/2007" resulting in this:

<profile id="1">
<meta>
<groupID>100</groupID>
</meta>
<data>
<field id="businessStage" date="8/15/2007">Shipping Product</field>
<field id="ticker" date="8/15/2007">MyTICK</field>
</data>
</profile>

Basically where I'm at now i either get the whole document returned or just
the fields. Clearly I'm just starting out with experimenting with XQuery
but i'm totally stuck trying to do what I thought was going to be an easy
task.

Any help or thoughts on this would be super appreciated.

Regards,
Zach
 
P

Pavel Lepin

Zach Brown said:
<profile id="1">
<meta>
<groupID>100</groupID>
</meta>
<data>
<field id="businessStage" date="8/15/2007">Shipping
Product</field> <field id="businessStage"
date="8/14/2007">Development</field> <field
id="businessStage" date="8/13/2007">Research</field>
<field id="ticker" date="8/15/2007">MyTICK</field>
<field id="ticker" date="5/15/2005>TICK</field
</data>
</profile>

And, i was hoping that i could write an xquery expression
that would select basically the whole document minus any
fields whose date didn't match "8/15/2007"

So what's the problem? Process all the nodes recursively,
omitting the ones that fit your criteria:

declare function local:filter($node as node())
{
if (local:check($node))
then
if ($node[self::element()])
then
element { name($node) } { local:recurse($node) }
else
if ($node[self::document-node()])
then document { local:recurse($node) }
else $node
else ()
} ;

declare function local:recurse($node as node())
{
for $child in ($node/@*|$node/node())
return local:filter($child)
} ;

declare function local:check($node as node())
{
if ($node[self::field and @date!='8/15/2007'])
then false() else true()
} ;

let $a := fn:doc('filter.xml')
return local:filter($a)
 
Z

Zach Brown

Wow. I've only been working around with xquery for the last week. For some
reason, all the stuff that i've managed to find not once mentioned user
defined functions. Powerful.

Thanks for this Pavel. I appreciate it. Sometimes the biggest challenge
when looking for an answer in a new technology is understanding what to
ask... Thanks again.

Regards,
Zach

Pavel Lepin said:
Zach Brown said:
<profile id="1">
<meta>
<groupID>100</groupID>
</meta>
<data>
<field id="businessStage" date="8/15/2007">Shipping
Product</field> <field id="businessStage"
date="8/14/2007">Development</field> <field
id="businessStage" date="8/13/2007">Research</field>
<field id="ticker" date="8/15/2007">MyTICK</field>
<field id="ticker" date="5/15/2005>TICK</field
</data>
</profile>

And, i was hoping that i could write an xquery expression
that would select basically the whole document minus any
fields whose date didn't match "8/15/2007"

So what's the problem? Process all the nodes recursively,
omitting the ones that fit your criteria:

declare function local:filter($node as node())
{
if (local:check($node))
then
if ($node[self::element()])
then
element { name($node) } { local:recurse($node) }
else
if ($node[self::document-node()])
then document { local:recurse($node) }
else $node
else ()
} ;

declare function local:recurse($node as node())
{
for $child in ($node/@*|$node/node())
return local:filter($child)
} ;

declare function local:check($node as node())
{
if ($node[self::field and @date!='8/15/2007'])
then false() else true()
} ;

let $a := fn:doc('filter.xml')
return local:filter($a)
 
P

Pavel Lepin

Please don't top post.

Zach Brown said:
Pavel Lepin said:
So what's the problem? Process all the nodes recursively,
omitting the ones that fit your criteria:
[snip]

I've only been working around with xquery for the last
week.

It's the second XQuery I've ever written, so 'only last
week' sounds like an awful lot of time to do some reading
to me.
For some reason, all the stuff that i've managed to find
not once mentioned user defined functions. Powerful.

You've been reading the wrong stuff then. The XQuery spec is
reasonably good as a reference, and definitely worth
skimming over. If that's too hard for you, I'm fairly
certain IBM's developerWorks has some good introductory
reading in its XQuery library:

http://www.ibm.com/developerworks/xml
 
Z

Zach Brown

Please don't top post.

I top posted because my comment was no longer relevant to the initial
question and was just a reflection. Don't make people scroll all the way to
the bottom of a post if the data in the post in no longer relevant to the
current threads voice. Just like the body was removed to clean up the
document because it's no longer relevant to "this" discussion.

Regards,
Zach Brown
 
Z

Zach Brown

Pavel Lepin said:
Zach Brown said:
<profile id="1">
<meta>
<groupID>100</groupID>
</meta>
<data>
<field id="businessStage" date="8/15/2007">Shipping
Product</field> <field id="businessStage"
date="8/14/2007">Development</field> <field
id="businessStage" date="8/13/2007">Research</field>
<field id="ticker" date="8/15/2007">MyTICK</field>
<field id="ticker" date="5/15/2005>TICK</field
</data>
</profile>

And, i was hoping that i could write an xquery expression
that would select basically the whole document minus any
fields whose date didn't match "8/15/2007"

So what's the problem? Process all the nodes recursively,
omitting the ones that fit your criteria:

declare function local:filter($node as node())
{
if (local:check($node))
then
if ($node[self::element()])
then
element { name($node) } { local:recurse($node) }
else
if ($node[self::document-node()])
then document { local:recurse($node) }
else $node
else ()
} ;

declare function local:recurse($node as node())
{
for $child in ($node/@*|$node/node())
return local:filter($child)
} ;

declare function local:check($node as node())
{
if ($node[self::field and @date!='8/15/2007'])
then false() else true()
} ;

let $a := fn:doc('filter.xml')
return local:filter($a)

Got this implemented and this worked great BTW. Thanks again.

Best,
Zach
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top