From 0dd038405f5a906e6951084ae3bdcd4bab588cf8 Mon Sep 17 00:00:00 2001
From: Martin Goik <goik@hdm-stuttgart.de>
Date: Tue, 27 Oct 2015 07:44:52 +0100
Subject: [PATCH] catalog2xhtml example completed

---
 Doc/Sda1/dom.xml                              | 249 ++++++++++--------
 P/Sda1/Jdom/Catalog2Xhtml/.gitignore          |   5 +
 P/Sda1/Jdom/Catalog2Xhtml/pom.xml             |  31 +++
 .../src/main/java/dom/Article2Html.java       |  59 +++++
 .../src/main/java/dom/Article2HtmlDriver.java |  19 ++
 .../src/main/java/dom/HtmlTree.java           | 105 ++++++++
 .../src/main/java/sax/MySaxErrorHandler.java  |  44 ++++
 .../src/main/resources/catalog.xml            |   5 +
 P/pom.xml                                     |   1 +
 9 files changed, 410 insertions(+), 108 deletions(-)
 create mode 100644 P/Sda1/Jdom/Catalog2Xhtml/.gitignore
 create mode 100644 P/Sda1/Jdom/Catalog2Xhtml/pom.xml
 create mode 100644 P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/Article2Html.java
 create mode 100644 P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/Article2HtmlDriver.java
 create mode 100644 P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/HtmlTree.java
 create mode 100644 P/Sda1/Jdom/Catalog2Xhtml/src/main/java/sax/MySaxErrorHandler.java
 create mode 100644 P/Sda1/Jdom/Catalog2Xhtml/src/main/resources/catalog.xml

diff --git a/Doc/Sda1/dom.xml b/Doc/Sda1/dom.xml
index c3ec4a796..2c3ff9d92 100644
--- a/Doc/Sda1/dom.xml
+++ b/Doc/Sda1/dom.xml
@@ -364,30 +364,31 @@ public class CreateDoc {
 
     <titleabbrev>Parsing</titleabbrev>
 
-    <para>We already used a <acronym
-    xlink:href="http://www.saxproject.org">SAX</acronym> to parse an XML
-    document. Rather than handling <acronym
-    xlink:href="http://www.saxproject.org">SAX</acronym> events ourselves
-    these events may be used to construct a <acronym
-    xlink:href="http://www.w3.org/DOM">DOM</acronym> representation of our
-    document. This work is done by an instance of. We use our catalog example
-    from <xref linkend="simpleCatalog"/> as an introductory example.</para>
-
-    <para>We already noticed the need for an
-    <classname>org.xml.sax.ErrorHandler</classname> object during <acronym
+    <para>JDom uses <acronym
+    xlink:href="http://www.saxproject.org">SAX</acronym> for parsing XML
+    documents. Rather than handling <acronym
+    xlink:href="http://www.saxproject.org">SAX</acronym> events ourselves we
+    prefer a <acronym xlink:href="http://www.w3.org/DOM">DOM</acronym>
+    representation of our document. This is achieved by a <classname
+    xlink:href="http://www.jdom.org/docs/apidocs/org/jdom2/input/SAXBuilder.html">SAXBuilder</classname>
+    instance. Our <link linkend="simpleCatalog">simple catalog</link> serves
+    as an introductory example.</para>
+
+    <para>We already noticed the need for an <classname
+    xlink:href="http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html">ErrorHandler</classname>
+    instance during <acronym
     xlink:href="http://www.saxproject.org">SAX</acronym> processing. A
     <acronym xlink:href="http://www.w3.org/DOM">DOM</acronym> Parser requires
-    a similar type of Object in order to react to parsing errors in a
-    meaningful way. In principle a <acronym
+    a similar type of Object to communicate parsing errors in a meaningful
+    way. In principle a <acronym
     xlink:href="http://www.w3.org/DOM">DOM</acronym> parser implementor is
     free to choose his implementation but most implementations are based on
     top of a <acronym xlink:href="http://www.saxproject.org">SAX</acronym>
-    parser. For this reason it was natural to choose a <acronym
+    parser. For this reason it is natural choosing a <acronym
     xlink:href="http://www.w3.org/DOM">DOM</acronym> error handling interface
-    which is similar to a <acronym
-    xlink:href="http://www.saxproject.org">SAX</acronym>
-    <classname>org.xml.sax.ErrorHandler</classname>. The following code serves
-    the needs described before:</para>
+    similar to a <acronym xlink:href="http://www.saxproject.org">SAX</acronym>
+    <classname
+    xlink:href="http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html">ErrorHandler</classname>:</para>
 
     <figure xml:id="domTreeTraversal">
       <title>Accessing a XML Tree purely by <acronym
@@ -469,11 +470,15 @@ Article: 200W Stereo Amplifier, order number: 9921</programlisting>
           <question>
             <label>Simple HTML output</label>
 
-            <para>Instead of exporting simple text output in <xref
-            linkend="domTreeTraversal"/> we may also create HTML pages
-            like:</para>
+            <para>Instead of transforming our <link
+            linkend="simpleCatalog">simple catalog</link> into textual output
+            in <xref linkend="domTreeTraversal"/> we may also create <xref
+            linkend="glo_XHTML"/> pages like:</para>
 
-            <programlisting language="xml">&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;
+            <programlisting language="xml">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
+&lt;!-- Static content section--&gt; <co
+                xml:id="sda1CatalogStaticContentSection"/>
 &lt;html&gt;
   &lt;head&gt;
     &lt;title&gt;Available articles&lt;/title&gt;
@@ -482,9 +487,11 @@ Article: 200W Stereo Amplifier, order number: 9921</programlisting>
     &lt;h1&gt;Available articles&lt;/h1&gt;
     &lt;table&gt;
       &lt;tbody&gt;
-        &lt;tr&gt;
-          &lt;th align="left"&gt;Article Description&lt;/th&gt;&lt;th&gt;Order Number&lt;/th&gt;
-        &lt;/tr&gt;
+        &lt;tr /&gt;
+        &lt;th&gt;Article Description&lt;/th&gt;
+        &lt;th&gt;Order Number&lt;/th&gt;
+        &lt;!-- End of static, beginning of dynamic section--&gt; <co
+                xml:id="sda1CatalogDynamicContentSection"/>
         &lt;tr&gt;
           &lt;td align="left"&gt;<emphasis role="bold">Swinging headset</emphasis>&lt;/td&gt;&lt;td&gt;<emphasis
                 role="bold">3218</emphasis>&lt;/td&gt;
@@ -498,64 +505,88 @@ Article: 200W Stereo Amplifier, order number: 9921</programlisting>
   &lt;/body&gt;
 &lt;/html&gt;</programlisting>
 
-            <para>Rather then
+            <para>Rather just
             coding<code>...println(&lt;html&gt;\n\t&lt;head&gt;...)</code>
             statements you are expected to implement a more sophisticated
-            solution. We may combine<xref linkend="createDocModify"/> and
-            <xref linkend="createDocModify"/>. The idea is reading the XML
-            catalog instance as a <acronym
-            xlink:href="http://www.w3.org/DOM">DOM</acronym> as before. Then
-            construct a <emphasis>second</emphasis> <acronym
-            xlink:href="http://www.w3.org/DOM">DOM</acronym> tree for the
-            desired HTML output and fill in the article information from the
-            first <acronym xlink:href="http://www.w3.org/DOM">DOM</acronym>
-            tree accordingly.</para>
+            solution: We may combine<xref linkend="domTreeTraversal"/> and
+            <xref linkend="createDocModify"/>. The idea is parsing the <link
+            linkend="simpleCatalog">XML catalog instance</link> to a <xref
+            linkend="glo_Java"/> <acronym
+            xlink:href="http://www.w3.org/DOM">DOM</acronym> object as before.
+            Then construct a <emphasis>second</emphasis> <acronym
+            xlink:href="http://www.w3.org/DOM">DOM</acronym> tree representing
+            the desired HTML output and fill in the article information from
+            the first <acronym
+            xlink:href="http://www.w3.org/DOM">DOM</acronym> tree
+            accordingly.</para>
+
+            <tip>
+              <para>The desired <xref linkend="glo_HTML"/> output does contain
+              both static <coref linkend="sda1CatalogStaticContentSection"/>
+              and dynamic content <coref
+              linkend="sda1CatalogDynamicContentSection"/> with respect to a
+              given <xref linkend="glo_XML"/> <link
+              linkend="simpleCatalog">catalog input</link>.</para>
+
+              <para>The static content may be implemented as in <xref
+              linkend="simpleDomCreate"/>. Regarding dynamic content you'll
+              have to parse your <link linkend="simpleCatalog">catalog
+              input</link> and construct the <xref linkend="glo_HTML"/>'s
+              table lines in a similar fashion by iterating over
+              <code>&lt;item orderNo="..."&gt;...&lt;/item&gt;</code> elements
+              .</para>
+            </tip>
           </question>
 
           <answer>
+            <annotation>
+              <para>P/Sda1/Jdom/Catalog2Xhtml</para>
+            </annotation>
+
             <para>We introduce a class
-            <classname>solve.dom.HtmlTree</classname>:</para>
+            <classname>dom.HtmlTree</classname>:</para>
 
-            <programlisting language="java">package solve.dom;
-...
-package solve.dom;
+            <programlisting language="java">package dom;
 
 import java.io.IOException;
 import java.io.PrintStream;
 
 import org.jdom2.DocType;
-import org.jdom2.Document;
-import org.jdom2.Element;
-import org.jdom2.Text;
-import org.jdom2.output.Format;
-import org.jdom2.output.XMLOutputter;
-
-/**
- * Holding a HTML DOM to produce output.
- * @author goik
- */
+
+ ...
+
 public class HtmlTree {
 
-   private Document htmlOutput;
-   private Element tableBody;
+   private final Element tableBody;
 
+   /**
+    * Create a HTML skeleton (&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;...&amp;lt;body&amp;gt; ...&amp;lt;/body&amp;gt;&amp;lt;/head&amp;gt;
+    * to be filled in later by calling {@link #appendItem(String, String)}.
+    *
+    * @param titleText 
+    *   The document's title, e.g. "Available articles"
+    *   
+    * @param tableHeaderFields
+    *   The articles will be displayed as HTML table with these header fields
+    *   e.g. {"Article Description", "Order Number" }
+    */
    public HtmlTree(final String titleText,
          final String[] tableHeaderFields) { <co
                 linkends="programlisting_catalog2html_htmlskel_co"
                 xml:id="programlisting_catalog2html_htmlskel"/>
 
-      DocType doctype =  new DocType("html",
+      final DocType doctype =  new DocType("html",
             "-//W3C//DTD XHTML 1.0 Strict//EN", 
             "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
 
-      final Element htmlRoot = new Element("html"); <co
-                linkends="programlisting_catalog2html_tablehead_co"
-                xml:id="programlisting_catalog2html_tablehead"/>
-      htmlOutput = new Document(htmlRoot);
-      htmlOutput.setDocType(doctype);
-
-      // We create a HTML skeleton including an "empty" table
-      final Element head = new Element("head"),
+      final Element htmlRoot = new Element("html");
+      
+      final Document htmlOutput = new Document (htmlRoot, doctype);
+      htmlOutput.addContent(0, new Comment(" Static content section"));
+      
+      // We create a HTML skeleton including a yet empty table
+      final Element 
+            head = new Element("head"),
             body = new Element("body"),
             table = new Element("table");
 
@@ -567,17 +598,25 @@ public class HtmlTree {
 
       body.addContent(table);
 
-
       tableBody = new Element("tbody");
       table.addContent(tableBody);
       
-      final Element tr = tableBody.addContent(new Element("tr"));
+      final Element tr = new Element("tr");
+      tableBody.addContent(tr);
       for (final String headerField:  tableHeaderFields) {
          tr.addContent(new Element("th").addContent(new Text(headerField)));
       }
+      
+      tableBody.addContent(new Comment(" End of static, beginning of dynamic section"));
    }
    
-   public void appendItem(final String itemName, final String orderNo) {<co
+   /**
+    * Inserting an &amp;lt;item&amp;gt; as a new table row with two &amp;lt;td&amp;gt; elements.
+    * 
+    * @param itemName The item's name (e.g. Tennis racket)
+    * @param orderNo The item's order number
+    */
+   public void appendItem(final String itemName, final String orderNo) { <co
                 linkends="programlisting_catalog2html_insertproduct_co"
                 xml:id="programlisting_catalog2html_insertproduct"/>
       final Element tr = new Element("tr");
@@ -585,7 +624,11 @@ public class HtmlTree {
       tr.addContent(new Element("td").addContent(new Text(itemName)));
       tr.addContent(new Element("td").addContent(new Text(orderNo)));
    }
-   public void serialize(PrintStream out){
+   /**
+    * Serialize the HTML DOM to a stream
+    * @param out Output destination.
+    */
+   public void serialize(final PrintStream out){
 
       // Set formatting for the XML output
       final Format outFormat = Format.getPrettyFormat();
@@ -593,21 +636,19 @@ public class HtmlTree {
       // Serialize to console
       final XMLOutputter printer = new XMLOutputter(outFormat);
       try {
-         printer.output(htmlOutput, System.out);
+         printer.output(tableBody.getDocument(), System.out);
       } catch (IOException e) {
          e.printStackTrace();
          System.exit(1);
       }
    }
    /**
-    * @return the table's &lt;tbody&gt; element
+    * @return the table's &amp;lt;tbody&amp;gt; element
     */
    public Element getTable() {
       return tableBody;
    }
-}
-
-   </programlisting>
+}</programlisting>
 
             <calloutlist>
               <callout arearefs="programlisting_catalog2html_htmlskel"
@@ -624,7 +665,10 @@ public class HtmlTree {
     &lt;body&gt;
         &lt;h1&gt;Available articles&lt;/h1&gt;
         &lt;table&gt;
-            <emphasis role="bold">&lt;tbody&gt;</emphasis> &lt;!-- Data to be inserted here in next step --&gt;
+            <emphasis role="bold">&lt;tbody&gt;</emphasis>
+              &lt;th&gt;Article Description&lt;/th&gt;
+              &lt;th&gt;Order Number&lt;/th&gt;
+              &lt;!-- Data to be inserted here during &lt;item&gt; iteration --&gt;
             <emphasis role="bold">&lt;/tbody&gt;</emphasis>
         &lt;/table&gt;
     &lt;/body&gt;
@@ -634,29 +678,12 @@ public class HtmlTree {
                 point and thus invalid.</para>
               </callout>
 
-              <callout arearefs="programlisting_catalog2html_tablehead"
-                       xml:id="programlisting_catalog2html_tablehead_co">
-                <para>The table's header is appended but the actual data from
-                our two products is still missing:</para>
-
-                <programlisting language="xml">...
-&lt;h1&gt;Available articles&lt;/h1&gt;
- &lt;table&gt;
-   &lt;tbody&gt;
-    &lt;tr&gt;
-      &lt;th&gt;Article Description&lt;/th&gt;
-      &lt;th&gt;Order Number&lt;/th&gt;
-<emphasis role="bold">    &lt;/tr&gt;</emphasis>&lt;!-- Data to be appended after this row in next step --&gt;
-<emphasis role="bold">  &lt;/tbody&gt;</emphasis>
-&lt;/table&gt; ...</programlisting>
-              </callout>
-
               <callout arearefs="programlisting_catalog2html_insertproduct"
                        xml:id="programlisting_catalog2html_insertproduct_co">
                 <para>Calling
                 <methodname>solve.dom.HtmlTree.appendItem(String,String)</methodname>
-                once per product completes the creation of our HTML DOM
-                tree:</para>
+                once per <tag class="starttag">item</tag> completes the
+                creation of our HTML DOM tree:</para>
 
                 <programlisting language="xml">...             &lt;/tr&gt;
                 &lt;tr&gt;
@@ -674,13 +701,20 @@ public class HtmlTree {
             <para>The class <classname>solve.dom.Article2Html</classname>
             reads the catalog data:</para>
 
-            <programlisting language="java">package solve.dom;
-...
+            <programlisting language="java">package dom;
+
+import ...
+
 public class Article2Html {
    
   private final SAXBuilder builder = new SAXBuilder();
   private final HtmlTree htmlResult;
 
+  /**
+   * Instances of this class allow for reading XML catalogs and delegate
+   * XHTML transformation to a {@link HtmlTree} object,
+   * see {@link #process(String, PrintStream)}. 
+   */
   public Article2Html() {
     
      builder.setErrorHandler(new MySaxErrorHandler(System.out));
@@ -691,21 +725,21 @@ public class Article2Html {
         "Article Description", "Order Number" });
   }
 
-  /** Read an Xml catalog instance and insert product names among with
-   * their order numbers into the HTML DOM. Then serialize HTML tree 
-   * to a stream.
-   *
+  /** Read an Xml catalog instance and insert product names among with their order numbers
+   *  into a HTML DOM. Then serialize the resulting HTML tree to a stream. 
+   * 
    * @param 
    *   filename of the Xml source.
    * @param out
    *    The output stream for HTML serialization. 
-   * @throws IOException 
-   * @throws JDOMException
+   * @throws IOException In case filename cannot be opened
+   * @throws JDOMException Parsing error
+   * 
    */
-  public void process(final String filename, final PrintStream out)
-                          throws JDOMException, IOException{
+  public void process(final String filename, final PrintStream out) throws JDOMException, IOException{
     final List&lt;Element&gt; items = 
-      builder.build(filename).getRootElement().getChildren();
+//          builder.build(filename).getRootElement().getChildren();
+    builder.build(getClass().getClassLoader().getResource(filename)).getRootElement().getChildren();
     
     for (final Element item : items) { <co
                 linkends="programlisting_catalog2html_glue_prodloop_co"
@@ -763,19 +797,18 @@ public class Article2Html {
     <para>Due to script language support in a variety of browsers we may also
     use the <acronym xlink:href="http://www.w3.org/DOM">DOM</acronym> to
     implement client side event handling. As an example we <link
-    xlink:href="Sda1/Ref/src/tablesort.html">demonstrate</link> how a HTML
-    table can be made sortable by clicking on a header's column. The example
-    code along with the code description can be found at <uri
+    xlink:href="Sda1/Ref/src/tablesort.html">demonstrate</link> JavaScript
+    based sortable HTML table. The example code along with the code
+    description can be found at <uri
     xlink:href="http://www.kryogenix.org/code/browser/sorttable">http://www.kryogenix.org/code/browser/sorttable</uri>.</para>
 
-    <para>Quite remarkably there are only few ingredients required to enrich
-    an ordinary static HTML table with this functionality:</para>
+    <para>Few steps are required enriching a simple HTML table with this
+    functionality:</para>
 
     <itemizedlist>
       <listitem>
-        <para>An external Javascript library has to be included via
-        <code>&lt;script type="text/javascript"
-        src="sorttable.js"&gt;</code></para>
+        <para>Including an external Javascript library by <code>&lt;script
+        type="text/javascript" src="sorttable.js"&gt;</code></para>
       </listitem>
 
       <listitem>
diff --git a/P/Sda1/Jdom/Catalog2Xhtml/.gitignore b/P/Sda1/Jdom/Catalog2Xhtml/.gitignore
new file mode 100644
index 000000000..4ef0c0524
--- /dev/null
+++ b/P/Sda1/Jdom/Catalog2Xhtml/.gitignore
@@ -0,0 +1,5 @@
+/target/
+/.settings/
+A1.log
+.classpath
+.project
diff --git a/P/Sda1/Jdom/Catalog2Xhtml/pom.xml b/P/Sda1/Jdom/Catalog2Xhtml/pom.xml
new file mode 100644
index 000000000..c1eaf7761
--- /dev/null
+++ b/P/Sda1/Jdom/Catalog2Xhtml/pom.xml
@@ -0,0 +1,31 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>de.hdm-stuttgart.mi</groupId>
+		<artifactId>lecturenotes-pom</artifactId>
+		<version>1.0</version>
+
+		<relativePath>../../../pom.xml</relativePath>
+	</parent>
+
+	<groupId>de.hdm-stuttgart.mi.sda1</groupId>
+	<artifactId>catalog2xhtml</artifactId>
+	<version>0.8</version>
+	<packaging>jar</packaging>
+
+	<name>Catalog2xhtml</name>
+
+	<url>http://www.mi.hdm-stuttgart.de/freedocs</url>
+
+	<dependencies>
+
+		<dependency>
+			<groupId>org.jdom</groupId>
+			<artifactId>jdom2</artifactId>
+			<version>${org.jdom.jdom2.version}</version>
+		</dependency>
+
+	</dependencies>
+</project>
diff --git a/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/Article2Html.java b/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/Article2Html.java
new file mode 100644
index 000000000..b60675b10
--- /dev/null
+++ b/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/Article2Html.java
@@ -0,0 +1,59 @@
+package dom;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+
+import org.jdom2.Element;
+import org.jdom2.JDOMException;
+import org.jdom2.input.SAXBuilder;
+
+import sax.MySaxErrorHandler;
+
+
+/**
+ * This class may be used for transforming XML sources to
+ * XHTML by using {@link dom.HtmlTree}. 
+ *
+ */
+
+public class Article2Html {
+   
+  private final SAXBuilder builder = new SAXBuilder();
+  private final HtmlTree htmlResult;
+
+  /**
+   * Instances of this class allow for reading XML catalogs and delegate
+   * XHTML transformation to a {@link HtmlTree} object,
+   * see {@link #process(String, PrintStream)}. 
+   */
+  public Article2Html() {
+    
+     builder.setErrorHandler(new MySaxErrorHandler(System.out));
+    
+     htmlResult = new HtmlTree("Available articles", new String[] {
+        "Article Description", "Order Number" });
+  }
+
+  /** Read an Xml catalog instance and insert product names among with their order numbers
+   *  into a HTML DOM. Then serialize the resulting HTML tree to a stream. 
+   * 
+   * @param 
+   *   filename of the Xml source.
+   * @param out
+   *    The output stream for HTML serialization. 
+   * @throws IOException In case filename cannot be opened
+   * @throws JDOMException Parsing error
+   * 
+   */
+  public void process(final String filename, final PrintStream out) throws JDOMException, IOException{
+    final List<Element> items = 
+//          builder.build(filename).getRootElement().getChildren();
+    builder.build(getClass().getClassLoader().getResource(filename)).getRootElement().getChildren();
+    
+    for (final Element item : items) {
+       htmlResult.appendItem(item.getText(), item.getAttributeValue("orderNo"));
+    }
+    htmlResult.serialize(out);
+  }
+}
\ No newline at end of file
diff --git a/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/Article2HtmlDriver.java b/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/Article2HtmlDriver.java
new file mode 100644
index 000000000..0e67282ec
--- /dev/null
+++ b/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/Article2HtmlDriver.java
@@ -0,0 +1,19 @@
+package dom;
+
+/**
+ * This driver class simply instantiates an {@link Article2Html}object and
+ * initiates the parsing process. The resulting HTML output is written to
+ * stdout.
+ * 
+ * @author goik
+ *  
+ */
+public class Article2HtmlDriver {
+  /** @param argv unused
+   *  @throws Exception Inaccessible file or corrupt content
+   */
+  public static void main(String[] argv) throws Exception {
+    final Article2Html a2h = new Article2Html();
+    a2h.process("catalog.xml", System.out);
+  }
+}
\ No newline at end of file
diff --git a/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/HtmlTree.java b/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/HtmlTree.java
new file mode 100644
index 000000000..6cddabf0c
--- /dev/null
+++ b/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/dom/HtmlTree.java
@@ -0,0 +1,105 @@
+package dom;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.jdom2.Comment;
+import org.jdom2.DocType;
+import org.jdom2.Document;
+import org.jdom2.Element;
+import org.jdom2.Text;
+import org.jdom2.output.Format;
+import org.jdom2.output.XMLOutputter;
+
+/**
+ * Represent a XHTML DOM for output generation.
+ * @author goik
+ */
+public class HtmlTree {
+
+   private final Element tableBody;
+
+   /**
+    * Create a HTML skeleton (&lt;html&gt;&lt;head&gt;...&lt;body&gt; ...&lt;/body&gt;&lt;/head&gt;
+    * to be filled in later by calling {@link #appendItem(String, String)}.
+    *
+    * @param titleText 
+    *   The document's title, e.g. "Available articles"
+    *   
+    * @param tableHeaderFields
+    *   The articles will be displayed as HTML table with these header fields
+    *   e.g. {"Article Description", "Order Number" }
+    */
+   public HtmlTree(final String titleText,
+         final String[] tableHeaderFields) {
+
+      final DocType doctype =  new DocType("html",
+            "-//W3C//DTD XHTML 1.0 Strict//EN", 
+            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
+
+      final Element htmlRoot = new Element("html");
+      
+      final Document htmlOutput = new Document (htmlRoot, doctype);
+      htmlOutput.addContent(0, new Comment(" Static content section"));
+      
+      // We create a HTML skeleton including a yet empty table
+      final Element 
+            head = new Element("head"),
+            body = new Element("body"),
+            table = new Element("table");
+
+      htmlRoot.addContent(head).addContent(body);
+
+      head.addContent(new Element("title").addContent(new Text(titleText)));
+      
+      body.addContent(new Element("h1").addContent(new Text(titleText))).addContent(table);
+
+      tableBody = new Element("tbody");
+      table.addContent(tableBody);
+      
+      final Element tr = new Element("tr");
+      tableBody.addContent(tr);
+      for (final String headerField:  tableHeaderFields) {
+         tr.addContent(new Element("th").addContent(new Text(headerField)));
+      }
+      
+      tableBody.addContent(new Comment(" End of static, beginning of dynamic section"));
+   }
+   
+   /**
+    * Inserting an &lt;item&gt; as a new table row with two &lt;td&gt; elements.
+    * 
+    * @param itemName The item's name (e.g. Tennis racket)
+    * @param orderNo The item's order number
+    */
+   public void appendItem(final String itemName, final String orderNo) {
+      final Element tr = new Element("tr");
+      tableBody.addContent(tr);
+      tr.addContent(new Element("td").addContent(new Text(itemName)));
+      tr.addContent(new Element("td").addContent(new Text(orderNo)));
+   }
+   /**
+    * Serialize the HTML DOM to a stream
+    * @param out Output destination.
+    */
+   public void serialize(final PrintStream out){
+
+      // Set formatting for the XML output
+      final Format outFormat = Format.getPrettyFormat();
+
+      // Serialize to console
+      final XMLOutputter printer = new XMLOutputter(outFormat);
+      try {
+         printer.output(tableBody.getDocument(), System.out);
+      } catch (IOException e) {
+         e.printStackTrace();
+         System.exit(1);
+      }
+   }
+   /**
+    * @return the table's &lt;tbody&gt; element
+    */
+   public Element getTable() {
+      return tableBody;
+   }
+}
\ No newline at end of file
diff --git a/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/sax/MySaxErrorHandler.java b/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/sax/MySaxErrorHandler.java
new file mode 100644
index 000000000..cf66b9435
--- /dev/null
+++ b/P/Sda1/Jdom/Catalog2Xhtml/src/main/java/sax/MySaxErrorHandler.java
@@ -0,0 +1,44 @@
+package sax;
+
+import java.io.PrintStream;
+
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+
+
+/**
+ * 
+ * @author goik
+ */
+public class MySaxErrorHandler implements ErrorHandler {
+   
+   private PrintStream out; //The error handler's output goes here
+
+   private String getParseExceptionInfo //Returns a string describing
+   (SAXParseException ex) { //parse exception details.
+     return "Error '" + ex.getMessage() + "' at line " + 
+      ex.getLineNumber() + ", column " +
+         ex.getColumnNumber();
+   }
+
+   /**
+    * @param out Report's destination
+    */
+   public MySaxErrorHandler(final PrintStream out) {
+     this.out = out;
+   }
+   @Override
+   public void warning(SAXParseException exception) throws SAXException {
+      out.print("Warning:" + getParseExceptionInfo(exception));
+   }
+   @Override
+   public void error(SAXParseException exception) throws SAXException {
+      out.print("Error:" + getParseExceptionInfo(exception));
+   }
+   @Override
+   public void fatalError(SAXParseException exception) throws SAXException {
+      out.print("Fatal error:" + getParseExceptionInfo(exception));
+   }
+}
\ No newline at end of file
diff --git a/P/Sda1/Jdom/Catalog2Xhtml/src/main/resources/catalog.xml b/P/Sda1/Jdom/Catalog2Xhtml/src/main/resources/catalog.xml
new file mode 100644
index 000000000..2fd148d25
--- /dev/null
+++ b/P/Sda1/Jdom/Catalog2Xhtml/src/main/resources/catalog.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<articlelist>
+  <article orderNo="t11" >Dungeons and Dragons</article>
+  <article orderNo="t12" >Professional glider</article>
+</articlelist>
diff --git a/P/pom.xml b/P/pom.xml
index c4210a94e..7096ebe8f 100644
--- a/P/pom.xml
+++ b/P/pom.xml
@@ -119,6 +119,7 @@
     <module>Sda1/InsertGui/V4</module>
 
 
+    <module>Sda1/Jdom/Catalog2Xhtml</module>
     <module>Sda1/Jdom/StructTitle</module>
 
     <module>Sda1/Jpa/HibernateStandalone</module>
-- 
GitLab