From cf26925a572ce28eca6b8afb48c1a13c7f913a15 Mon Sep 17 00:00:00 2001
From: Martin Goik <goik@hdm-stuttgart.de>
Date: Thu, 10 Apr 2014 23:33:16 +0200
Subject: [PATCH] element lists

---
 Doc/course.xml                                | 237 +++++++++++++++---
 .../Jdbc/src/main/java/sax/count/Driver.java  |  34 +++
 .../java/sax/count/ListTagNamesHandler.java   |  35 +++
 3 files changed, 270 insertions(+), 36 deletions(-)
 create mode 100644 ws/eclipse/Jdbc/src/main/java/sax/count/Driver.java
 create mode 100644 ws/eclipse/Jdbc/src/main/java/sax/count/ListTagNamesHandler.java

diff --git a/Doc/course.xml b/Doc/course.xml
index 811c61c74..fba191e37 100644
--- a/Doc/course.xml
+++ b/Doc/course.xml
@@ -7666,8 +7666,8 @@ public class ElementCount {
           redefine only those methods corresponding to events actually being
           handled by the application in question.</para>
 
-          <qandaset defaultlabel="qanda" xml:id="exercise_saxAttrib">
-            <title>Reading XML attributes</title>
+          <qandaset xml:id="sda1SaxReadAttributes">
+            <title>SAX and attribute values</title>
 
             <qandadiv>
               <qandaentry>
@@ -7703,19 +7703,183 @@ public class AttribEventHandler extends DefaultHandler {
 }</programlisting>
                 </answer>
               </qandaentry>
+            </qandadiv>
+          </qandaset>
 
-              <qandaentry xml:id="saxRdbms">
+          <qandaset xml:id="sda1QandaElementNames">
+            <title>Element lists of arbitrary XML documents.</title>
+
+            <qandadiv>
+              <qandaentry>
                 <question>
-                  <label>SAX processing with RDBMS access.</label>
+                  <para>We reconsider the simple application reading arbitrary
+                  XML documents and providing a list of XML Elements being
+                  contained within:</para>
 
-                  <para>Implement the example given in <xref
-                  linkend="saxRdbmsAccessPrinciple"/> to produce the output
-                  sketched in <xref linkend="saxPriceOut"/>. You may start by
-                  implementing <emphasis>and testing</emphasis> the following
-                  methods of a RDBMS interfacing class using <trademark
-                  xlink:href="http://electronics.zibb.com/trademark/jdbc/29545026">JDBC</trademark>:</para>
+                  <programlisting>Opening Document
+<emphasis role="bold">Opening "catalog"</emphasis> 
+Content "
+  "
+<emphasis role="bold">Opening "item"</emphasis> 
+Content "Swinging headset"
+Closing "item"
+Content " ...</programlisting>
+
+                  <para>If an element like e.g. <tag
+                  class="starttag">item</tag> appears multiple times it will
+                  also be written to standard output multiple times.</para>
+
+                  <para>We are now interested to get the list of all elements
+                  names being present in an arbitrary XML document. Consider
+                  the following example:</para>
+
+                  <programlisting language="xml">&lt;memo&gt;
+  &lt;from&gt;
+    &lt;name&gt;Martin&lt;/name&gt;
+    &lt;surname&gt;Goik&lt;/surname&gt;
+  &lt;/from&gt;
+  &lt;to&gt;
+    &lt;name&gt;Adam&lt;/name&gt;
+    &lt;surname&gt;Hacker&lt;/surname&gt;
+  &lt;/to&gt;
+  &lt;to&gt;
+    &lt;name&gt;Eve&lt;/name&gt;
+    &lt;surname&gt;Intruder&lt;/surname&gt;
+  &lt;/to&gt;
+  &lt;date year="2005" month="1" day="6"/&gt;
+  &lt;subject&gt;Firewall problems&lt;/subject&gt;
+  &lt;content&gt;
+    &lt;para&gt;Thanks for your excellent work.&lt;/para&gt;
+    &lt;para&gt;Our firewall is definitely broken!&lt;/para&gt;
+  &lt;/content&gt;
+&lt;/memo&gt;</programlisting>
+
+                  <para>The elements <tag class="starttag">to</tag> , <tag
+                  class="starttag">name</tag>, <tag
+                  class="starttag">surname</tag> and <tag
+                  class="starttag">para</tag> both appear multiple times.
+                  Write a SAX application which processes arbitrary XML
+                  documents and creates an alphabetically sorted list of
+                  elements being contained <emphasis role="bold">excluding
+                  duplicates</emphasis>. The intended output for the above
+                  example is: </para>
+
+                  <programlisting>List of elements: {content date from memo name para subject surname to }</programlisting>
+
+                  <para>The corresponding handler should be implemented in a
+                  re-usable way. Thus if different XML documents are being
+                  handled in succession the list of elements should be erased
+                  prior to processing the current document. Hints:</para>
+
+                  <itemizedlist>
+                    <listitem>
+                      <para>Use a <classname>java.util.SortedSet</classname>
+                      instance to collect element names thereby excluding
+                      duplicates.</para>
+                    </listitem>
+
+                    <listitem>
+                      <para>The method
+                      <methodname>sax.count.ListTagNamesHandler.startDocument()</methodname>
+                      may be used to initialize your handler.</para>
+                    </listitem>
+                  </itemizedlist>
+                </question>
+
+                <answer>
+                  <para>A suitable handler reads:</para>
+
+                  <programlisting language="java">package sax.count;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/** Reading attributes from element events */
+public class ListTagNamesHandler extends DefaultHandler {
 
-                  <programlisting language="java">package sax.rdbms;
+  // A SortedSet by definition does not contain any duplicates.
+  private SortedSet&lt;String&gt; elementNames = new TreeSet&lt;&gt;();
+
+  @Override
+  public void startDocument() throws SAXException {
+    elementNames.clear(); // May contain elements from a previous run.
+  }
+
+  public void startElement(String namespaceUri, String localName,
+      String rawName, Attributes attrs) {
+    // In case the current element name has already been inserted
+    // this method call will be silently ignored.
+    elementNames.add(rawName);
+  }
+
+  /**
+   * @return A sorted list of element names of he currently processed XML
+   *         document without duplicates.
+   */
+  public String[] getTagNames() {
+    return elementNames.toArray(new String[0]);
+  }
+}</programlisting>
+
+                  <para>A complete application requires a driver:</para>
+
+                  <programlisting language="java">package sax.count;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.XMLReader;
+
+import sax.stat.v2.MyErrorHandler;
+
+public class Driver {
+
+  public static void main(String argv[]) throws Exception {
+
+    final SAXParserFactory saxPf = SAXParserFactory.newInstance();
+    final SAXParser saxParser = saxPf.newSAXParser();
+    final XMLReader xmlReader = saxParser.getXMLReader();
+    final ListTagNamesHandler handler = new ListTagNamesHandler();
+    xmlReader.setContentHandler(handler);
+    xmlReader.setErrorHandler(new MyErrorHandler());
+    xmlReader.parse("Input/Xml/Memo/message.xml");
+
+    System.out.print("List of elements: {");
+    for (String elementName : handler.getTagNames()) {
+      System.out.print(elementName + " ");
+    }
+    System.out.println("}");
+  }
+}</programlisting>
+                </answer>
+              </qandaentry>
+            </qandadiv>
+          </qandaset>
+
+          <section xml:id="sda1SaxRdbms">
+            <title>SAX and RDBMS</title>
+
+            <qandaset defaultlabel="qanda" xml:id="exercise_saxAttrib">
+              <title>Reading XML attributes</title>
+
+              <qandadiv>
+                <qandaentry xml:id="saxRdbms">
+                  <question>
+                    <label>SAX processing with RDBMS access.</label>
+
+                    <para>Implement the example given in <xref
+                    linkend="saxRdbmsAccessPrinciple"/> to produce the output
+                    sketched in <xref linkend="saxPriceOut"/>. You may start
+                    by implementing <emphasis>and testing</emphasis> the
+                    following methods of a RDBMS interfacing class using
+                    <trademark
+                    xlink:href="http://electronics.zibb.com/trademark/jdbc/29545026">JDBC</trademark>:</para>
+
+                    <programlisting language="java">package sax.rdbms;
         
 public class RdbmsAccess {
 
@@ -7731,30 +7895,30 @@ public class RdbmsAccess {
   }
 }</programlisting>
 
-                  <para>You may find it helpful to write a small testbed for
-                  the RDBMS access functionality prior to integrate it into
-                  your <acronym
-                  xlink:href="http://www.saxproject.org">SAX</acronym>
-                  application producing HTML output.</para>
-                </question>
+                    <para>You may find it helpful to write a small testbed for
+                    the RDBMS access functionality prior to integrate it into
+                    your <acronym
+                    xlink:href="http://www.saxproject.org">SAX</acronym>
+                    application producing HTML output.</para>
+                  </question>
 
-                <answer>
-                  <para>We start by creating a suitable RDBMS Table:</para>
+                  <answer>
+                    <para>We start by creating a suitable RDBMS Table:</para>
 
-                  <programlisting>CREATE SCHEMA AUTHORIZATION midb2
+                    <programlisting>CREATE SCHEMA AUTHORIZATION midb2
 CREATE TABLE Product(
   orderNo CHAR(10) NOT NULL PRIMARY KEY
  ,price DECIMAL (9,2) NOT NULL 
 )</programlisting>
 
-                  <para>Next we feed some toy data:</para>
+                    <para>Next we feed some toy data:</para>
 
-                  <programlisting>INSERT INTO Product VALUES('x-223', 330.20);
+                    <programlisting>INSERT INTO Product VALUES('x-223', 330.20);
 INSERT INTO Product VALUES('w-124', 110.40);</programlisting>
 
-                  <para>Now we implement our RDBMS access class:</para>
+                    <para>Now we implement our RDBMS access class:</para>
 
-                  <programlisting language="java">package dom.xsl;
+                    <programlisting language="java">package dom.xsl;
 ...
 public class DbAccess {
 
@@ -7797,10 +7961,10 @@ public class DbAccess {
   private Connection conn = null;
 }</programlisting>
 
-                  <para>This access layer may be tested independently from
-                  handling catalog instances:</para>
+                    <para>This access layer may be tested independently from
+                    handling catalog instances:</para>
 
-                  <programlisting language="java">package dom/xsl;
+                    <programlisting language="java">package dom/xsl;
 
 public class DbAccessDriver {
 
@@ -7814,12 +7978,12 @@ public class DbAccessDriver {
   }
 }</programlisting>
 
-                  <para>If the above test succeeds we may embed the RDBMS
-                  access layer into our The <acronym
-                  xlink:href="http://www.saxproject.org">SAX</acronym>
-                  handler:</para>
+                    <para>If the above test succeeds we may embed the RDBMS
+                    access layer into our The <acronym
+                    xlink:href="http://www.saxproject.org">SAX</acronym>
+                    handler:</para>
 
-                  <programlisting language="java">package sax.rdbms;
+                    <programlisting language="java">package sax.rdbms;
 ...
 public class HtmlEventHandler extends DefaultHandler{
   public void startDocument() {
@@ -7861,10 +8025,11 @@ public class HtmlEventHandler extends DefaultHandler{
   }
   private DbAccess dbaccess = new DbAccess();
 }</programlisting>
-                </answer>
-              </qandaentry>
-            </qandadiv>
-          </qandaset>
+                  </answer>
+                </qandaentry>
+              </qandadiv>
+            </qandaset>
+          </section>
         </section>
 
         <section xml:id="saxValidate">
diff --git a/ws/eclipse/Jdbc/src/main/java/sax/count/Driver.java b/ws/eclipse/Jdbc/src/main/java/sax/count/Driver.java
new file mode 100644
index 000000000..e09282ff6
--- /dev/null
+++ b/ws/eclipse/Jdbc/src/main/java/sax/count/Driver.java
@@ -0,0 +1,34 @@
+package sax.count;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.XMLReader;
+
+import sax.stat.v2.MyErrorHandler;
+
+/** Driver class */
+public class Driver {
+
+  /**
+   * @param argv
+   *          unused
+   * @throws Exception
+   */
+  public static void main(String argv[]) throws Exception {
+
+    final SAXParserFactory saxPf = SAXParserFactory.newInstance();
+    final SAXParser saxParser = saxPf.newSAXParser();
+    final XMLReader xmlReader = saxParser.getXMLReader();
+    final ListTagNamesHandler handler = new ListTagNamesHandler();
+    xmlReader.setContentHandler(handler);
+    xmlReader.setErrorHandler(new MyErrorHandler());
+    xmlReader.parse("Input/Xml/Memo/message.xml");
+
+    System.out.print("List of elements: {");
+    for (String elementName : handler.getTagNames()) {
+      System.out.print(elementName + " ");
+    }
+    System.out.println("}");
+  }
+}
\ No newline at end of file
diff --git a/ws/eclipse/Jdbc/src/main/java/sax/count/ListTagNamesHandler.java b/ws/eclipse/Jdbc/src/main/java/sax/count/ListTagNamesHandler.java
new file mode 100644
index 000000000..cfb6bb92c
--- /dev/null
+++ b/ws/eclipse/Jdbc/src/main/java/sax/count/ListTagNamesHandler.java
@@ -0,0 +1,35 @@
+package sax.count;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/** Reading attributes from element events */
+public class ListTagNamesHandler extends DefaultHandler {
+
+  // A SortedSet by definition does not contain any duplicates.
+  private SortedSet<String> elementNames = new TreeSet<>();
+
+  @Override
+  public void startDocument() throws SAXException {
+    elementNames.clear(); // May contain elements from a previous run.
+  }
+
+  public void startElement(String namespaceUri, String localName,
+      String rawName, Attributes attrs) {
+    // In case the current element name has already been inserted
+    // this method call will be silently ignored.
+    elementNames.add(rawName);
+  }
+
+  /**
+   * @return A sorted list of element names of he currently processed XML
+   *         document without duplicates.
+   */
+  public String[] getTagNames() {
+    return elementNames.toArray(new String[0]);
+  }
+}
\ No newline at end of file
-- 
GitLab