0
votes

I'm just getting started on learning XPath and the subset XQuery in order to query and parse an XML document(s) set much like a SQL database.

My first question is how do you -easily- return more than one related element for a specific query?

For instance, here's a sample XPath query of mine:

doc(XXXfakeURL.xml?user=username;pwd=mypassword)//schedule[employee-id=1425 and activity-id=2058]/time-start

This opens a certain XML document, finds the schedule element with a certain employee and activity, and returns the element "time-start."

However, what if I want to return MULTIPLE child elements from that node? Like, not only time-start, but also time-end, work group, other stuff, blah blah, etc. I don't want to type that whole path again.

For now, I've discovered I could do [verbose query]/node()[position()=4 or position=(7)].

This, through some probably non-ideal code, returns the nodes at multiple positions, which I have to look up, instead of simply returning multiple elements.

My other question is if I can store URL names in variables in XML.

Like say I frequently reference doc("locolhost:8888/schedule/1032/employees/3230/planninggroup/2014.xml?user=johnsmith&amppwd=mysecretpassword")

Is there a way to store that document in a variable? Or at least make it shorter?

I think this application I'm querying (3rd party application) may have literally hundreds of XML documents that comprise the "data" so I may not even be able to re-use one document URL. My code just seems super cluttered because I have to call a HUGE URL document for an employee list, another giant URL document for schedules, ANOTHER to determine what office everyone works at ---- why this wasn't put in just one document, I'm not sure.

2

2 Answers

0
votes

I'm not sure I completely understand what you're trying to do, but one way to make things simpler is to write small reusable functions:

declare function local:planning-group(
  $user as xs:string,
  $pwd as xs:string
) as document-node()
{
  doc(concat(
    "localhost:8888/schedule/1032/employees/3230/planninggroup/2014.xml?",
    "user=", $user, "&amppwd=", $pwd))
};

local:planning-group("johnsmith", "mysecretpassword")

You could compose and overload functions in ways that allow you to account for all the variables in the URLs, and it would be fairly tidy. For example, you could store some values as global variables if you want easy to configure defaults, and then this 2-param function could default to those (localhost:8888, 1032, 3230, etc.) - then other 2-, 3-, etc. param functions could selectively override them.

To return multiple nodes with XPath, you can use parens:

doc(...)//schedule[...]/(time-start | time-end | work-group)
0
votes

what if I want to return MULTIPLE child elements from that node? Like, not only time-start, but also time-end, work group, other stuff,

replace EXPR/time-start by

EXPR/(time-start, time-end, work-group, other-stuff)

Like say I frequently reference doc("locolhost:8888/schedule/1032/employees/3230/planninggroup/2014.xml?user=johnsmith&amppwd=mysecretpassword")

Is there a way to store that document in a variable?

In XQuery, and in XPath 3.0, you can write

let $doc := doc("long uri here")
return $doc/a/b/c/d

In XPath 2.0 you can "abuse" the for expression for this purpose:

for $doc in doc("long uri here")
return $doc/a/b/c/d