XQuery generating multiple XML documents?

by Marc Van Cappellen on December 4, 2007

in XML

A requirement we often see with DataDirect XQuery customers, is the ability to generate multiple results. Imagine a directory with XML files, each of which needs to be transformed and result in a new XML document. Wouldn’t it be great to query the complete directory and generate the corresponding results, all in a single XQuery? No need to glue multiple queries together, do external scripting, write Java or any other proprietary code. Simply a single XQuery!

The use case is not new. And not surprising, people are doing this in XSLT since a long time through the xsl:result-document instruction. Despite the library of almost 200 built-in functions in XQuery, there is not such a function in XQuery 1.0.

The good news is that DataDirect XQuery 3.1 adds out-of-the-box support to serialize query results in a file.

1
2
3
4
ddtek:serialize-to-url(
      $items as item()*,
      $url as xs:string,
      $options as xs:string)

ddtek:serialize-to-url() has three arguments, first the data to be serialized, second a URL specifying the file to be saved and the last argument tweaks the serialization process.

The following example creates a output.xml file in the c:\results directory,

1
2
3
4
let $item := <message>XQuery rocks!</message>
return
  ddtek:serialize-to-url($item,
     "file:///results/output.xml","")

As you see there is no need at all to write any Java code, this can be executed from within your favorite XQuery editor or using the DataDirect XQuery command line utility.

As a URL specifies the output location, you can for example easily upload the result to an FTP server,

1
2
3
4
let $item := <message>XQuery rocks!</message>
return
  ddtek:serialize-to-url($item,
     "ftp://uid:pwd@myftpserver/results/", "")

Finally, the serialization of the results can be tweaked. Here we encode the XML output as UTF-16 and specify to include an XML declaration,

1
2
3
4
5
let $item := <message>XQuery rocks!</message>
return
  ddtek:serialize-to-url($item,
     "file:///results/output.xml",  
     "omit-xml-declaration=no,encoding=UTF-16")

Let’s look at a more concrete example, where all XML document are copied from one directory to another. in this query we use DataDirect XQuery’s capability to query a complete directory through fn:collection.

1
2
3
4
5
6
7
8
9
declare function local:get-file-name($document-uri as xs:string){
  tokenize($document-uri, "/")[last()]
};

for $doc in fn:collection("file:///C:/input?select=*.xml")
let $filename := concat("file:///C:/output/",
                        local:get-file-name(document-uri($doc)))
return
  ddtek:serialize-to-url($doc, $filename, "")

Assuming this XQuery is saved as C:\xquery\copy-document.xq, it can be executed from the command line as follows

1
java -jar C:\ddxq\lib\ddxq.jar C:\xquery\copy-document.xq

In the next days, we’ll show through some real use cases how to take advantage of ddtek:serialize-to-url

Tech Tags:
Bookmark and Share

{ 2 comments… read them below or add one }

1 vikram June 2, 2009 at 5:46 am

have started working on XQURY for my upcomping project .need help regarding Query. Like if want to insert child node in XML How can i do .
this is error[Error at line 1, column 46. In an insert expression where into, as first into, or as last into is specified, it is a type error if the target expression returns a non-empty result that does not consist of a single element or document node.] have done most of other Queries with QUEry .as
exp

Java
Jerry Pournelle
Pocket
0743416910
5.99

want to make it like

Java
Larry Niven

job1
6pm

Pocket
0743416910
5.99

Any solution this is my Query in java
String queryString =
“declare option ddtek:automatic-update ‘yes’;”+
” insert nodes”+
“job27pm”+
” as last into” +
” doc (’src/books.xml’)/inventory/book[@year='2005']“;
Thanks
Vikram

2 Marc Van Cappellen June 14, 2009 at 2:29 pm

Hi Vikas,

without knowing you input document (books.xml), I guess the document contains multiple books of the year 2005. Remember the target expression must evaluate to a single element.

BTW, for DataDirect XQuery product specific questions, I want to encourage you either to contact our support organization (http://knowledgebase.datadirect.com/display/4/kb/optional/index.aspx?tab=opt2&opt=2&c=12&cpc=TgX6Jd18xTb14qA40Nfr5EdyY0JfnR2l&cid=4&r=0.4629323) or our DataDirect XQuery online forum (http://forums.datadirect.com/ddforums/forum.jspa?forumID=9).

Regards,
Marc

Leave a Comment

Previous post: XQJ Part XI – Processing large inputs

Next post: XQuery 1.0 errata published