3
votes

I'm using exist-db to parse XML documents. I am writing a xquery script to process the documents.

My XML input looks something like this

<data>   
<schedules>
<schedule>
<event date="2015-08-28"/>
<event date="2015-08-29"/>
</schedule>
</schedules>
</data>

I want to use xquery/xpath to select all events where event/@date = "2015-08-28".

I tried this

let $rawDoc := collection("/db/test")/data/schedules/schedule[event/@date = "2015-08-28"]

but I get back this

<data>   
<schedules>
<schedule>
<event date="2015-08-28"/>
<event date="2015-08-29"/>
</schedule>
</schedules>
</data>

when I want this

<data>   
<schedules>
<schedule>
<event date="2015-08-28"/>
</schedule>
</schedules>
</data>

it seems like the presence of the "-" in either the date attribute value or my query string is not being treated as an explicit dash. It isn't clear to me how to escape the "-"? I tried "-" and that didn't work (no results returned).

Any ideas?

Thanks, Ty

2
If you select for /data/schedules/schedule[...] you're going to get the entire contents of that element, which will include any descendant event elements. Maybe instead select on event elements? Or why do you need the schedule element? - thrig
Your theory that it has something to do with the hyphens is about as wild as a conjecture that it depends on the phase of the moon. - Michael Kay
Did either answer below help? Please mark one as the answer so that this question no longer shows up as "unanswered." - Joe Wicentowski

2 Answers

0
votes

I want to use xquery/xpath to select all events where event/@date = "2015-08-28".

You use:

let $rawDoc := collection("/db/test")/data/schedules/schedule[event/@date = "2015-08-28"]

Which means, give me any schedule element that has at least one child event with that date.

Just change that to:

let $rawDoc := collection("/db/test")/data/schedules/schedule/event[@date = "2015-08-28"]

Which will give you all the event elements with that date.

0
votes

If you want to return the schedule elements and exclude all of it's event element children that do not have the desired date, your could do something like this:

let $rawDoc := collection("/db/test")/data/schedules/schedule

for $schedule in $rawDoc
return element { node-name($schedule) } {
    $schedule/@*,
    $schedule/node()[self::event[@date='2015-08-28'] | 
                                 self::text() | 
                                 self::processing-instruction() | 
                                 self::comment()]
}

Although, it might be easier to just select the desired event elements and return them inside of a schedule element:

let $rawDoc := collection("/db/test")/data/schedules/schedule/event[@date = "2015-08-28"]

for $event in $rawDoc
return <schedule>{$event}</schedule>