{"id":233,"date":"2010-01-20T00:11:00","date_gmt":"2010-01-19T22:11:00","guid":{"rendered":""},"modified":"2023-03-20T12:29:26","modified_gmt":"2023-03-20T11:29:26","slug":"xquery4j-in-action","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2010\/01\/20\/xquery4j-in-action\/","title":{"rendered":"xquery4j in action"},"content":{"rendered":"<p>In my previous article, I introduced a wrapper library for Saxon, xquery4j <a href=\"http:\/\/github.com\/rafalrusin\/xquery4j\">http:\/\/github.com\/rafalrusin\/xquery4j<\/a>.<br \/>\nHere, I will explain how to use it to create an article generator in Java and XQuery for XHTML, called Article. You can download it here: <a href=\"http:\/\/github.com\/rafalrusin\/Article\">http:\/\/github.com\/rafalrusin\/Article<\/a>. It\u2019s a simple DSL for article generation.<\/p>\n<p>I think it is something worth noticing, because the whole project took me just a while to implement and has interesting features. Those are:<\/p>\n<ul>\n<li>embedded code syntax highlighting for a lot of programming languages (using external program highlight), <\/li>\n<li>creating href entries for links, so you don\u2019t need to type URL twice<\/li>\n<li>it integrates natively with XHTML constructs<\/li>\n<\/ul>\n<p>This is an example of an input it takes:<\/p>\n<pre class=\"hl\"><span class=\"hl kwa\"><a:article<\/span> xmlns='http:\/\/www.w3.org\/<span class=\"hl num\">1999<\/span>\/xhtml' xmlns:<span class=\"hl kwb\">a<\/span>=<span class=\"hl str\">\"urn:article\"<\/span><span class=\"hl kwa\">><\/span><br \/><span class=\"hl kwa\"><a><\/a><\/span>Some text<span class=\"hl kwa\"><\/span><br \/><span class=\"hl kwa\"><a:code<\/span> <span class=\"hl kwb\">lang<\/span>=<span class=\"hl str\">\"xml\"<\/span><span class=\"hl kwa\">><\/span><![CDATA[<br \/><span class=\"hl kwa\"><\/span><br \/>]]<span class=\"hl kwa\">><\/span><br \/><span class=\"hl kwa\"><\/span><\/pre>\n<p>It generates XHTML output for it, using command<\/p>\n<pre class=\"hl\">.<span class=\"hl sym\">\/<\/span>run <span class=\"hl sym\"><<\/span>input.xml <span class=\"hl sym\">><\/span>output.xhtml<\/pre>\n<p>The interesting thing is that XQuery expression for this transformation is very simple to do in Saxon. This is the complete code of it:<\/p>\n<pre class=\"hl\">declare namespace <span class=\"hl kwb\">a<\/span>=<span class=\"hl str\">\"urn:article\"<\/span>;<br \/>declare default element namespace <span class=\"hl str\">\"http:\/\/www.w3.org\/1999\/xhtml\"<\/span>;<\/pre>\n<p>declare function a:processLine($l) {<br \/>\nfor $i in $l\/node()<br \/>\nreturn<br \/>\ntypeswitch ($i)<br \/>\ncase element(a:link, xs:untyped) return <span class=\"hl kwa\"><a<\/span> <span class=\"hl kwb\">href<\/span>=<span class=\"hl str\">\u201c{$i\/text()}\u201d<\/span><span class=\"hl kwa\">><\/span>{$i\/text()}<span class=\"hl kwa\"><\/span><br \/>\ndefault return $i<br \/>\n};<\/p>\n<p>declare function a:articleItem($i) {<br \/>\ntypeswitch ($i)<br \/>\ncase element(a:l, xs:untyped) return (a:processLine($i), <span class=\"hl kwa\"><br \/><\/span>)<\/p>\n<p>case element(a:code, xs:untyped) return<br \/>\n( a:highlight($i\/text(), $i\/@lang)\/body\/* , <span class=\"hl kwa\"><br \/><\/span>)<\/p>\n<p>default return <span class=\"hl str\">\u201cerror;\u201d<\/span><br \/>\n};<\/p>\n<p><span class=\"hl kwa\"><html<\/span> <span class=\"hl kwb\">xmlns<\/span>=<span class=\"hl str\">\u201chttp:\/\/www.w3.org\/1999\/xhtml\u201d<\/span><span class=\"hl kwa\">><\/span><br \/>\n<span class=\"hl kwa\"><\/span><br \/>\n<span class=\"hl kwa\"><title><br \/>\n<\/title><\/span>a.xml<\/p>\n<p><span class=\"hl kwa\"><\/span><br \/>\n<span class=\"hl kwa\"><link<\/span> <span class=\"hl kwb\">rel<\/span>=<span class=\"hl str\">\u201cstylesheet\u201d<\/span> <span class=\"hl kwb\">type<\/span>=<span class=\"hl str\">\u201ctext\/css\u201d<\/span> <span class=\"hl kwb\">href<\/span>=<span class=\"hl str\">\u201chighlight.css\u201d<\/span><span class=\"hl kwa\">\/><\/span><br \/>\n<span class=\"hl kwa\"><\/span><br \/>\n<span class=\"hl kwa\"><\/span><br \/>\n{<br \/>\nfor $i in a:article\/*<br \/>\nreturn<br \/>\na:articleItem($i)<br \/>\n}<br \/>\n<span class=\"hl kwa\"><\/span><br \/>\n<span class=\"hl kwa\"><\/span><\/p>\n<p>Inside this expression, there is bound a:highlight Java function, which takes two strings on input (a code and a language) and returns DOM Node containing XHTML output from highlight command.<br \/>\nSince there is not much trouble with manipulating DOM using xquery4j, we can get as simple solution as this for a:highlight function:<\/p>\n<pre class=\"hl\"><span class=\"hl kwa\">public static class<\/span> Mod <span class=\"hl sym\">{<\/span><br \/>        <span class=\"hl kwa\">public static<\/span> <span class=\"hl kwc\">Node<\/span> <span class=\"hl kwd\">highlight<\/span><span class=\"hl sym\">(<\/span><span class=\"hl kwa\">final<\/span> <span class=\"hl kwc\">String<\/span> code<span class=\"hl sym\">,<\/span> <span class=\"hl kwc\">String<\/span> lang<span class=\"hl sym\">)<\/span> <span class=\"hl kwa\">throws<\/span> <span class=\"hl kwc\">Exception<\/span> <span class=\"hl sym\">{<\/span><br \/>            Validate<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">notNull<\/span><span class=\"hl sym\">(<\/span>lang<span class=\"hl sym\">);<\/span><br \/>            <span class=\"hl kwa\">final<\/span> <span class=\"hl kwc\">Process<\/span> p <span class=\"hl sym\">=<\/span> <span class=\"hl kwa\">new<\/span> <span class=\"hl kwc\">ProcessBuilder<\/span><span class=\"hl sym\">(<\/span><span class=\"hl str\">\"highlight\"<\/span><span class=\"hl sym\">,<\/span> <span class=\"hl str\">\"-X\"<\/span><span class=\"hl sym\">,<\/span> <span class=\"hl str\">\"--syntax\"<\/span><span class=\"hl sym\">,<\/span> lang<span class=\"hl sym\">).<\/span><span class=\"hl kwd\">start<\/span><span class=\"hl sym\">();<\/span><br \/>            <span class=\"hl kwc\">Thread<\/span> t <span class=\"hl sym\">=<\/span> <span class=\"hl kwa\">new<\/span> <span class=\"hl kwc\">Thread<\/span><span class=\"hl sym\">(<\/span><span class=\"hl kwa\">new<\/span> <span class=\"hl kwc\">Runnable<\/span><span class=\"hl sym\">() {<\/span><\/pre>\n<p><span class=\"hl kwa\">public<\/span> <span class=\"hl kwb\">void<\/span> <span class=\"hl kwd\">run<\/span><span class=\"hl sym\">() {<\/span><br \/>\n<span class=\"hl kwa\">try<\/span> <span class=\"hl sym\">{<\/span><br \/>\n<span class=\"hl kwc\">OutputStream<\/span> out <span class=\"hl sym\">=<\/span> p<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">getOutputStream<\/span><span class=\"hl sym\">();<\/span><br \/>\nIOUtils<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">write<\/span><span class=\"hl sym\">(<\/span>code<span class=\"hl sym\">,<\/span> out<span class=\"hl sym\">);<\/span><br \/>\nout<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">flush<\/span><span class=\"hl sym\">();<\/span><br \/>\nout<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">close<\/span><span class=\"hl sym\">();<\/span><br \/>\n<span class=\"hl sym\">}<\/span> <span class=\"hl kwa\">catch<\/span> <span class=\"hl sym\">(<\/span><span class=\"hl kwc\">IOException<\/span> e<span class=\"hl sym\">) {<\/span><br \/>\n<span class=\"hl kwa\">throw new<\/span> <span class=\"hl kwc\">RuntimeException<\/span><span class=\"hl sym\">(<\/span>e<span class=\"hl sym\">);<\/span><br \/>\n<span class=\"hl sym\">}<\/span><br \/>\n<span class=\"hl sym\">}<\/span><br \/>\n<span class=\"hl sym\">});<\/span><br \/>\nt<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">start<\/span><span class=\"hl sym\">();<\/span><br \/>\n<span class=\"hl kwc\">String<\/span> result <span class=\"hl sym\">=<\/span> IOUtils<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">toString<\/span><span class=\"hl sym\">(<\/span>p<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">getInputStream<\/span><span class=\"hl sym\">());<\/span><br \/>\nt<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">join<\/span><span class=\"hl sym\">();<\/span><br \/>\n<span class=\"hl kwa\">return<\/span> DOMUtils<span class=\"hl sym\">.<\/span><span class=\"hl kwd\">parse<\/span><span class=\"hl sym\">(<\/span>result<span class=\"hl sym\">).<\/span><span class=\"hl kwd\">getDocumentElement<\/span><span class=\"hl sym\">();<\/span><br \/>\n<span class=\"hl sym\">}<\/span><br \/>\n<span class=\"hl sym\">}<\/span><\/p>\n<p>Please note that creating a separate thread for feeding input into highlight command is required, since Thread\u2019s output queue is limited and potentially might lead to dead lock. So we need to concurrently collect output from spawned Process.<br \/>\nHowever at the end, when we need to convert a String to DOM and we use xquery4j\u2019s DOMUtils.parse(result), so it\u2019s a very simple construct.<\/p>\n<div class=\"blogger-post-footer\">\n  <img width='1' height='1' src='https:\/\/blogger.googleusercontent.com\/tracker\/6983141563768732668-4164230652127853388?l=rrusin.blogspot.com' alt='' \/>\n<\/div>\n","protected":false},"excerpt":{"rendered":"In my previous article, I introduced a wrapper library for Saxon, xquery4j http:\/\/github.com\/rafalrusin\/xquery4j. Here, I will explain how&hellip;\n","protected":false},"author":35,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[107],"class_list":{"0":"post-233","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-xml"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/233","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=233"}],"version-history":[{"count":29,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/233\/revisions"}],"predecessor-version":[{"id":15321,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/233\/revisions\/15321"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=233"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=233"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=233"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}