From c7531ef1e6de036de050f6bcff8d63032766c58c Mon Sep 17 00:00:00 2001
From: Martin Goik <goik@hdm-stuttgart.de>
Date: Sun, 7 Dec 2014 19:23:29 +0100
Subject: [PATCH] New exercise converting a memo to html

---
 .../SaxMemo2Html/Saxmemo2html/.gitignore      |  4 +
 Sda1/Etest/SaxMemo2Html/Saxmemo2html/pom.xml  | 98 +++++++++++++++++++
 .../mi/sda1/saxhtml/v1/Driver.java            | 15 +++
 .../mi/sda1/saxhtml/v1/Memo2Html.java         | 51 ++++++++++
 .../mi/sda1/saxhtml/v1/Memo2HtmlHandler.java  | 63 ++++++++++++
 .../mi/sda1/saxhtml/v1/MyErrorHandler.java    | 25 +++++
 .../mi/sda1/saxhtml/v2/Driver.java            | 15 +++
 .../mi/sda1/saxhtml/v2/Memo2Html.java         | 53 ++++++++++
 .../mi/sda1/saxhtml/v2/Memo2HtmlHandler.java  | 64 ++++++++++++
 .../src/main/resources/.gitignore             |  2 +
 .../src/main/resources/log4j2.xml             | 21 ++++
 .../Saxmemo2html/src/main/resources/memo.xml  |  8 ++
 .../src/main/resources/memo.xml.1.sample.html | 15 +++
 .../src/main/resources/memo.xml.2.sample.html | 20 ++++
 .../sda1/saxhtml/v1/test/ConversionTest.java  | 63 ++++++++++++
 .../sda1/saxhtml/v2/test/ConversionTest.java  | 74 ++++++++++++++
 .../de/testing/dom/AssertXpathResult.java     | 18 ++++
 .../de/testing/dom/DomAssert.java             | 91 +++++++++++++++++
 18 files changed, 700 insertions(+)
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/.gitignore
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/pom.xml
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Driver.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Memo2Html.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Memo2HtmlHandler.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/MyErrorHandler.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Driver.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Memo2Html.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Memo2HtmlHandler.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/.gitignore
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/log4j2.xml
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml.1.sample.html
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml.2.sample.html
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/sda1/saxhtml/v1/test/ConversionTest.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/sda1/saxhtml/v2/test/ConversionTest.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/testing/dom/AssertXpathResult.java
 create mode 100644 Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/testing/dom/DomAssert.java

diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/.gitignore b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/.gitignore
new file mode 100644
index 000000000..a1c3ab4d0
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/.gitignore
@@ -0,0 +1,4 @@
+/target/
+/.settings/
+.classpath
+.project
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/pom.xml b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/pom.xml
new file mode 100644
index 000000000..c04167eb8
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/pom.xml
@@ -0,0 +1,98 @@
+<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>
+  
+  <groupId>de.hdm_stuttgart.mi.sda1.saxhtml</groupId>
+  <artifactId>saxmemo2html</artifactId>
+  <version>1.0</version>
+
+  <packaging>jar</packaging>
+  
+  <name>SaxMemo2Hhtml</name>
+
+  <!--Fixme: Add a sensible project related domain here -->
+  <url>http://www.mi.hdm-stuttgart.de/freedocs</url>
+  
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  
+  <dependencies>
+  
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.11</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.jdom</groupId>
+      <artifactId>jdom2</artifactId>
+      <version>2.0.5</version>
+    </dependency>
+	
+	<dependency>
+	  <groupId>jaxen</groupId>
+      <artifactId>jaxen</artifactId>
+      <version>1.1.4</version>
+	</dependency>    
+
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <version>2.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <version>2.1</version>
+    </dependency>
+    
+  </dependencies>
+  
+  <build>
+    <plugins>
+
+        <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+
+    <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.10.1</version>
+        <configuration/>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>2.3</version>
+        <configuration>
+          <transformers>
+            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+              <manifestEntries>
+                <Main-Class>de.hdm_stuttgart.de.saxstandard.App</Main-Class>
+              </manifestEntries>
+            </transformer>
+          </transformers>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      
+    </plugins>
+  </build>
+</project>
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Driver.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Driver.java
new file mode 100644
index 000000000..78c63536f
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Driver.java
@@ -0,0 +1,15 @@
+package de.hdm_stuttgart.mi.sda1.saxhtml.v1;
+
+/** Driver */
+public class Driver {
+  /** @param argv unused */
+  public static void main(String argv[]) {
+    try{
+    Memo2Html memo2html = new Memo2Html(System.out);
+    memo2html.parse("src/main/resources/memo.xml");
+
+    } catch (Exception e){
+      e.printStackTrace(System.err);
+    }
+  }
+}
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Memo2Html.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Memo2Html.java
new file mode 100644
index 000000000..1e0d749a6
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Memo2Html.java
@@ -0,0 +1,51 @@
+package de.hdm_stuttgart.mi.sda1.saxhtml.v1;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+/** Parser, content- and error handler assembly */
+public class Memo2Html {
+
+	private final XMLReader xmlReader;
+	private final Memo2HtmlHandler eventHandler;
+	private final MyErrorHandler errorHandler = new MyErrorHandler();
+
+	/**
+	 * @param out
+	 * @throws SAXException
+	 *             Parsing may fail.
+	 * @throws ParserConfigurationException
+	 *             Unable to instantiate parser.
+	 */
+	public Memo2Html(final PrintStream out) throws SAXException,
+			ParserConfigurationException {
+		final SAXParserFactory saxPf = SAXParserFactory.newInstance();
+		final SAXParser saxParser = saxPf.newSAXParser();
+		xmlReader = saxParser.getXMLReader();
+
+		eventHandler = new Memo2HtmlHandler(out);
+		xmlReader.setContentHandler(eventHandler);
+		xmlReader.setErrorHandler(errorHandler);
+	}
+
+	/**
+	 * Parse an existing memo instance and create HTML output.
+	 * 
+	 * @param uri
+	 *            The resource to be parsed
+	 * @throws IOException
+	 *             Access related problems
+	 * @throws SAXException
+	 *             Parsing may fail
+	 */
+	public void parse(final String uri) throws IOException, SAXException {
+		xmlReader.parse(uri);
+	}
+}
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Memo2HtmlHandler.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Memo2HtmlHandler.java
new file mode 100644
index 000000000..f930bebb0
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/Memo2HtmlHandler.java
@@ -0,0 +1,63 @@
+package de.hdm_stuttgart.mi.sda1.saxhtml.v1;
+
+import java.io.PrintStream;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ * Turning &lt;memo&gt; documents to HTML as being shown in sample document memo.xml.1.sample.html 
+ *
+ */
+public class Memo2HtmlHandler implements ContentHandler {
+
+	private final PrintStream out;
+
+	/**
+	 * @param out
+	 */
+	public Memo2HtmlHandler(final PrintStream out) {
+		this.out = out;
+	}
+
+	@Override
+	public void startDocument() throws SAXException {
+		// TODO Auto-generated method stub
+		out.print("<html>");
+	}
+
+	@Override
+	public void endDocument() throws SAXException {
+		// TODO Auto-generated method stub
+		out.print("</html>");
+	}
+
+	@Override
+	public void startElement(String uri, String localName, String qName,
+			Attributes atts) throws SAXException {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public void endElement(String uri, String localName, String qName)
+			throws SAXException {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public void characters(char[] ch, int start, int length)
+			throws SAXException {
+		// TODO Auto-generated method stub
+	}
+
+	// You probably don't need the following callbacks.
+	//
+	@Override public void setDocumentLocator(Locator locator) {}
+	@Override public void startPrefixMapping(String prefix, String uri) throws SAXException {}
+	@Override public void endPrefixMapping(String prefix) throws SAXException {}
+	@Override public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {}
+	@Override public void processingInstruction(String target, String data) throws SAXException {}
+	@Override public void skippedEntity(String name) throws SAXException {}
+}
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/MyErrorHandler.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/MyErrorHandler.java
new file mode 100644
index 000000000..1fce5e72b
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v1/MyErrorHandler.java
@@ -0,0 +1,25 @@
+package de.hdm_stuttgart.mi.sda1.saxhtml.v1;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ErrorHandler;
+
+/** Handle parsing errors */
+public class MyErrorHandler implements ErrorHandler {
+  /** @see ErrorHandler#warning(SAXParseException) */
+  public void warning(SAXParseException e) {
+    System.err.println("[Warning]" + getLocationString(e));
+  }
+  /** @see ErrorHandler#error(SAXParseException) */
+  public void error(SAXParseException e) {
+    System.err.println("[Error]" + getLocationString(e));
+  }
+  /** @see ErrorHandler#fatalError(SAXParseException) */
+  public void fatalError(SAXParseException e) throws SAXException{
+    System.err.println("[Fatal Error]" + getLocationString(e));
+  }
+  private String getLocationString(SAXParseException e) {
+    return " line " + e.getLineNumber() +
+    	", column " + e.getColumnNumber()+ ":" +  e.getMessage();
+  }
+}
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Driver.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Driver.java
new file mode 100644
index 000000000..c36643969
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Driver.java
@@ -0,0 +1,15 @@
+package de.hdm_stuttgart.mi.sda1.saxhtml.v2;
+
+/** Driver */
+public class Driver {
+  /** @param argv unused */
+  public static void main(String argv[]) {
+    try{
+    Memo2Html memo2html = new Memo2Html(System.out);
+    memo2html.parse("src/main/resources/memo.xml");
+
+    } catch (Exception e){
+      e.printStackTrace(System.err);
+    }
+  }
+}
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Memo2Html.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Memo2Html.java
new file mode 100644
index 000000000..5d0dcf1ba
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Memo2Html.java
@@ -0,0 +1,53 @@
+package de.hdm_stuttgart.mi.sda1.saxhtml.v2;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+import de.hdm_stuttgart.mi.sda1.saxhtml.v1.MyErrorHandler;
+
+/** Parser, content- and error handler assembly */
+public class Memo2Html {
+
+	private final XMLReader xmlReader;
+	private final Memo2HtmlHandler eventHandler;
+	private final MyErrorHandler errorHandler = new MyErrorHandler();
+
+	/**
+	 * @param out Write output to stream
+	 * @throws SAXException
+	 *             Parsing may fail.
+	 * @throws ParserConfigurationException
+	 *             Unable to instantiate parser.
+	 */
+	public Memo2Html(final PrintStream out) throws SAXException,
+			ParserConfigurationException {
+		final SAXParserFactory saxPf = SAXParserFactory.newInstance();
+		final SAXParser saxParser = saxPf.newSAXParser();
+		xmlReader = saxParser.getXMLReader();
+
+		eventHandler = new Memo2HtmlHandler(out);
+		xmlReader.setContentHandler(eventHandler);
+		xmlReader.setErrorHandler(errorHandler);
+	}
+
+	/**
+	 * Parse an existing memo instance and create HTML output.
+	 * 
+	 * @param uri
+	 *            The resource to be parsed
+	 * @throws IOException
+	 *             Access related problems
+	 * @throws SAXException
+	 *             Parsing may fail
+	 */
+	public void parse(final String uri) throws IOException, SAXException {
+		xmlReader.parse(uri);
+	}
+}
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Memo2HtmlHandler.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Memo2HtmlHandler.java
new file mode 100644
index 000000000..99ce8c38f
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/java/de/hdm_stuttgart/mi/sda1/saxhtml/v2/Memo2HtmlHandler.java
@@ -0,0 +1,64 @@
+package de.hdm_stuttgart.mi.sda1.saxhtml.v2;
+
+import java.io.PrintStream;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Turning &lt;memo&gt; documents to HTML
+ *
+ */
+public class Memo2HtmlHandler extends DefaultHandler {
+
+	private final PrintStream out;
+
+	/**
+	 * @param out
+	 *            Write output to stream
+	 */
+	public Memo2HtmlHandler(final PrintStream out) {
+		this.out = out;
+	}
+
+	@Override
+	public void startDocument() throws SAXException {
+		// TODO Auto-generated method stub
+		out.print("<html>");
+	}
+
+	@Override
+	public void endDocument() throws SAXException {
+		// TODO Auto-generated method stub
+		out.print("</html>");
+	}
+
+	@Override
+	public void startElement(String uri, String localName, String qName,
+			Attributes atts) throws SAXException {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public void endElement(String uri, String localName, String qName)
+			throws SAXException {
+		// TODO Auto-generated method stub
+	}
+
+	@Override
+	public void characters(char[] ch, int start, int length)
+			throws SAXException {
+		// TODO Auto-generated method stub
+	}
+
+	// You probably don't need the following callbacks.
+	//
+	@Override public void setDocumentLocator(Locator locator) {}
+	@Override public void startPrefixMapping(String prefix, String uri) throws SAXException {}
+	@Override public void endPrefixMapping(String prefix) throws SAXException {}
+	@Override public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {}
+	@Override public void processingInstruction(String target, String data) throws SAXException {}
+	@Override public void skippedEntity(String name) throws SAXException {}
+}
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/.gitignore b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/.gitignore
new file mode 100644
index 000000000..472b549de
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/.gitignore
@@ -0,0 +1,2 @@
+/memo.xml.1.html
+/memo.xml.2.html
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/log4j2.xml b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/log4j2.xml
new file mode 100644
index 000000000..ffeb6ae18
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/log4j2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration>
+    <Appenders>
+        <File name="A1" fileName="A1.log" append="false">
+            <PatternLayout pattern="%t %-5p %c{2} - %m%n"/>
+        </File>
+        <Console name="STDOUT" target="SYSTEM_OUT">
+            <PatternLayout pattern="%C{2} (%F:%L) - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+
+        <!-- You my want to define class or package level per-logger rules -->
+        <Logger name="de.hdm_stuttgart.de.saxstandard.App" level="debug">
+            <AppenderRef ref="A1"/>
+        </Logger>
+        <Root level="debug">
+            <AppenderRef ref="STDOUT"/>
+        </Root>
+    </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml
new file mode 100644
index 000000000..bb23c32cb
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<memo>
+  <from>M. Goik</from>
+  <to>B. King</to>
+  <to>A. June</to>
+  <subject>Best wishes</subject>
+  <content>Hi all, congratulations to your splendid party</content>
+</memo>
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml.1.sample.html b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml.1.sample.html
new file mode 100644
index 000000000..9157fb5aa
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml.1.sample.html
@@ -0,0 +1,15 @@
+<html>
+  <head>
+    <title>Memo message</title>
+  </head>
+  <body>
+    <h2>Message from <strong>M. Goik</strong></h2>
+    <h2>Recipients:</h2>
+    <ul>
+      <li>B. King</li>
+      <li>A. June</li>
+    </ul>
+    <h2>Subject: Best wishes</h2>
+    <p>Hi all, congratulations to your splendid party</p>
+  </body>
+</html>
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml.2.sample.html b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml.2.sample.html
new file mode 100644
index 000000000..85659d988
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/main/resources/memo.xml.2.sample.html
@@ -0,0 +1,20 @@
+<html>
+  <head><title>Memo from M. Goik</title></head>
+  <body>
+    <h2>Subject:Best wishes</h2>
+    <dl>
+      <dt>Sender:</dt>
+      <dd>M. Goik</dd>
+      <dt>Recipients:</dt>
+      <dd>
+        <ul>
+          <li>B. King</li>
+          <li>A. June</li>
+        </ul>
+      </dd>
+    </dl>
+    <h2>Subject: Best wishes</h2>
+    <p>Hi all, congratulations to your splendid party</p>
+    <p>End of message from <strong>M. Goik</strong></p>
+  </body>
+</html>
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/sda1/saxhtml/v1/test/ConversionTest.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/sda1/saxhtml/v1/test/ConversionTest.java
new file mode 100644
index 000000000..c4b3c305d
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/sda1/saxhtml/v1/test/ConversionTest.java
@@ -0,0 +1,63 @@
+package de.hdm_stuttgart.de.sda1.saxhtml.v1.test;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.jdom2.Element;
+import org.jdom2.JDOMException;
+import org.jdom2.input.SAXBuilder;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import de.hdm_stuttgart.de.testing.dom.DomAssert;
+import de.hdm_stuttgart.mi.sda1.saxhtml.v1.Memo2Html;
+
+/**
+ * Unit testing XML to HTML output
+ */
+@SuppressWarnings("javadoc")
+public class ConversionTest {
+   
+   final static String
+      xmlInputFileName = "src/main/resources/memo.xml",
+      htmlOutputFileName = xmlInputFileName + ".1.html";
+   
+   static Element htmlRootElement; 
+   
+   @BeforeClass public static void init()
+         throws JDOMException, SAXException, ParserConfigurationException, IOException {
+      
+         final PrintStream out = new PrintStream(htmlOutputFileName);
+         final Memo2Html memo2html = new Memo2Html(out);
+         memo2html.parse(xmlInputFileName);
+         final SAXBuilder parser = new SAXBuilder();
+         htmlRootElement = parser.build(htmlOutputFileName).getRootElement();
+         out.close();
+   }
+   
+   @Test public void testSenderInHeader() {
+      DomAssert.assertSingleNodeContent("<title>Memo message</title> must be the only child of <head>", htmlRootElement, "head/*", "title", "Memo message");
+   }
+   @Test public void testFrom() {
+      DomAssert.assertSingleNodeContent("<strong>M. Goik</strong> must appear within first <h2> child of <body>",
+            htmlRootElement, "body/h2[1]/strong", "strong", "M. Goik");
+   }
+   @Test public void testNumberfRecipients() {
+      DomAssert.assertNumberOfNodes("Two <li> elements required matching two recipients", htmlRootElement, "body/ul/li", 2);
+   }
+   @Test public void testSecondRecipient() {
+      DomAssert.assertSingleNodeContent("Second recipient must be <li>A. June</li>",
+            htmlRootElement, "body/ul/li[2]", "li", "A. June");
+   }
+   @Test public void testSubject() {
+      DomAssert.assertSingleNodeContent("<h2>Subject: Best wishes</h2> must appear as first child of <body>",
+            htmlRootElement, "body/*[4]", "h2", "Subject: Best wishes");
+   }
+   @Test public void testContent() {
+      DomAssert.assertSingleNodeContent("Last child of <body> must be content",
+            htmlRootElement, "body/*[5]", "p", "Hi all, congratulations to your splendid party");
+   }
+}
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/sda1/saxhtml/v2/test/ConversionTest.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/sda1/saxhtml/v2/test/ConversionTest.java
new file mode 100644
index 000000000..b7ed83106
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/sda1/saxhtml/v2/test/ConversionTest.java
@@ -0,0 +1,74 @@
+package de.hdm_stuttgart.de.sda1.saxhtml.v2.test;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.jdom2.Element;
+import org.jdom2.JDOMException;
+import org.jdom2.input.SAXBuilder;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import de.hdm_stuttgart.de.testing.dom.DomAssert;
+import de.hdm_stuttgart.mi.sda1.saxhtml.v2.Memo2Html;
+
+/**
+ * Turning &lt;memo&gt; documents to HTML as being shown in sample document memo.xml.2.sample.html 
+
+ */
+@SuppressWarnings("javadoc")
+public class ConversionTest {
+
+	final static String
+	xmlInputFileName = "src/main/resources/memo.xml",
+	htmlOutputFileName = xmlInputFileName + ".2.html";
+
+	static Element htmlRootElement; 
+
+	/**
+	 * @throws JDOMException
+	 * @throws SAXException
+	 * @throws ParserConfigurationException
+	 * @throws IOException
+	 */
+	@BeforeClass public static void init()
+			throws JDOMException, SAXException, ParserConfigurationException, IOException {
+
+		final PrintStream out = new PrintStream(htmlOutputFileName);
+		final Memo2Html memo2html = new Memo2Html(out);
+		memo2html.parse(xmlInputFileName);
+		final SAXBuilder parser = new SAXBuilder();
+		htmlRootElement = parser.build(htmlOutputFileName).getRootElement();
+		out.close();
+	}
+
+	@Test public void testSenderInHeader() {
+		DomAssert.assertSingleNodeContent("<title>Memo from M. Goik</title> must be child of <head>", htmlRootElement, "head/title", "Memo from M. Goik");
+	}
+	@Test public void testNumberfRecipients() {
+		DomAssert.assertNumberOfNodes("There should be two <li> elements matching two recipients", htmlRootElement, "body/dl/dd/ul/li", 2);
+	}
+	@Test public void testH1MemoSubjectMessage() {
+		DomAssert.assertSingleNodeContent("<h2>Subject:Best wishes</h2> must appear as first child of <body>",
+				htmlRootElement, "body/*[1]", "h2", "Subject:Best wishes");
+	}
+	@Test public void testSenderBeforeRecipientList() {
+		DomAssert.assertSingleNodeContent("<dd>M. Goik</dd> must appear as second child  of the list of recipients",
+				htmlRootElement, "body/dl/*[2]", "dd", "M. Goik");
+	}
+	@Test public void testMemoContent() {
+		DomAssert.assertSingleNodeContent("content must appear as second <p> child after recipient list in <body>",
+				htmlRootElement, "body/dl/following-sibling::*[2]", "p", "Hi all, congratulations to your splendid party");
+	}
+	@Test public void testLastParagraph() {
+		DomAssert.assertNumberOfNodes("Expecting two <p> children of <body>",
+				htmlRootElement, "body/*[name(.)='p']", 2);
+	}
+	@Test public void testSenderAtFoot() {
+		DomAssert.assertSingleNodeContent("<strong>M. Goik</strong> must appear inside a <p> immediately following the list of recipients",
+				htmlRootElement, "body/dl/following-sibling::*[1]", "h2", "Subject: Best wishes");
+	}
+}
\ No newline at end of file
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/testing/dom/AssertXpathResult.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/testing/dom/AssertXpathResult.java
new file mode 100644
index 000000000..d36d86304
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/testing/dom/AssertXpathResult.java
@@ -0,0 +1,18 @@
+package de.hdm_stuttgart.de.testing.dom;
+
+/**
+ * @author goik
+ *
+ */
+public class AssertXpathResult extends AssertionError {
+
+	private static final long serialVersionUID = -1369600480719379445L;
+
+	/**
+	 * @param msg
+	 */
+	public AssertXpathResult(String msg) {
+		super(msg);
+	}
+
+}
diff --git a/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/testing/dom/DomAssert.java b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/testing/dom/DomAssert.java
new file mode 100644
index 000000000..02f9ba854
--- /dev/null
+++ b/Sda1/Etest/SaxMemo2Html/Saxmemo2html/src/test/java/de/hdm_stuttgart/de/testing/dom/DomAssert.java
@@ -0,0 +1,91 @@
+package de.hdm_stuttgart.de.testing.dom;
+
+import java.util.List;
+
+import org.jdom2.Element;
+import org.jdom2.xpath.XPathExpression;
+import org.jdom2.xpath.XPathFactory;
+
+/**
+ * @author goik
+ *
+ */
+public class DomAssert {
+   
+   
+   final static XPathFactory xpf = XPathFactory.instance();
+
+   /**
+ * @param msg
+ * @param context
+ * @param xpath
+ * @param expectedNodeCount
+ */
+public static void assertNumberOfNodes(final String msg, final Element context, final String xpath, int expectedNodeCount) {
+      
+      @SuppressWarnings({ "unchecked", "rawtypes" })
+      final XPathExpression<Element> xpathExpr = (XPathExpression<Element>) (XPathExpression) xpf.compile(xpath);
+
+      final List<Element> matchedNodes = xpathExpr.evaluate(context);
+      
+      if (expectedNodeCount != matchedNodes.size()) {
+         throw new AssertXpathResult(msg + "\nExpected " + expectedNodeCount + " node" + (expectedNodeCount == 1? "":"s") + " for xpath '" + xpath + 
+               "' but found " + matchedNodes.size());
+      }
+   } 
+   
+   /**
+ * @param msg
+ * @param context
+ * @param xpath
+ * @param expectedContent
+ */
+public static void assertSingleNodeContent(final String msg, final Element context, final String xpath, String expectedContent) {
+      
+      @SuppressWarnings({ "unchecked", "rawtypes" })
+      final XPathExpression<Element> xpathExpr = (XPathExpression<Element>) (XPathExpression) xpf.compile(xpath);
+
+      final List<Element> matchedNodes = xpathExpr.evaluate(context);
+      if (1 == matchedNodes.size()) {
+         final String content = matchedNodes.get(0).getValue();
+         if (!content.equals(expectedContent)) {
+            throw new AssertXpathResult(msg + "\nExpected content '" + expectedContent + "' for xpath '" + xpath + "' but found '" + content + "'");
+         }
+      } else {
+         throw new AssertXpathResult("\nExactly one node expected for xpath '" + xpath + "' but found " + matchedNodes.size());
+      }
+   }
+
+   /**
+ * @param msg
+ * @param context
+ * @param xpath
+ * @param expectedTagName
+ * @param expectedContent
+ */
+public static void assertSingleNodeContent(final String msg, final Element context, final String xpath, final String expectedTagName, String expectedContent) {
+      
+      @SuppressWarnings({ "unchecked", "rawtypes" })
+      final XPathExpression<Element> xpathExpr = (XPathExpression<Element>) (XPathExpression) xpf.compile(xpath);
+
+      final List<Element> matchedNodes = xpathExpr.evaluate(context);
+      if (1 == matchedNodes.size()) {
+         
+         final Element element = matchedNodes.get(0);
+         
+         final String elementTagName = element.getName();
+         if (!expectedTagName.equals(elementTagName)) {
+            throw new AssertXpathResult(msg + "\nExpected <" + expectedTagName  + "> for xpath '" + xpath + "' but found <" +
+                  elementTagName + ">");
+         }
+         final String content = element.getValue();
+         if (!expectedContent.equals(content)) {
+            throw new AssertXpathResult(msg + "\nExpected element content '" + expectedContent  + "' for xpath '" + xpath + "' but found '" +
+                                       content + "'");
+         }
+
+      } else {
+         throw new AssertXpathResult("Exactly node expected for xpath '" + xpath + "' but found " + matchedNodes.size());
+      }
+   }
+}
-- 
GitLab