3

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

user5326900
  • 31
  • 1
  • 2
  • 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 Sep 11 '15 at 21:07
  • 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 Sep 12 '15 at 08:40
  • Did either answer below help? Please mark one as the answer so that this question no longer shows up as "unanswered." – Joe Wicentowski Sep 04 '18 at 22:56

2 Answers2

0

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.

Abel
  • 56,041
  • 24
  • 146
  • 247
0

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>
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
  • Thank you; I was under the misunderstanding that /schedule[event/@date] would select 'only', not 'any'. I wanted to capture the surrounding 'schedules/schedule' parent nodes in the output, hence the reason I initially decided to select on /schedule[event/@date] rather than /schedule/event[@date]. I appreciate that you provided a way for me to retain the parental nodes. – user5326900 Sep 14 '15 at 12:30
  • 1
    You might also consider selecting the relevant `schedules`, and then transforming the information with XSLT. It may be more simple/easy to use a modified identity transform to prune the unwanted content with a couple of empty templates: https://en.wikipedia.org/wiki/Identity_transform – Mads Hansen Sep 14 '15 at 13:36