Tuesday, January 19, 2010

xquery4j in action

In my previous article, I introduced a wrapper library for Saxon, xquery4j http://github.com/rafalrusin/xquery4j.
Here, 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: http://github.com/rafalrusin/Article. It's a simple DSL for article generation.

I think it is something worth noticing, because the whole project took me just a while to implement and has interesting features. Those are:
  • embedded code syntax highlighting for a lot of programming languages (using external program highlight),
  • creating href entries for links, so you don't need to type URL twice
  • it integrates natively with XHTML constructs

This is an example of an input it takes:
<a:article xmlns='http://www.w3.org/1999/xhtml' xmlns:a="urn:article">
<a:l>Some text</a:l>
<a:code lang="xml"><![CDATA[
<someXml/>
]]></a:code>
</a:article>

It generates XHTML output for it, using command
./run <input.xml >output.xhtml

The interesting thing is that XQuery expression for this transformation is very simple to do in Saxon. This is the complete code of it:
declare namespace a="urn:article";
declare default element namespace "http://www.w3.org/1999/xhtml";

declare function a:processLine($l) {
for $i in $l/node()
return
typeswitch ($i)
  case element(a:link, xs:untyped) return <a href="{$i/text()}">{$i/text()}</a>
  default return $i
};

declare function a:articleItem($i) {
typeswitch ($i)
 case element(a:l, xs:untyped) return (a:processLine($i), <br/>)

 case element(a:code, xs:untyped) return
  ( a:highlight($i/text(), $i/@lang)/body/* , <br/>)

 default return "error;"
};

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>a.xml</title>
<link rel="stylesheet" type="text/css" href="highlight.css"/>
</head>
<body>
{
for $i in a:article/*
return
a:articleItem($i)
}
</body>
</html>

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.
Since there is not much trouble with manipulating DOM using xquery4j, we can get as simple solution as this for a:highlight function:
    public static class Mod {
        public static Node highlight(final String code, String lang) throws Exception {
            Validate.notNull(lang);
            final Process p = new ProcessBuilder("highlight", "-X", "--syntax", lang).start();
            Thread t = new Thread(new Runnable() {

                public void run() {
                    try {
                        OutputStream out = p.getOutputStream();
                        IOUtils.write(code, out);
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
            t.start();
            String result = IOUtils.toString(p.getInputStream());
            t.join();
            return DOMUtils.parse(result).getDocumentElement();
        }
    }

Please note that creating a separate thread for feeding input into highlight command is required, since Thread's output queue is limited and potentially might lead to dead lock. So we need to concurrently collect output from spawned Process.
However at the end, when we need to convert a String to DOM and we use xquery4j's DOMUtils.parse(result), so it's a very simple construct.

4 comments:

  1. I must say you have done a very good job with this. In addition, the blog loads very fast for me on Internet explorer. Excellent Blog! Thank you so much for sharing. Also visit yabatech nd degree supplementary admission list out

    ReplyDelete
  2. الحفاظ على وزن صحي: السمنة قد تزيد من ضغط الدم على الأوردة السطحية في الساقين. لذلك، يوصى بالحفاظ على وزن صحي ومتوازن للحد من تطور دوالي الساقين وتخفيف الأعراض المصاحبة كذلك علاج دوالي الساقين بالليزر يساعد علي الشفاء بشكل سريع

    ReplyDelete
  3. مواصفات ارخص شركة نقل اثاث بالقاهرة
    التقديرات السعرية:
    اطلب تقديرات سعرية من عدة شركات مختلفة وقارن بينها. تأكد من أن الشركة تقدم تقديرات مفصلة تشمل جميع الخدمات المطلوبة مع توضيح الرسوم والتكاليف.

    الخدمات المقدمة:
    تحقق من نطاق الخدمات التي تقدمها الشركة، مثل خدمات التعبئة والتغليف، وفك وتركيب الأثاث، والنقل الداخلي أو الخارجي.

    المرونة الزمنية:
    اسأل عن مرونة الشركة في تحديد مواعيد النقل بما يتناسب مع جدولك الزمني.

    ReplyDelete
  4. عند نقل عفش بالونش بيتك يجب أن تخضع سيارة النقل للصيانة الدورية للتأكد من سلامة الهيكل والميكانيكية، مما يسهم في تقديم خدمة نقل آمنة كذلك القيادة الهادئة والآمنة تلعب دورًا في تجنب حوادث النقل، لذلك يجب على السائق الالتزام بقواعد السلامة والقانون.باختيار سيارة نقل العفش المناسبة واتخاذ التدابير الصحيحة لتأمين العفش داخلها، يمكن تحقيق نقل الأثاث بدون تلف وبشكل آمن.

    ReplyDelete