{"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&#8217;s 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&#8217;t 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\">&lt;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\">&gt;<\/span><br \/><span class=\"hl kwa\"><a><\/a><\/span>Some text<span class=\"hl kwa\"><\/span><br \/><span class=\"hl kwa\">&lt;a:code<\/span> <span class=\"hl kwb\">lang<\/span>=<span class=\"hl str\">\"xml\"<\/span><span class=\"hl kwa\">&gt;<\/span>&lt;![CDATA[<br \/><span class=\"hl kwa\"><\/span><br \/>]]<span class=\"hl kwa\">&gt;<\/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\">&lt;<\/span>input.xml <span class=\"hl sym\">&gt;<\/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\">&lt;a<\/span> <span class=\"hl kwb\">href<\/span>=<span class=\"hl str\">&#8220;{$i\/text()}&#8221;<\/span><span class=\"hl kwa\">&gt;<\/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\">&#8220;error;&#8221;<\/span><br \/>\n};<\/p>\n<p><span class=\"hl kwa\">&lt;html<\/span> <span class=\"hl kwb\">xmlns<\/span>=<span class=\"hl str\">&#8220;http:\/\/www.w3.org\/1999\/xhtml&#8221;<\/span><span class=\"hl kwa\">&gt;<\/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\">&lt;link<\/span> <span class=\"hl kwb\">rel<\/span>=<span class=\"hl str\">&#8220;stylesheet&#8221;<\/span> <span class=\"hl kwb\">type<\/span>=<span class=\"hl str\">&#8220;text\/css&#8221;<\/span> <span class=\"hl kwb\">href<\/span>=<span class=\"hl str\">&#8220;highlight.css&#8221;<\/span><span class=\"hl kwa\">\/&gt;<\/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&#8217;s 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&#8217;s DOMUtils.parse(result), so it&#8217;s 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],"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/233"}],"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}]}}