При разработке первой версии интерент-магазина постельного белья kunmeng.ru, мне нужно было быстро сгенерировать много страниц по шаблону. Изначально текстовые данные о товаре я перевел в XML. Соответственно, для генерации карточек товаров и групп логично было бы использовать XSLT, который я не люблю. Выяснилось, что появился новый язык для работы с XML данными — XQuery, который оказался гораздо проще XSLT по синтаксису и вообще как-то понятнее.
Оставались только две небольшие проблемы:
Практически единственной доступной и нормальной реализацией оказался Saxon. Но вторая проблема в нем решалась только в коммерческой версии с помощью функции saxon:result-document(). Зато, можно было писать свои расширения на Java, и поэтому я быстренько набросал простейший убогий аналог saxon:result-document():
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;
/**
* Created: 16.11.2007
*
* @author Artem Kuroptev
*/
public class XQSaver
{
public static String save(String path,
String content,
String enc)
throws IOException
{
FileOutputStream fos
= new FileOutputStream(new File(path));
try
{
fos.write(content.getBytes(enc));
}
finally
{
fos.close();
}
return "";
}
}
Как использовать эту функцию в XQ? Очень просто.
Нужно скомпилировать класс и добавить его в classpath при вызове Saxon:
java -cp Lib\saxonb9-0-0-1j\saxon9.jar;java\classes net.sf.saxon.Query ...
Затем в XQ в заголовке пишем:
declare namespace my="java:XQSaver";
А теперь сам вызов:
for $item in doc("catalog.xml")/items/item
let $file := concat(concat("item-", $item/id/text()), ".html")
let $a:= <html>test</html>
return
<done>{my:save($file,
saxon:serialize($a,
<xsl:output
method="html"
encoding="cp1251"
indent="yes"
saxon:indent-spaces="2"/>),
"cp1251")}</done>
Этот пример, конечно, грязноват с идеологической точки зрения, но когда нужно сделать работу быстро или набросать тестик — он вполне подходит.