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: http://www.webreference.com/xml/column68/dtddoc.java.html
Created: Nov 11, 2002
Revised: Nov 11, 2002

Find a programming school near you