summaryrefslogtreecommitdiffstats
path: root/org/madore
diff options
context:
space:
mode:
authorDavid A. Madore <david+git@madore.org>2011-08-31 22:26:55 +0200
committerDavid A. Madore <david+git@madore.org>2011-08-31 22:26:55 +0200
commit057a46982292c765e664f886097fdaf33ed22a62 (patch)
treef9ba446ae36f4e13f4b579b293ace2004a0dbf29 /org/madore
parent3d44424a1738ce3f70c82780f4441e077c1194a3 (diff)
downloaddamlengine-057a46982292c765e664f886097fdaf33ed22a62.tar.gz
damlengine-057a46982292c765e664f886097fdaf33ed22a62.tar.bz2
damlengine-057a46982292c765e664f886097fdaf33ed22a62.zip
Wrap it all in a single command handler.
Diffstat (limited to 'org/madore')
-rw-r--r--org/madore/damlengine/Context.java8
-rw-r--r--org/madore/damlengine/DamlEngine.java70
-rw-r--r--org/madore/damlengine/WeblogIndexSelect.java6
-rw-r--r--org/madore/damlengine/WeblogPopulate.java154
-rw-r--r--org/madore/damlengine/WeblogRSS.java13
-rw-r--r--org/madore/damlengine/WeblogSelect.java32
-rw-r--r--org/madore/damlengine/weblog-cat-template.daml60
-rw-r--r--org/madore/damlengine/weblog-index-template.daml60
-rw-r--r--org/madore/damlengine/weblog-month-template.daml178
-rw-r--r--org/madore/damlengine/weblog-recent-template.daml60
10 files changed, 536 insertions, 105 deletions
diff --git a/org/madore/damlengine/Context.java b/org/madore/damlengine/Context.java
index 388a076..12e2f1b 100644
--- a/org/madore/damlengine/Context.java
+++ b/org/madore/damlengine/Context.java
@@ -49,6 +49,14 @@ public class Context implements Cloneable {
}
}
+ public static class WeblogRecentSelectionContext
+ extends WeblogSelectionContext {
+ public int count;
+ public WeblogRecentSelectionContext(int count) {
+ this.count = count;
+ }
+ }
+
public WeblogSelectionContext wsc;
public static class EntryContext {
diff --git a/org/madore/damlengine/DamlEngine.java b/org/madore/damlengine/DamlEngine.java
index e54ee86..874a220 100644
--- a/org/madore/damlengine/DamlEngine.java
+++ b/org/madore/damlengine/DamlEngine.java
@@ -1,9 +1,14 @@
package org.madore.damlengine;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
import java.io.InputStream;
import java.io.FileInputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
+import java.io.BufferedReader;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -117,12 +122,65 @@ public final class DamlEngine {
public static void main(String[] args)
throws Exception {
- if ( args.length == 0 ) {
- System.err.println("expecting filename as argument");
- }
-
- for (String fname : args) {
- fullProcess (new FileInputStream(fname), System.out);
+ BufferedReader buf = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
+ String line;
+ Matcher matcher;
+
+ while ( ( line = buf.readLine() ) != null ) {
+ if ( Pattern.matches("^\\s+$", line) )
+ continue;
+ else if ( (matcher=Pattern.compile("process\\s+(\\S+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+ String inf = matcher.group(1);
+ String outf = matcher.group(2);
+ InputStream in = new FileInputStream(inf);
+ OutputStream out = (outf != null)
+ ? new FileOutputStream(outf)
+ : System.out;
+ fullProcess(in, out);
+ } else if ( (matcher=Pattern.compile("process-weblog-month\\s+(\\d{4})\\-(\\d{2})(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+ String year = matcher.group(1);
+ String month = matcher.group(2);
+ String outf = matcher.group(3);
+ OutputStream out = (outf != null)
+ ? new FileOutputStream(outf)
+ : System.out;
+ WeblogSelect.fullProcess(new Context.WeblogMonthSelectionContext(year,month),
+ out);
+ } else if ( (matcher=Pattern.compile("process-weblog-cat\\s+([a-z0-9\\-]+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+ String code = matcher.group(1);
+ String outf = matcher.group(2);
+ OutputStream out = (outf != null)
+ ? new FileOutputStream(outf)
+ : System.out;
+ WeblogSelect.fullProcess(new Context.WeblogCategorySelectionContext(code),
+ out);
+ } else if ( (matcher=Pattern.compile("process-weblog-recent\\s+(\\d+)(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+ int count = Integer.parseInt(matcher.group(1));
+ String outf = matcher.group(2);
+ OutputStream out = (outf != null)
+ ? new FileOutputStream(outf)
+ : System.out;
+ WeblogSelect.fullProcess(new Context.WeblogRecentSelectionContext(count),
+ out);
+ } else if ( (matcher=Pattern.compile("process-weblog-index(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+ String outf = matcher.group(1);
+ OutputStream out = (outf != null)
+ ? new FileOutputStream(outf)
+ : System.out;
+ WeblogIndexSelect.fullProcess(out);
+ } else if ( (matcher=Pattern.compile("process-weblog-rss(?:\\s+\\>\\s*(\\S+))?\\s*").matcher(line)).matches() ) {
+ String outf = matcher.group(1);
+ OutputStream out = (outf != null)
+ ? new FileOutputStream(outf)
+ : System.out;
+ WeblogRSS.fullProcess(out);
+ } else if ( (matcher=Pattern.compile("populate-weblog\\s+(\\S+)\\s*").matcher(line)).matches() ) {
+ String inf = matcher.group(1);
+ InputStream in = new FileInputStream(inf);
+ WeblogPopulate.populate(in);
+ } else {
+ throw new IllegalArgumentException("couldn't understand command");
+ }
}
}
diff --git a/org/madore/damlengine/WeblogIndexSelect.java b/org/madore/damlengine/WeblogIndexSelect.java
index c9bf617..83c5461 100644
--- a/org/madore/damlengine/WeblogIndexSelect.java
+++ b/org/madore/damlengine/WeblogIndexSelect.java
@@ -1,16 +1,18 @@
package org.madore.damlengine;
+import java.io.OutputStream;
+
public final class WeblogIndexSelect {
private WeblogIndexSelect() { // Forbid instantiation
throw new AssertionError("WeblogIndexSelect cannot be instantiated");
}
- public static void main(String[] args)
+ public static void fullProcess(OutputStream out)
throws Exception {
DamlEngine.fullProcess(DamlEngine.class.getResourceAsStream("weblog-index-template.daml"),
- System.out, null);
+ out, null);
}
diff --git a/org/madore/damlengine/WeblogPopulate.java b/org/madore/damlengine/WeblogPopulate.java
index 0d28d92..56e51ac 100644
--- a/org/madore/damlengine/WeblogPopulate.java
+++ b/org/madore/damlengine/WeblogPopulate.java
@@ -1,6 +1,7 @@
package org.madore.damlengine;
import java.util.regex.Pattern;
+import java.io.InputStream;
import java.security.MessageDigest;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -25,15 +26,11 @@ public final class WeblogPopulate {
return sb.toString();
}
- public static void main(String[] args)
+ public static void populate(InputStream in)
throws Exception {
final DocumentBuilder db = DamlEngine.GetDocumentBuilder.db;
- if ( args.length == 0 ) {
- System.err.println("expecting filename as argument");
- }
-
final DOMImplementationLS domi
= (DOMImplementationLS)(db.getDOMImplementation());
LSSerializer ser = domi.createLSSerializer();
@@ -56,83 +53,81 @@ public final class WeblogPopulate {
final PreparedStatement setCatSt
= conn.prepareStatement("INSERT INTO incat(id,code) VALUES (?,?)");
- for (String fname : args) {
- Document doc = db.parse(fname);
- XPathFactory xpf = XPathFactory.newInstance();
- XPath xp = xpf.newXPath();
- xp.setNamespaceContext(new DamlEngine.DamlNSMapping());
- XPathExpression expr = xp.compile("//d:weblog/d:entry");
- XPathExpression texpr = xp.compile("d:title");
- NodeList entries = (NodeList)(expr.evaluate(doc, XPathConstants.NODESET));
- for ( int i=0 ; i<entries.getLength() ; i++ ) {
- Element ent = (Element)(entries.item(i));
- String idStr = ent.getAttributeNS(null, "number");
- if ( ! Pattern.matches("^\\d{4}$", idStr) )
- throw new IllegalArgumentException("entry number attribute must be of the form NNNN");
- int id = Integer.parseInt(idStr);
- String date = ent.getAttributeNS(null, "date");
- if ( ! Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", date) )
- throw new IllegalArgumentException("entry date attribute must be of the form YYYY-MM-DD");
- String cdate;
- if ( ent.hasAttributeNS(null, "cdate") )
- cdate = ent.getAttributeNS(null, "cdate");
+ Document doc = db.parse(in);
+ XPathFactory xpf = XPathFactory.newInstance();
+ XPath xp = xpf.newXPath();
+ xp.setNamespaceContext(new DamlEngine.DamlNSMapping());
+ XPathExpression expr = xp.compile("//d:weblog/d:entry");
+ XPathExpression texpr = xp.compile("d:title");
+ NodeList entries = (NodeList)(expr.evaluate(doc, XPathConstants.NODESET));
+ for ( int i=0 ; i<entries.getLength() ; i++ ) {
+ Element ent = (Element)(entries.item(i));
+ String idStr = ent.getAttributeNS(null, "number");
+ if ( ! Pattern.matches("^\\d{4}$", idStr) )
+ throw new IllegalArgumentException("entry number attribute must be of the form NNNN");
+ int id = Integer.parseInt(idStr);
+ String date = ent.getAttributeNS(null, "date");
+ if ( ! Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$", date) )
+ throw new IllegalArgumentException("entry date attribute must be of the form YYYY-MM-DD");
+ String cdate;
+ if ( ent.hasAttributeNS(null, "cdate") )
+ cdate = ent.getAttributeNS(null, "cdate");
+ else
+ cdate = null;
+ String catStr = ent.getAttributeNS(null, "cat");
+ String[] catList = catStr.split("\\s+");
+ String lang = LangHelper.getLangRec(ent);
+ String content = ser.writeToString(ent);
+ sha1.reset();
+ String digest = toHex(sha1.digest(content.getBytes("UTF-8")));
+
+ checkSt.setInt(1, id);
+ ResultSet checkRes = checkSt.executeQuery();
+ boolean exists = checkRes.next();
+ if ( exists && checkRes.getString(1).equals(digest) )
+ continue;
+ Node titleNode = (Node)(texpr.evaluate(ent, XPathConstants.NODE));
+ String titleTxt = (titleNode != null) ? titleNode.getTextContent() : null;
+ String titleXml = (titleNode != null) ? ser.writeToString(titleNode) : null;
+ conn.setAutoCommit(false);
+ if ( exists ) {
+ System.err.println("Updating entry "+id);
+ updateSt.setString(1, date);
+ updateSt.setString(2, lang);
+ updateSt.setString(3, titleTxt);
+ updateSt.setString(4, titleXml);
+ updateSt.setString(5, content);
+ updateSt.setString(6, digest);
+ updateSt.setInt(7, id);
+ updateSt.executeUpdate();
+ } else {
+ System.err.println("Registering entry "+id);
+ PreparedStatement insertSt;
+ if ( cdate == null )
+ insertSt = insertNSt;
else
- cdate = null;
- String catStr = ent.getAttributeNS(null, "cat");
- String[] catList = catStr.split("\\s+");
- String lang = LangHelper.getLangRec(ent);
- String content = ser.writeToString(ent);
- sha1.reset();
- String digest = toHex(sha1.digest(content.getBytes("UTF-8")));
-
- checkSt.setInt(1, id);
- ResultSet checkRes = checkSt.executeQuery();
- boolean exists = checkRes.next();
- if ( exists && checkRes.getString(1).equals(digest) )
- continue;
- Node titleNode = (Node)(texpr.evaluate(ent, XPathConstants.NODE));
- String titleTxt = (titleNode != null) ? titleNode.getTextContent() : null;
- String titleXml = (titleNode != null) ? ser.writeToString(titleNode) : null;
- conn.setAutoCommit(false);
- if ( exists ) {
- System.err.println("Updating entry "+id);
- updateSt.setString(1, date);
- updateSt.setString(2, lang);
- updateSt.setString(3, titleTxt);
- updateSt.setString(4, titleXml);
- updateSt.setString(5, content);
- updateSt.setString(6, digest);
- updateSt.setInt(7, id);
- updateSt.executeUpdate();
- } else {
- System.err.println("Registering entry "+id);
- PreparedStatement insertSt;
- if ( cdate == null )
- insertSt = insertNSt;
- else
- insertSt = insertCSt;
- insertSt.setInt(1, id);
- insertSt.setString(2, date);
- insertSt.setString(3, lang);
- insertSt.setString(4, titleTxt);
- insertSt.setString(5, titleXml);
- insertSt.setString(6, content);
- insertSt.setString(7, digest);
- if ( cdate != null )
- insertSt.setString(8, cdate);
- insertSt.executeUpdate();
- }
- clearCatSt.setInt(1, id);
- clearCatSt.executeUpdate();
- for ( String cat : catList ) {
- if ( ! cat.equals("") ) {
- setCatSt.setInt(1, id);
- setCatSt.setString(2, cat);
- setCatSt.executeUpdate();
- }
+ insertSt = insertCSt;
+ insertSt.setInt(1, id);
+ insertSt.setString(2, date);
+ insertSt.setString(3, lang);
+ insertSt.setString(4, titleTxt);
+ insertSt.setString(5, titleXml);
+ insertSt.setString(6, content);
+ insertSt.setString(7, digest);
+ if ( cdate != null )
+ insertSt.setString(8, cdate);
+ insertSt.executeUpdate();
+ }
+ clearCatSt.setInt(1, id);
+ clearCatSt.executeUpdate();
+ for ( String cat : catList ) {
+ if ( ! cat.equals("") ) {
+ setCatSt.setInt(1, id);
+ setCatSt.setString(2, cat);
+ setCatSt.executeUpdate();
}
- conn.commit();
}
+ conn.commit();
}
checkSt.close();
@@ -141,7 +136,6 @@ public final class WeblogPopulate {
updateSt.close();
clearCatSt.close();
setCatSt.close();
- conn.close();
}
diff --git a/org/madore/damlengine/WeblogRSS.java b/org/madore/damlengine/WeblogRSS.java
index c08991c..31744f5 100644
--- a/org/madore/damlengine/WeblogRSS.java
+++ b/org/madore/damlengine/WeblogRSS.java
@@ -2,6 +2,7 @@ package org.madore.damlengine;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
+import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -19,7 +20,7 @@ public final class WeblogRSS {
throw new AssertionError("WeblogRSS cannot be instantiated");
}
- public static void main(String[] args)
+ public static void fullProcess(OutputStream out)
throws Exception {
final Connection conn = WeblogDatabaseConnection.getConnection();
@@ -37,9 +38,9 @@ public final class WeblogRSS {
ser.getDomConfig().setParameter("xml-declaration", true);
LSParser par = domi.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
- final LSOutput out = domi.createLSOutput();
- out.setByteStream(System.out);
- out.setEncoding("UTF-8");
+ final LSOutput lsout = domi.createLSOutput();
+ lsout.setByteStream(out);
+ lsout.setEncoding("UTF-8");
Document rssDoc = db.newDocument();
Element rssRoot = rssDoc.createElementNS(DamlEngine.RDF_NS, "rdf:RDF");
@@ -144,8 +145,8 @@ public final class WeblogRSS {
itemDescr.appendChild(rssDoc.createTextNode(descrStr));
}
- ser.write(rssDoc, out);
- out.getByteStream().write("\n".getBytes("UTF-8"));
+ ser.write(rssDoc, lsout);
+ out.write("\n".getBytes("UTF-8"));
}
diff --git a/org/madore/damlengine/WeblogSelect.java b/org/madore/damlengine/WeblogSelect.java
index cb263e6..1593d72 100644
--- a/org/madore/damlengine/WeblogSelect.java
+++ b/org/madore/damlengine/WeblogSelect.java
@@ -2,6 +2,7 @@ package org.madore.damlengine;
import java.util.HashSet;
import java.util.ArrayList;
+import java.io.OutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -12,21 +13,30 @@ public final class WeblogSelect {
throw new AssertionError("WeblogSelect cannot be instantiated");
}
- public static void main(String[] args)
+ public static void fullProcess(Context.WeblogSelectionContext wsc,
+ OutputStream out)
throws Exception {
- String year = "2011";
- String month = "08";
-
final Connection conn = WeblogDatabaseConnection.getConnection();
- final PreparedStatement selSt
- = conn.prepareStatement("SELECT id , content FROM entries WHERE edate LIKE ? ORDER BY id DESC");
- selSt.setString(1,year+"-"+month+"-__");
+ String templateResourceName;
+ final PreparedStatement selSt;
+ if ( wsc instanceof Context.WeblogMonthSelectionContext ) {
+ templateResourceName = "weblog-month-template.daml";
+ selSt = conn.prepareStatement("SELECT id , content FROM entries WHERE edate LIKE ? ORDER BY id DESC");
+ selSt.setString(1,((Context.WeblogMonthSelectionContext)wsc).year+"-"+((Context.WeblogMonthSelectionContext)wsc).month+"-__");
+ } else if ( wsc instanceof Context.WeblogCategorySelectionContext ) {
+ templateResourceName = "weblog-cat-template.daml";
+ selSt = conn.prepareStatement("SELECT entries.id , entries.content FROM entries , incat WHERE entries.id=incat.id AND incat.code=? ORDER BY entries.id DESC");
+ selSt.setString(1,((Context.WeblogCategorySelectionContext)wsc).code);
+ } else if ( wsc instanceof Context.WeblogRecentSelectionContext ) {
+ templateResourceName = "weblog-recent-template.daml";
+ selSt = conn.prepareStatement("SELECT id , content FROM entries ORDER BY id DESC LIMIT ?");
+ selSt.setInt(1,((Context.WeblogRecentSelectionContext)wsc).count);
+ } else
+ throw new IllegalArgumentException("don't know how to perform this selection");
final ResultSet selRes = selSt.executeQuery();
- final Context.WeblogSelectionContext wsc
- = new Context.WeblogMonthSelectionContext(year,month);
wsc.sel = new HashSet<Integer>();
wsc.xmlData = new ArrayList<String>();
while ( selRes.next() ) {
@@ -36,8 +46,8 @@ public final class WeblogSelect {
wsc.xmlData.add(content);
}
- DamlEngine.fullProcess(DamlEngine.class.getResourceAsStream("weblog-month-template.daml"),
- System.out, wsc);
+ DamlEngine.fullProcess(DamlEngine.class.getResourceAsStream(templateResourceName),
+ out, wsc);
}
diff --git a/org/madore/damlengine/weblog-cat-template.daml b/org/madore/damlengine/weblog-cat-template.daml
new file mode 100644
index 0000000..261686f
--- /dev/null
+++ b/org/madore/damlengine/weblog-cat-template.daml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE d:daml [
+ <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+ %HTMLlat1;
+ <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+ %HTMLspecial;
+ <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+ %HTMLsymbol;
+ <!ENTITY uri-to-top "../">
+ <!ENTITY file.language "en">
+ <!ENTITY my-email "<d:email-despammed xmlns:d='http://www.madore.org/~david/NS/daml/'>david+www<d:email-at />madore<d:email-dot />org</d:email-despammed>">
+]>
+
+<d:daml xml:lang="&file.language;" uri-to-top="&uri-to-top;" xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.madore.org/~david/NS/daml/">
+
+<d:title>David Madore's WebLog</d:title>
+
+<d:meta-description>David Alexander Madore's WebLog / Diary</d:meta-description>
+
+<d:meta-keywords>David Alexander Madore, WebLog, diary</d:meta-keywords>
+
+<link rel="alternate" type="application/rss+xml" title="RSS" href="weblog.rss" />
+
+<d:body>
+
+<p>This WebLog is bilingual, some entries are in English and others
+are in French. A few of them have a version in either language.
+Other than that, the French entries are <em>not</em> translations of
+the English ones or vice versa. Of course, if you understand only
+English, the English entries ought to be quite understandable without
+reading the French ones.</p>
+
+<p xml:lang="fr">Ce WebLog est bilingue, certaines entrées sont en
+anglais et d'autres sont en français. Quelques-unes ont une version
+dans chaque langue. À part ça, les entrées en français <em>ne</em>
+sont <em>pas</em> des traductions de celles en anglais ou vice versa.
+Bien sûr, si vous ne comprenez que le français, les entrées en
+français devraient être assez compréhensibles sans lire celles en
+anglais.</p>
+
+<p>Note that the first entry comes <a
+d:wref="#d.2003-05-01.0001">last</a>! <span xml:lang="fr">Notez que la
+première entrée vient en <a
+d:wref="#d.2003-05-01.0001">dernier</a> !</span></p>
+
+<p><a href="weblog-index.html#index">Index of all entries &mdash;
+<span xml:lang="fr">Index de toutes les entrées</span></a> &mdash; <a
+href="weblog.rss" rel="alternate" type="application/rss+xml"
+title="RSS"><img src="&uri-to-top;images/xml.gif" alt="XML" width="36"
+height="14" /></a> (<abbr>RSS</abbr> 1.0) &mdash; <a
+href="http://www.madore.org/cgi-bin/comment.pl/lscomments">Recent
+comments &mdash; <span xml:lang="fr">Commentaires
+récents</span></a></p>
+
+<d:weblog-select />
+
+</d:body>
+
+</d:daml>
diff --git a/org/madore/damlengine/weblog-index-template.daml b/org/madore/damlengine/weblog-index-template.daml
new file mode 100644
index 0000000..fb45477
--- /dev/null
+++ b/org/madore/damlengine/weblog-index-template.daml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE d:daml [
+ <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+ %HTMLlat1;
+ <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+ %HTMLspecial;
+ <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+ %HTMLsymbol;
+ <!ENTITY uri-to-top "../">
+ <!ENTITY file.language "en">
+ <!ENTITY my-email "<d:email-despammed xmlns:d='http://www.madore.org/~david/NS/daml/'>david+www<d:email-at />madore<d:email-dot />org</d:email-despammed>">
+]>
+
+<d:daml xml:lang="&file.language;" uri-to-top="&uri-to-top;" xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.madore.org/~david/NS/daml/">
+
+<d:title>David Madore's WebLog</d:title>
+
+<d:meta-description>David Alexander Madore's WebLog / Diary</d:meta-description>
+
+<d:meta-keywords>David Alexander Madore, WebLog, diary</d:meta-keywords>
+
+<link rel="alternate" type="application/rss+xml" title="RSS" href="weblog.rss" />
+
+<d:body>
+
+<p>This WebLog is bilingual, some entries are in English and others
+are in French. A few of them have a version in either language.
+Other than that, the French entries are <em>not</em> translations of
+the English ones or vice versa. Of course, if you understand only
+English, the English entries ought to be quite understandable without
+reading the French ones.</p>
+
+<p xml:lang="fr">Ce WebLog est bilingue, certaines entrées sont en
+anglais et d'autres sont en français. Quelques-unes ont une version
+dans chaque langue. À part ça, les entrées en français <em>ne</em>
+sont <em>pas</em> des traductions de celles en anglais ou vice versa.
+Bien sûr, si vous ne comprenez que le français, les entrées en
+français devraient être assez compréhensibles sans lire celles en
+anglais.</p>
+
+<p>Note that the first entry comes <a
+d:wref="#d.2003-05-01.0001">last</a>! <span xml:lang="fr">Notez que la
+première entrée vient en <a
+d:wref="#d.2003-05-01.0001">dernier</a> !</span></p>
+
+<p><a href="weblog-index.html#index">Index of all entries &mdash;
+<span xml:lang="fr">Index de toutes les entrées</span></a> &mdash; <a
+href="weblog.rss" rel="alternate" type="application/rss+xml"
+title="RSS"><img src="&uri-to-top;images/xml.gif" alt="XML" width="36"
+height="14" /></a> (<abbr>RSS</abbr> 1.0) &mdash; <a
+href="http://www.madore.org/cgi-bin/comment.pl/lscomments">Recent
+comments &mdash; <span xml:lang="fr">Commentaires
+récents</span></a></p>
+
+<d:weblog-index-select />
+
+</d:body>
+
+</d:daml>
diff --git a/org/madore/damlengine/weblog-month-template.daml b/org/madore/damlengine/weblog-month-template.daml
new file mode 100644
index 0000000..f0cf0b3
--- /dev/null
+++ b/org/madore/damlengine/weblog-month-template.daml
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE d:daml [
+ <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+ %HTMLlat1;
+ <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+ %HTMLspecial;
+ <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+ %HTMLsymbol;
+ <!ENTITY uri-to-top "../">
+ <!ENTITY file.language "en">
+ <!ENTITY my-email "<d:email-despammed xmlns:d='http://www.madore.org/~david/NS/daml/'>david+www<d:email-at />madore<d:email-dot />org</d:email-despammed>">
+]>
+
+<d:daml xml:lang="&file.language;" uri-to-top="&uri-to-top;" xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.madore.org/~david/NS/daml/">
+
+<d:title>David Madore's WebLog</d:title>
+
+<d:meta-description>David Alexander Madore's WebLog / Diary</d:meta-description>
+
+<d:meta-keywords>David Alexander Madore, WebLog, diary</d:meta-keywords>
+
+<link rel="alternate" type="application/rss+xml" title="RSS" href="weblog.rss" />
+
+<d:body>
+
+<p>This WebLog is bilingual, some entries are in English and others
+are in French. A few of them have a version in either language.
+Other than that, the French entries are <em>not</em> translations of
+the English ones or vice versa. Of course, if you understand only
+English, the English entries ought to be quite understandable without
+reading the French ones.</p>
+
+<p xml:lang="fr">Ce WebLog est bilingue, certaines entrées sont en
+anglais et d'autres sont en français. Quelques-unes ont une version
+dans chaque langue. À part ça, les entrées en français <em>ne</em>
+sont <em>pas</em> des traductions de celles en anglais ou vice versa.
+Bien sûr, si vous ne comprenez que le français, les entrées en
+français devraient être assez compréhensibles sans lire celles en
+anglais.</p>
+
+<p>Note that the first entry comes <a
+d:wref="#d.2003-05-01.0001">last</a>! <span xml:lang="fr">Notez que la
+première entrée vient en <a
+d:wref="#d.2003-05-01.0001">dernier</a> !</span></p>
+
+<p><a href="weblog-index.html#index">Index of all entries &mdash;
+<span xml:lang="fr">Index de toutes les entrées</span></a> &mdash; <a
+href="weblog.rss" rel="alternate" type="application/rss+xml"
+title="RSS"><img src="&uri-to-top;images/xml.gif" alt="XML" width="36"
+height="14" /></a> (<abbr>RSS</abbr> 1.0) &mdash; <a
+href="http://www.madore.org/cgi-bin/comment.pl/lscomments">Recent
+comments &mdash; <span xml:lang="fr">Commentaires
+récents</span></a></p>
+
+<d:weblog-select />
+
+<p>Entries by month / <span xml:lang="fr">Entrées par mois</span>:</p>
+
+<table border="1">
+
+<tr><th>2011</th><td><a href="2011-01.html">Jan</a></td><td><a
+href="2011-02.html">Feb</a></td><td><a
+href="2011-03.html">Mar</a></td><td><a
+href="2011-04.html">Apr</a></td><td><a
+href="2011-05.html">May</a></td><td><a
+href="2011-06.html">Jun</a></td><td><a
+href="2011-07.html">Jul</a></td><td><a
+href="2011-08.html">Aug</a></td><td><a
+href="2011-09.html">Sep</a></td><td colspan="3"
+/></tr>
+
+<tr><th>2010</th><td><a href="2010-01.html">Jan</a></td><td><a
+href="2010-02.html">Feb</a></td><td><a
+href="2010-03.html">Mar</a></td><td><a
+href="2010-04.html">Apr</a></td><td><a
+href="2010-05.html">May</a></td><td><a
+href="2010-06.html">Jun</a></td><td><a
+href="2010-07.html">Jul</a></td><td><a
+href="2010-08.html">Aug</a></td><td><a
+href="2010-09.html">Sep</a></td><td><a
+href="2010-10.html">Oct</a></td><td><a
+href="2010-11.html">Nov</a></td><td><a
+href="2010-12.html">Dec</a></td></tr>
+
+<tr><th>2009</th><td><a href="2009-01.html">Jan</a></td><td><a
+href="2009-02.html">Feb</a></td><td><a
+href="2009-03.html">Mar</a></td><td><a
+href="2009-04.html">Apr</a></td><td><a
+href="2009-05.html">May</a></td><td><a
+href="2009-06.html">Jun</a></td><td><a
+href="2009-07.html">Jul</a></td><td><a
+href="2009-08.html">Aug</a></td><td><a
+href="2009-09.html">Sep</a></td><td><a
+href="2009-10.html">Oct</a></td><td><a
+href="2009-11.html">Nov</a></td><td><a
+href="2009-12.html">Dec</a></td></tr>
+
+<tr><th>2008</th><td><a href="2008-01.html">Jan</a></td><td><a
+href="2008-02.html">Feb</a></td><td><a
+href="2008-03.html">Mar</a></td><td><a
+href="2008-04.html">Apr</a></td><td><a
+href="2008-05.html">May</a></td><td><a
+href="2008-06.html">Jun</a></td><td><a
+href="2008-07.html">Jul</a></td><td><a
+href="2008-08.html">Aug</a></td><td><a
+href="2008-09.html">Sep</a></td><td><a
+href="2008-10.html">Oct</a></td><td><a
+href="2008-11.html">Nov</a></td><td><a
+href="2008-12.html">Dec</a></td></tr>
+
+<tr><th>2007</th><td><a href="2007-01.html">Jan</a></td><td><a
+href="2007-02.html">Feb</a></td><td><a
+href="2007-03.html">Mar</a></td><td><a
+href="2007-04.html">Apr</a></td><td><a
+href="2007-05.html">May</a></td><td><a
+href="2007-06.html">Jun</a></td><td><a
+href="2007-07.html">Jul</a></td><td><a
+href="2007-08.html">Aug</a></td><td><a
+href="2007-09.html">Sep</a></td><td><a
+href="2007-10.html">Oct</a></td><td><a
+href="2007-11.html">Nov</a></td><td><a
+href="2007-12.html">Dec</a></td></tr>
+
+<tr><th>2006</th><td><a href="2006-01.html">Jan</a></td><td><a
+href="2006-02.html">Feb</a></td><td><a
+href="2006-03.html">Mar</a></td><td><a
+href="2006-04.html">Apr</a></td><td><a
+href="2006-05.html">May</a></td><td><a
+href="2006-06.html">Jun</a></td><td><a
+href="2006-07.html">Jul</a></td><td><a
+href="2006-08.html">Aug</a></td><td><a
+href="2006-09.html">Sep</a></td><td><a
+href="2006-10.html">Oct</a></td><td><a
+href="2006-11.html">Nov</a></td><td><a
+href="2006-12.html">Dec</a></td></tr>
+
+<tr><th>2005</th><td><a href="2005-01.html">Jan</a></td><td><a
+href="2005-02.html">Feb</a></td><td><a
+href="2005-03.html">Mar</a></td><td><a
+href="2005-04.html">Apr</a></td><td><a
+href="2005-05.html">May</a></td><td><a
+href="2005-06.html">Jun</a></td><td><a
+href="2005-07.html">Jul</a></td><td><a
+href="2005-08.html">Aug</a></td><td><a
+href="2005-09.html">Sep</a></td><td><a
+href="2005-10.html">Oct</a></td><td><a
+href="2005-11.html">Nov</a></td><td><a
+href="2005-12.html">Dec</a></td></tr>
+
+<tr><th>2004</th><td><a href="2004-01.html">Jan</a></td><td><a
+href="2004-02.html">Feb</a></td><td><a
+href="2004-03.html">Mar</a></td><td><a
+href="2004-04.html">Apr</a></td><td><a
+href="2004-05.html">May</a></td><td><a
+href="2004-06.html">Jun</a></td><td><a
+href="2004-07.html">Jul</a></td><td><a
+href="2004-08.html">Aug</a></td><td><a
+href="2004-09.html">Sep</a></td><td><a
+href="2004-10.html">Oct</a></td><td><a
+href="2004-11.html">Nov</a></td><td><a
+href="2004-12.html">Dec</a></td></tr>
+
+<tr><th>2003</th><td colspan="4" /><td><a
+href="2003-05.html">May</a></td><td><a
+href="2003-06.html">Jun</a></td><td><a
+href="2003-07.html">Jul</a></td><td><a
+href="2003-08.html">Aug</a></td><td><a
+href="2003-09.html">Sep</a></td><td><a
+href="2003-10.html">Oct</a></td><td><a
+href="2003-11.html">Nov</a></td><td><a
+href="2003-12.html">Dec</a></td></tr>
+
+</table>
+
+</d:body>
+
+</d:daml>
diff --git a/org/madore/damlengine/weblog-recent-template.daml b/org/madore/damlengine/weblog-recent-template.daml
new file mode 100644
index 0000000..261686f
--- /dev/null
+++ b/org/madore/damlengine/weblog-recent-template.daml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE d:daml [
+ <!ENTITY % HTMLlat1 PUBLIC "-//W3C//ENTITIES Latin 1 for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
+ %HTMLlat1;
+ <!ENTITY % HTMLspecial PUBLIC "-//W3C//ENTITIES Special for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent">
+ %HTMLspecial;
+ <!ENTITY % HTMLsymbol PUBLIC "-//W3C//ENTITIES Symbols for XHTML//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent">
+ %HTMLsymbol;
+ <!ENTITY uri-to-top "../">
+ <!ENTITY file.language "en">
+ <!ENTITY my-email "<d:email-despammed xmlns:d='http://www.madore.org/~david/NS/daml/'>david+www<d:email-at />madore<d:email-dot />org</d:email-despammed>">
+]>
+
+<d:daml xml:lang="&file.language;" uri-to-top="&uri-to-top;" xmlns="http://www.w3.org/1999/xhtml" xmlns:d="http://www.madore.org/~david/NS/daml/">
+
+<d:title>David Madore's WebLog</d:title>
+
+<d:meta-description>David Alexander Madore's WebLog / Diary</d:meta-description>
+
+<d:meta-keywords>David Alexander Madore, WebLog, diary</d:meta-keywords>
+
+<link rel="alternate" type="application/rss+xml" title="RSS" href="weblog.rss" />
+
+<d:body>
+
+<p>This WebLog is bilingual, some entries are in English and others
+are in French. A few of them have a version in either language.
+Other than that, the French entries are <em>not</em> translations of
+the English ones or vice versa. Of course, if you understand only
+English, the English entries ought to be quite understandable without
+reading the French ones.</p>
+
+<p xml:lang="fr">Ce WebLog est bilingue, certaines entrées sont en
+anglais et d'autres sont en français. Quelques-unes ont une version
+dans chaque langue. À part ça, les entrées en français <em>ne</em>
+sont <em>pas</em> des traductions de celles en anglais ou vice versa.
+Bien sûr, si vous ne comprenez que le français, les entrées en
+français devraient être assez compréhensibles sans lire celles en
+anglais.</p>
+
+<p>Note that the first entry comes <a
+d:wref="#d.2003-05-01.0001">last</a>! <span xml:lang="fr">Notez que la
+première entrée vient en <a
+d:wref="#d.2003-05-01.0001">dernier</a> !</span></p>
+
+<p><a href="weblog-index.html#index">Index of all entries &mdash;
+<span xml:lang="fr">Index de toutes les entrées</span></a> &mdash; <a
+href="weblog.rss" rel="alternate" type="application/rss+xml"
+title="RSS"><img src="&uri-to-top;images/xml.gif" alt="XML" width="36"
+height="14" /></a> (<abbr>RSS</abbr> 1.0) &mdash; <a
+href="http://www.madore.org/cgi-bin/comment.pl/lscomments">Recent
+comments &mdash; <span xml:lang="fr">Commentaires
+récents</span></a></p>
+
+<d:weblog-select />
+
+</d:body>
+
+</d:daml>