dtddoc step 4: Java code - exploring XML
dtddoc step 4: Generating HTML
The Java solution
import java.util.*; import java.io.*; import com.wutka.dtd.*; import org.apache.oro.text.regex.*; public class DTDDoc { public static void main(String[] args) throws IOException { DTDParser p = new DTDParser(new FileReader(args[0])); DTD dtd = p.parse(true); Enumeration e = dtd.getItemsByType(DTDComment.class).elements(); Hashtable comments = new Hashtable(); while (e.hasMoreElements()) { Object o = e.nextElement(); if (!(o instanceof DTDComment)) continue; parseComment(comments, ((DTDComment)o).getText()); } Hashtable parents = findParents(dtd); writeOverviewPage(new FileWriter("dtd-overview.html"), dtd, comments); writeTreePage(new FileWriter("dtd-tree.html"), dtd, comments); writeIndexPage(new FileWriter("dtd-index.html"), dtd, comments); writeNotationsPage(new FileWriter("dtd-notations.html"), dtd, comments); writeEntitiesPage(new FileWriter("dtd-entities.html"), dtd, comments); e = dtd.elements.elements(); while (e.hasMoreElements()) { DTDElement elt = (DTDElement) e.nextElement(); writeElementPage(new FileWriter("elt-" + elt.name + ".html"), dtd, comments, parents, elt); } } private static void parseComment(Hashtable comments, String comment) { PatternCompiler pc = new Perl5Compiler(); PatternMatcher pm = new Perl5Matcher(); Pattern pattern; try { pattern = pc.compile("<(\\w*)(\\s+(\\w+)=\"[^\"]*\")?>\\s*(.*)(\n[\\w\\W]*)?", Perl5Compiler.MULTILINE_MASK); } catch (MalformedPatternException ex) { throw new IllegalArgumentException("invalid pattern"); } PatternMatcherInput input = new PatternMatcherInput(comment); if (pm.contains(input, pattern)) { MatchResult result = pm.getMatch(); String[] s = {htmlifyComment(result.group(4)), htmlifyComment(result.group(5))}; comments.put(result.group(1) + " " + result.group(3),s); } } private static String getShortComment(Hashtable comments, DTDElement elt, DTDAttribute att) { String eltname = elt == null ? "" : elt.name; String attname = att == null ? "null" : att.name; String[] comment = (String[])comments.get(eltname + " " + attname); return comment[0]; } private static String getLongComment(Hashtable comments, DTDElement elt, DTDAttribute att) { String eltname = elt == null ? "" : elt.name; String attname = att == null ? " null" : att.name; String[] comment = (String[])comments.get(eltname + attname); return comment[1].equals("null") ? "" : comment[1]; } private static Hashtable findParents(DTD dtd) throws IOException { Hashtable parents = new Hashtable(); Enumeration e = dtd.elements.elements(); while (e.hasMoreElements()) { DTDElement elt = (DTDElement) e.nextElement(); StringWriter sw = new StringWriter(); elt.content.write(new PrintWriter(sw)); PatternCompiler pc = new Perl5Compiler(); PatternMatcher pm = new Perl5Matcher(); Pattern pattern; try { pattern = pc.compile("[ (](\\w+)"); } catch (MalformedPatternException ex) { throw new IllegalArgumentException("invalid pattern"); } PatternMatcherInput input = new PatternMatcherInput(sw.toString()); while (pm.contains(input, pattern)) { MatchResult result = pm.getMatch(); String child = result.group(1); Vector v = parents.containsKey(child) ? (Vector)parents.get(child) : new Vector(); v.addElement(elt.name); parents.put(child, v); } } return parents; } private static void writeOverviewPage(Writer w, DTD dtd, Hashtable comments) throws IOException { writeHeader(w); w.write("<h1>DTD Overview</h1>"); w.write("<p>" + getShortComment(comments, null, null) + "</p>"); w.write("<p>" + getLongComment(comments, null, null) + "</p>"); String root = dtd.rootElement.name; w.write("<h2>Root element</h2><p><a href=elt-" + root + ".html>" + root + "</a></p>"); writeFooter(w); } private static void writeTreePage(Writer w, DTD dtd, Hashtable comments) throws IOException { writeHeader(w); w.write("<h1>Element Tree</h1>"); w.write("<ul>"); writeTreeElement(w, dtd, comments, dtd.rootElement.name); w.write("</ul>"); writeFooter(w); } private static void writeTreeElement(Writer w, DTD dtd, Hashtable comments, String eltName) throws IOException { DTDElement elt = (DTDElement)dtd.elements.get(eltName); w.write("<li><a href=elt-" + elt.name + ".html>" + elt.name + "</a>"); w.write(" - " + getShortComment(comments, elt, null)); DTDItem content = elt.getContent(); if (content instanceof DTDContainer) { boolean first = true; Enumeration e = ((DTDContainer)content).getItemsVec().elements(); while (e.hasMoreElements()) { DTDItem i = (DTDItem)e.nextElement(); if (i instanceof DTDName) { if (first) { w.write("<ul>"); first = false; } writeTreeElement(w, dtd, comments,((DTDName)i).value); } } if (!first) w.write("</ul>"); } } private static void writeIndexPage(Writer w, DTD dtd, Hashtable comments) throws IOException { writeHeader(w); w.write("<h1>Index</h1>"); Vector v = new Vector(); Enumeration e = dtd.elements.elements(); while (e.hasMoreElements()) { DTDElement elt = (DTDElement)e.nextElement(); insertIntoIndex(v, elt.name, "Element", getShortComment(comments, elt, null)); Enumeration f = elt.attributes.elements(); while (f.hasMoreElements()) { DTDAttribute att = (DTDAttribute) f.nextElement(); insertIntoIndex(v, att.name + " (" + elt.name + ")", "Attribute", getShortComment(comments, elt, att)); } } e = dtd.entities.elements(); while (e.hasMoreElements()) { DTDEntity ent = (DTDEntity)e.nextElement(); insertIntoIndex(v, ent.name, "Entity", ent.value); } e = dtd.notations.elements(); while (e.hasMoreElements()) { DTDNotation not = (DTDNotation)e.nextElement(); insertIntoIndex(v, not.name, "Notation", not.externalID.system); } w.write("<table border=1><tr><th>Name</th><th>Type</th><th>Value</th></tr>"); e = v.elements(); while (e.hasMoreElements()) { String line = (String)e.nextElement(); w.write("<tr><td>" + line +"</td></tr>"); } w.write("</table>"); writeFooter(w); } private static void insertIntoIndex(Vector v, String name, String type, String value) { int i = 0; String sort = "<!--" + name + "-->"; while (i < v.size() && sort.compareToIgnoreCase((String)v.elementAt(i)) > 0) i++; sort = sort + (type.equals("Element") ? "<a href=elt-" + name + ".html>" + name + "</a>" : name); v.insertElementAt(sort + "</td><td>" + type + "</td><td>" + value, i); } private static void writeNotationsPage(Writer w, DTD dtd, Hashtable comments) throws IOException { writeHeader(w); w.write("<h1>Notations</h1>"); if (dtd.notations.size() == 0) { w.write("<p><em>None</em></p>"); } else { Enumeration e = dtd.notations.elements(); while (e.hasMoreElements()) { DTDNotation not = (DTDNotation)e.nextElement(); w.write("<li>" + not.name + " = " + not.externalID.system + "</li>"); } } writeFooter(w); } private static void writeEntitiesPage(Writer w, DTD dtd, Hashtable comments) throws IOException { writeHeader(w); w.write("<h1>Entities</h1>"); if (dtd.entities.size() == 0) { w.write("<p><em>None</em></p>"); } else { w.write("<ul>"); Enumeration e = dtd.entities.elements(); while (e.hasMoreElements()) { DTDEntity ent = (DTDEntity)e.nextElement(); w.write("<li>" + ent.name + " = " + ent.value + "</li>"); } w.write("</ul>"); } writeFooter(w); } private static void writeElementPage(Writer w, DTD dtd, Hashtable comments, Hashtable parents, DTDElement elt) throws IOException { writeHeader(w); w.write("<h1>Element <" + elt.name +"></h1>"); w.write("<p>" + getShortComment(comments, elt, null) + "</p>"); String comment = getLongComment(comments, elt, null); if (!comment.equals("")) w.write("<p>" + comment + "</p>"); w.write("<h2>Attributes</h2>"); if (elt.attributes.size() == 0) { w.write("<p><em>None</em></p>"); } else { w.write("<dl>"); Enumeration e = elt.attributes.elements(); while (e.hasMoreElements()) { DTDAttribute att = (DTDAttribute)e.nextElement(); String defaultValue = att.defaultValue == null ? "" : att.defaultValue; w.write("<dt>" + att.name + " " + att.decl.name + " " + defaultValue + "</dt>"); w.write("<dd>" + getShortComment(comments, elt, att) + "</dd>"); } w.write("</dl>"); } w.write("<h2>Content</h2>"); StringWriter sw = new StringWriter(); elt.content.write(new PrintWriter(sw)); w.write("<p>" + htmlifyContent(sw.toString()) + "</p>"); w.write("<h2>Parents</h2>"); Vector p = (Vector)parents.get(elt.name); if (p == null) { w.write("<p><em>None</em></p>"); } else { w.write("<p>"); Enumeration e = p.elements(); while (e.hasMoreElements()) { String parent = (String) e.nextElement(); w.write("<a href=elt-" + parent + ".html>" + parent + "</a> "); } w.write("</p>"); } writeFooter(w); } private static String htmlifyContent(String s) { String shtml; try { shtml = Util.substitute(new Perl5Matcher(), (new Perl5Compiler()).compile("([ (])(\\w+)"), new Perl5Substitution("$1<a href=elt-$2.html>$2</a>"), s, Util.SUBSTITUTE_ALL); } catch (MalformedPatternException ex) { throw new IllegalArgumentException("invalid pattern"); } return shtml; } private static String htmlifyComment(String s) { PatternCompiler pc = new Perl5Compiler(); PatternMatcher pm = new Perl5Matcher(); String shtml; if (s == null) return ""; try { shtml = Util.substitute(pm, pc.compile("<(\\w+)>"), new Perl5Substitution("<a href=elt-$1.html>$1</a>"), s, Util.SUBSTITUTE_ALL); shtml = Util.substitute(pm, pc.compile("html:"), new Perl5Substitution(), shtml, Util.SUBSTITUTE_ALL); } catch (MalformedPatternException ex) { throw new IllegalArgumentException("invalid pattern"); } return shtml; } private static void writeHeader(Writer w) throws IOException { w.write("<html><body><p>"); w.write("<a href=dtd-overview.html>Overview</a> "); w.write("<a href=dtd-tree.html>Tree</a> "); w.write("<a href=dtd-index.html>Index</a> "); w.write("<a href=dtd-notations.html>Notations</a> "); w.write("<a href=dtd-entities.html>Entities</a> "); w.write("</p>"); } private static void writeFooter(Writer w) throws IOException { w.write("</body></html>"); w.close(); } }
Produced by Michael Claßen
URL: https://www.webreference.com/xml/column68/dtddoc.java.html
Created: Nov 11, 2002
Revised: Nov 11, 2002