// DtdDemo.java: demonstration application showing DTD queries.
// NO WARRANTY! See README, and copyright below.
// $Id$
// Modified 11/8/98 to add package statement.
package com.microstar.xml.demo;
import java.util.Enumeration;
import com.microstar.xml.XmlParser;
/**
* Demonstration application showing DTD queries.
* <p>Usage: <code>java DtdDemo <url></code>
* <p>Or, use it as an applet, supplying the URL as the <code>url</code>
* parameter.
* <p>Note: This does not preserve any processing instructions
* or parameter entities in the DTD; otherwise, produces a fully expanded
* and normalised version.
* @author Copyright (c) 1997, 1998 by Microstar Software Ltd.;
* @author written by David Megginson <dmeggins@microstar.com>
* @version 1.1
* @since Ptolemy II 0.2
* @see com.microstar.xml.XmlParser
* @see com.microstar.xml.XmlHandler
* @see XmlApp
*/
public class DtdDemo extends XmlApp {
/**
* Entry point for an application (applets enter through XmlApp.init()).
* @see XmlApp
*/
public static void main(String[] args) throws Exception {
DtdDemo demo = new DtdDemo();
if (args.length != 1) {
System.err.println("Usage: java DtdDemo <uri>");
System.exit(1);
} else {
demo.doParse(args[0]);
}
}
/**
* Print a comment showing where the DTD (if any) begins.
*/
public void startDocument() {
displayText("<-- Start of DTD -->\n");
}
/**
* Print a comment showing where the DTD (if any) ends.
*/
public void endDocument(int errorCount) {
displayText("<-- End of DTD -->");
}
/**
* Dump the DTD.
* <p>Once this event is received, we know that the DTD is
* completely parsed, and can use AElfred's query routines
* to reconstruct a normalised version of it.
* @see #dumpNotations
* @see #dumpEntities
* @see #dumpElements
*/
public void doctypeDecl(String name, String pubid, String sysid) {
dumpNotations();
dumpEntities();
dumpElements();
}
/**
* Produce normalised declarations for all notations.
* @see #makeExternalIdentifiers
*/
public void dumpNotations() {
Enumeration notationNames = parser.declaredNotations();
String nname;
String extId;
// Mark the beginning of a new section.
displayText("<-- Notation Declarations -->\n");
// Loop through all declared notations.
while (notationNames.hasMoreElements()) {
nname = (String) notationNames.nextElement();
extId = makeExternalIdentifiers(parser.getNotationPublicId(nname),
parser.getNotationSystemId(nname));
displayText("<!NOTATION " + nname + +' ' + extId + ">\n");
}
}
/**
* Produce normalised declarations for all general entities.
* @see #makeLiteral
* @see #makeExternalIdentifiers
*/
public void dumpEntities() {
Enumeration entityNames = parser.declaredEntities();
String ename;
String value;
// Mark the beginning of a new section.
displayText("<-- Entity Declarations -->\n");
// Loop through all the declared
// entities.
while (entityNames.hasMoreElements()) {
ename = (String) entityNames.nextElement();
// Skip parameter entities.
if (ename.startsWith("%")) {
continue;
}
// Construct a value based on the
// class of entity.
value = null;
switch (parser.getEntityType(ename)) {
// Internal text entity
case XmlParser.ENTITY_INTERNAL:
value = makeLiteral(parser.getEntityValue(ename));
break;
// External binary entity
case XmlParser.ENTITY_NDATA:
value = makeExternalIdentifiers(
parser.getEntityPublicId(ename), parser
.getEntitySystemId(ename))
+ "NDATA " + parser.getEntityNotationName(ename);
break;
// External text entity
case XmlParser.ENTITY_TEXT:
value = makeExternalIdentifiers(
parser.getEntityPublicId(ename), parser
.getEntitySystemId(ename));
break;
}
// Print a normalised declaration.
displayText("<!ENTITY " + ename + ' ' + value + ">\n");
}
}
/**
* Produce normalised declarations for all elements.
* @see #dumpAttributes
*/
public void dumpElements() {
Enumeration elementNames = parser.declaredElements();
String elname;
// Mark the beginning of a new section.
displayText("<-- Element Type Declarations -->\n");
// Loop through all of the declared
// elements.
while (elementNames.hasMoreElements()) {
String contentSpec = "ANY";
elname = (String) elementNames.nextElement();
// Construct a content spec based
// on the element's content type.
switch (parser.getElementContentType(elname)) {
case XmlParser.CONTENT_EMPTY:
contentSpec = "EMPTY";
break;
case XmlParser.CONTENT_ANY:
contentSpec = "ANY";
break;
case XmlParser.CONTENT_ELEMENTS:
case XmlParser.CONTENT_MIXED:
contentSpec = parser.getElementContentModel(elname);
break;
}
// Print a normalised element type
// declaration.
displayText("<!ELEMENT " + elname + ' ' + contentSpec + ">");
// Print the ATTLIST declaration,
// if any.
dumpAttributes(elname);
// Blank line.
displayText("");
}
}
/**
* Dump attributes for an element.
* @see #makeAttributeType
* @see #makeAttributeValue
*/
public void dumpAttributes(String elname) {
Enumeration attributeNames = parser.declaredAttributes(elname);
String aname;
String type;
String value;
// Skip if there are no declared
// attributes for this element
// type.
if (attributeNames == null) {
return;
}
// Print the start of the ATTLIST
// declaration.
displayText("<!ATTLIST " + elname);
// Loop through all of the declared
// attributes.
while (attributeNames.hasMoreElements()) {
aname = (String) attributeNames.nextElement();
type = makeAttributeType(elname, aname);
value = makeAttributeValue(elname, aname);
// Print the declaration for a
// single attribute.
displayText(" " + aname + ' ' + type + ' ' + value);
}
// Finish the ATTLIST declaration.
displayText(">");
}
/**
* Generate the attribute type as a normalised string.
*/
public String makeAttributeType(String elname, String aname) {
// Construct a string equivalent
// of the attribute type.
switch (parser.getAttributeType(elname, aname)) {
case XmlParser.ATTRIBUTE_CDATA:
return "CDATA";
case XmlParser.ATTRIBUTE_ID:
return "ID";
case XmlParser.ATTRIBUTE_IDREF:
return "IDREF";
case XmlParser.ATTRIBUTE_IDREFS:
return "IDREFS";
case XmlParser.ATTRIBUTE_ENTITY:
return "ENTITY";
case XmlParser.ATTRIBUTE_ENTITIES:
return "ENTITIES";
case XmlParser.ATTRIBUTE_NMTOKEN:
return "NMTOKEN";
case XmlParser.ATTRIBUTE_NMTOKENS:
return "NMTOKENS";
case XmlParser.ATTRIBUTE_ENUMERATED:
// An enumeration.
return parser.getAttributeEnumeration(elname, aname);
case XmlParser.ATTRIBUTE_NOTATION:
// An enumeration of notations.
return "NOTATION " + parser.getAttributeEnumeration(elname, aname);
}
return null;
}
/**
* Generate a full attribute default value.
* @see #makeLiteral
*/
public String makeAttributeValue(String elname, String aname) {
// Generate a default value based
// on the type.
switch (parser.getAttributeDefaultValueType(elname, aname)) {
case XmlParser.ATTRIBUTE_DEFAULT_IMPLIED:
return "#IMPLIED";
case XmlParser.ATTRIBUTE_DEFAULT_SPECIFIED:
return makeLiteral(parser.getAttributeDefaultValue(elname, aname));
case XmlParser.ATTRIBUTE_DEFAULT_REQUIRED:
return "#REQUIRED";
case XmlParser.ATTRIBUTE_DEFAULT_FIXED:
return "#FIXED "
+ makeLiteral(parser
.getAttributeDefaultValue(elname, aname));
}
return null;
}
/**
* Construct a string equivalent of external identifiers.
* @see #makeLiteral
*/
public String makeExternalIdentifiers(String pubid, String sysid) {
String extId = "";
if (pubid != null) {
extId = "PUBLIC " + makeLiteral(pubid);
if (sysid != null) {
extId = extId + ' ' + makeLiteral(sysid);
}
} else {
extId = "SYSTEM " + makeLiteral(sysid);
}
return extId;
}
/**
* Quote a literal, and escape any '"' or non-ASCII characters within it.
*/
public String makeLiteral(String data) {
char[] ch = data.toCharArray();
StringBuffer buf = new StringBuffer();
buf.append('"');
for (int i = 0; i < ch.length; i++) {
if (ch[i] == '"') {
buf.append("");
} else if (ch[i] > 0x7f) {
buf.append("" + (int) ch[i] + ";");
} else {
buf.append(ch[i]);
}
}
buf.append('"');
return buf.toString();
}
}
// End of DtdDemo.java