XQuery/Parsing Query Strings
Motivation
editNormal http query strings use the ampersand (&) character in order to differentiate between different terms in a query string. However, because ampersands also are used as the start of entities within HTML and XML, this can make it difficult encoding parametric content into XML links, and it moreover makes it difficult to visually decipher query strings.
This program illustrates how to parse query strings using alternative delimiters (such as the semi-colon).
This program demonstrates some standard XQuery functions that are not part of the original XQuery specification but are required for precise web server XQuery functionality.
The functions are:
- exist request:get-method()
- exist util:unescape-uri()
- exist request:get-query-string()
- exist request:get-parameter()
- exist request:get-parameter-names()
Namespace
editmodule namespace common="http://www.example.org/xmlns/common";
Platform
edit- eXist
Parsing Query Strings
editcommon:get-parameters
editThis base function retrieves the query string from the URI, parses the string using the given delimiter and creates an XML structure of the form
<params>
<param name="param1" value="paramval1"/>
<param name="param2" value="paramval2"/>
</params>
declare function common:get-parameters($delimiter as xs:string) as node() {
let $params := if (request:get-method() = "GET") then
let $query-string := util:unescape-uri(request:get-query-string(),"UTF-8")
let $parsed-query := tokenize($query-string,$delimiter)
return <params>
{for $parsed-query-term in $parsed-query
let $parse-query-name := substring-before($parsed-query-term,"=")
let $parse-query-value := substring-after($parsed-query-term,"=")
return <param name="{$parse-query-name}" value="{$parse-query-value}"/>
}
</params>
else
<params>
{for $name in request:get-parameter-names()
let $parse-query-name := $name
let $parse-query-value := request:get-parameter($name,"")
return <param name="{$parse-query-name}" value="{$parse-query-value}"/>
}
</params>
return $params
};
common:get-parameter
editThis function retrieves a sequence of string values corresponding to the values for a given parameter key given in the query string. Note that while typically there will be only one string in the sequence, if you have a query string of the form ?a=val1;b=val2;a=val3 then get-parameter("a","",";") will return ("val1","val3")
declare function common:get-parameter($param-name as xs:string,$default-value as xs:string,$delimiter as xs:string) as xs:string* {
let $params := common:get-parameters($delimiter)
let $param-nodes := $params/param[@name=$param-name]
let $param-values :=
for $param-node in $param-nodes
return
if ($param-node/@value)
then string($param-node/@value)
else $default-value
return $param-values
};
common:get-parameter-names
editThis function retrieves the name of each query string key (once and only once per key).
declare function common:get-parameter-names($delimiter as xs:string) as xs:string* {
let $params := common:get-parameters($delimiter)
for $param-name in distinct-values($params/param/@name)
return $param-name
};
Example Program
editAssumes query string of
http://www.example.org/?a=5;b=test;a=8;c=new+message
let $msg := common:get-parameter("c","",";") return $msg
returns
new message
{ for $key in common:get-parameter-names(";") return <seq>{$key}:{common:get-parameter($key,"",";")}</seq> }
returns
<seq>a:5 8</seq> <seq>b:test</seq> <seq>c:new message</seq>
let $seq1 := common:get-parameter("a",0,";") return sum(for $n in $seq1 return number($n))
returns
13