XQuery/Parsing Query Strings

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Motivation[edit | edit source]

Normal 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[edit | edit source]

 module namespace common="http://www.example.org/xmlns/common";

Platform[edit | edit source]

  • eXist

Parsing Query Strings[edit | edit source]

common:get-parameters[edit | edit source]

This 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[edit | edit source]

This 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[edit | edit source]

This 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[edit | edit source]

Assumes 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