Thursday, May 5, 2011

how to create a xml document on the fly with xquery?

Hi all,

I what to use XQuery to convert string like "aaa=1&bbb=2" into xml

<request>
  <aaa>1</aaa>
  <bbb>2</bbb>
</request>

I have tried the following code, but failed!

xquery version "1.0" encoding "GBK";
(:: pragma  type="xs:anyType" ::)

declare namespace xf = "http://tempuri.org/BNetAP/Xquery/query2xml/";

declare function xf:query2xml($queryStr as xs:string)
    as element(*) {
    <query-params>
    {
     for $c in
      fn:tokenize($queryStr, "&amp;")
     let $myname as xs:string := "{fn:substring-before($c,"=")}"
     return 
      element
       {fn:QName("", $myname)}
       {"{fn:substring-after($c,"=")}"}
    }
    </query-params>
};

The error message is:

line 15, column 6:  "{http://www.w3.org/2004/07/xpath-functions}QName": unknown function (or number of arguments (2) is wrong)  BNetAP/Xquery query2xml.xq line 15 1241431186406 397

I have no idea why "QName" is a "unknow function"?!

From stackoverflow
  • You should be using the constructor xs:QName, not fn:QName.

    The body of your constructed element also looks a bit suspicious:

    "{fn:substring-after($c,"=")}"
    

    is in fact a comparison between the string "{fn:substring-after($c," and the string ")}" so the content of the element would just be the text "false".

    Similarly you $myname variable is actually being set to false and so will raise a type check error at run time.

    Your function should probably be as follows:

    declare function xf:query2xml($queryStr as xs:string)
        as element(*) {
      <query-params>
      {
        for $c in fn:tokenize($queryStr, "&amp;")
        let $myname := fn:substring-before($c,"=")
        return 
          element
            {xs:QName("", $myname)}
            {fn:substring-after($c,"=")}
      }
      </query-params>
    };
    

    A computed element constructor can also accept just a string for its name, so your return expression could be simplified to just

    return element {$myname} {fn:substring-after($c,"=")}
    

0 comments:

Post a Comment