Showing posts with label MarkLogic. Show all posts
Showing posts with label MarkLogic. Show all posts

Tuesday, 13 July 2010

MarkLogic cts:query serialization

If you work with MarkLogic you've surely come across cts functions (Built-In: Search), cts:query, and its closest counterparts.

One useful feature available in recent releases is the serialization of cts queries, which allows for the conversion of cts:query types to xml fragments, and the other way round.

If you take a look at the code below, you'll notice the local:mySearch() function which takes a cts:query as it's only parameter. You'll also note cts:search() is used inside this function and references the $query parameter abstracting the query executed by cts:search(). Most interestingly you'll also find a conditional statement invoking an xpath on the $query variable. "But the parameter is strongly typed to cts:query!" . . . you ask. Well that's because it is possible to serialize what would otherwise be "cts:element-value-query(xs:QName("filename"), "myFile", ("lang=en"), 1)" to xml, just by embedding the query in a parent element.

let $query as element(query) := element query {$query}


It is equally possible to do the reverse operation, simply by invoking an xpath returning cts elements in your fragment, wrapped in a cts:query() function.

cts:query($query/*)


This feature also allows for cts queries to be built dynamically as xml fragments rather than concatenated strings.


xquery version '1.0-ml';

declare function local:mySearch($query as cts:query) as element(response)
{
let $query as element(query) := element query {$query}
let $searchResults as element(record)* := cts:search(/record, cts:query($query/*))

return
element response
{
$query,
element results {
if($query/cts:element-value-query/cts:element/text() eq "filename")
then $searchResults//element1
else $searchResults//element2
}
}
};

declare function local:searchByFilename($filename as xs:string) as element(response)
{local:mySearch(cts:element-value-query(xs:QName("filename"), $filename))};

declare function local:searchByVolume($volume as xs:string) as element(response)
{local:mySearch(cts:element-value-query(xs:QName("volume"), $volume))};


local:searchByFilename("myFile")



returns

<response>
<query>
<cts:element-value-query xmlns:cts="http://marklogic.com/cts">
<cts:element>filename</cts:element>
<cts:text xml:lang="en">myfile</cts:text>
</cts:element-value-query>
</query>
<query>cts:element-value-query(xs:QName("filename"), "myfile", ("lang=en"), 1)</query>
<results>
<element1>some content</element1>
<element1>some other content</element1>
</results>
</response>

Wednesday, 4 February 2009

Hello World

To conform to tradition, when you're learning a new language, the first lesson has to be the Hello World application.

So here it is:

"hello world"


If you just add the above line to a text file, usually with the *.xqy, *.xq or *.xquery extension, then initiate a transformation using your favorite XQuery processor, you should see the string "hello world" in the output.

What processor to use
well I would go for something like Saxon, if you're just querying static XML files on your file system, or passing a standalone XML file to the processor at run time.

If you really want to see XQuery at it's best I'd recommend using an XML database as the repository for your XML content. or that you can try MarkLogic or eXist amongst others.

Most of the examples you'll see in future blogs are based on MarkLogic, as it is the processor I have the most experience with, but given the fact that ML has just gone closer to full compliance with W3C 1.0 XQuery standards, chances are that the examples you'll come across are as applicable in any other XQuery processor.

Now back to our code . . . What does "hello world" really mean?
Well the value between the quotes represents a item() of type xs:string. XQuery uses the same Data model as XPath 2.0, so if you're familiar with XSLT and XPath 1.0, then you'll find it really easy to understand the concepts of XQuery.

For a better understanding of data types in XQuery have a look at the XQuery 1.0 and XPath 2.0 Data Model.

Just to keep it simple I'll give you an example of a query, that interrogates an XML file, passed as the input xml to saxon.

The input xml:
<groups><group id="1"/><group id="2"/></groups>

the xquery file : my-lovely-query.xqy

/groups/group


This query returns:
<group id="1"/>
<group id="2"/>

The above represents a sequence of items of type element(group). This means the XPath expression "/groups/group" returned all "group" child element nodes of the root element "groups".

I think this illustrates nicely the very basics of XQuery. I'll get into more detail as new blogs are added.