A sample SAX2 counter. This sample program illustrates how to
register a SAX2 ContentHandler and receive the callbacks in
order to print information about the document. The output of
this program shows the time and count of elements, attributes,
ignorable whitespaces, and characters appearing in the document.
This class is useful as a "poor-man's" performance tester to
compare the speed and accuracy of various SAX parsers. However,
it is important to note that the first parse time of a parser
will include both VM class load time and parser initialization
that would not be present in subsequent parses with the same
file.
| Field Summary |
|---|
| protected static final String | NAMESPACES_FEATURE_ID | Namespaces feature id (http://xml.org/sax/features/namespaces). |
| protected static final String | NAMESPACE_PREFIXES_FEATURE_ID | Namespace prefixes feature id (http://xml.org/sax/features/namespace-prefixes). |
| protected static final String | VALIDATION_FEATURE_ID | Validation feature id (http://xml.org/sax/features/validation). |
| protected static final String | SCHEMA_VALIDATION_FEATURE_ID | Schema validation feature id (http://apache.org/xml/features/validation/schema). |
| protected static final String | SCHEMA_FULL_CHECKING_FEATURE_ID | Schema full checking feature id (http://apache.org/xml/features/validation/schema-full-checking). |
| protected static final String | HONOUR_ALL_SCHEMA_LOCATIONS_ID | Honour all schema locations feature id (http://apache.org/xml/features/honour-all-schemaLocations). |
| protected static final String | VALIDATE_ANNOTATIONS_ID | Validate schema annotations feature id (http://apache.org/xml/features/validate-annotations) |
| protected static final String | DYNAMIC_VALIDATION_FEATURE_ID | Dynamic validation feature id (http://apache.org/xml/features/validation/dynamic). |
| protected static final String | XINCLUDE_FEATURE_ID | XInclude feature id (http://apache.org/xml/features/xinclude). |
| protected static final String | XINCLUDE_FIXUP_BASE_URIS_FEATURE_ID | XInclude fixup base URIs feature id (http://apache.org/xml/features/xinclude/fixup-base-uris). |
| protected static final String | XINCLUDE_FIXUP_LANGUAGE_FEATURE_ID | XInclude fixup language feature id (http://apache.org/xml/features/xinclude/fixup-language). |
| protected static final String | DEFAULT_PARSER_NAME | Default parser name. |
| protected static final int | DEFAULT_REPETITION | Default repetition (1). |
| protected static final boolean | DEFAULT_NAMESPACES | Default namespaces support (true). |
| protected static final boolean | DEFAULT_NAMESPACE_PREFIXES | Default namespace prefixes (false). |
| protected static final boolean | DEFAULT_VALIDATION | Default validation support (false). |
| protected static final boolean | DEFAULT_SCHEMA_VALIDATION | Default Schema validation support (false). |
| protected static final boolean | DEFAULT_SCHEMA_FULL_CHECKING | Default Schema full checking support (false). |
| protected static final boolean | DEFAULT_HONOUR_ALL_SCHEMA_LOCATIONS | Default honour all schema locations (false). |
| protected static final boolean | DEFAULT_VALIDATE_ANNOTATIONS | Default validate schema annotations (false). |
| protected static final boolean | DEFAULT_DYNAMIC_VALIDATION | Default dynamic validation support (false). |
| protected static final boolean | DEFAULT_XINCLUDE | Default XInclude processing support (false). |
| protected static final boolean | DEFAULT_XINCLUDE_FIXUP_BASE_URIS | Default XInclude fixup base URIs support (true). |
| protected static final boolean | DEFAULT_XINCLUDE_FIXUP_LANGUAGE | Default XInclude fixup language support (true). |
| protected static final boolean | DEFAULT_MEMORY_USAGE | Default memory usage report (false). |
| protected static final boolean | DEFAULT_TAGGINESS | Default "tagginess" report (false). |
| protected long | fElements | Number of elements. |
| protected long | fAttributes | Number of attributes. |
| protected long | fCharacters | Number of characters. |
| protected long | fIgnorableWhitespace | Number of ignorable whitespace characters. |
| protected long | fTagCharacters | Number of characters of tags. |
| protected long | fOtherCharacters | Number of other content characters for the "tagginess" calculation. |
| Method from sax.Counter Summary: |
|---|
|
characters, error, fatalError, ignorableWhitespace, main, printError, printResults, processingInstruction, startDocument, startElement, warning |
| Methods from org.xml.sax.helpers.DefaultHandler: |
|---|
|
characters, endDocument, endElement, endPrefixMapping, error, fatalError, ignorableWhitespace, notationDecl, processingInstruction, resolveEntity, setDocumentLocator, skippedEntity, startDocument, startElement, startPrefixMapping, unparsedEntityDecl, warning |
| Method from sax.Counter Detail: |
public void characters(char[] ch,
int start,
int length) throws SAXException {
fCharacters += length;
}
|
public void error(SAXParseException ex) throws SAXException {
printError("Error", ex);
}
|
public void fatalError(SAXParseException ex) throws SAXException {
printError("Fatal Error", ex);
//throw ex;
}
|
public void ignorableWhitespace(char[] ch,
int start,
int length) throws SAXException {
fIgnorableWhitespace += length;
}
|
public static void main(String[] argv) {
// is there anything to do?
if (argv.length == 0) {
printUsage();
System.exit(1);
}
// variables
Counter counter = new Counter();
PrintWriter out = new PrintWriter(System.out);
XMLReader parser = null;
int repetition = DEFAULT_REPETITION;
boolean namespaces = DEFAULT_NAMESPACES;
boolean namespacePrefixes = DEFAULT_NAMESPACE_PREFIXES;
boolean validation = DEFAULT_VALIDATION;
boolean schemaValidation = DEFAULT_SCHEMA_VALIDATION;
boolean schemaFullChecking = DEFAULT_SCHEMA_FULL_CHECKING;
boolean honourAllSchemaLocations = DEFAULT_HONOUR_ALL_SCHEMA_LOCATIONS;
boolean validateAnnotations = DEFAULT_VALIDATE_ANNOTATIONS;
boolean dynamicValidation = DEFAULT_DYNAMIC_VALIDATION;
boolean xincludeProcessing = DEFAULT_XINCLUDE;
boolean xincludeFixupBaseURIs = DEFAULT_XINCLUDE_FIXUP_BASE_URIS;
boolean xincludeFixupLanguage = DEFAULT_XINCLUDE_FIXUP_LANGUAGE;
boolean memoryUsage = DEFAULT_MEMORY_USAGE;
boolean tagginess = DEFAULT_TAGGINESS;
// process arguments
for (int i = 0; i < argv.length; i++) {
String arg = argv[i];
if (arg.startsWith("-")) {
String option = arg.substring(1);
if (option.equals("p")) {
// get parser name
if (++i == argv.length) {
System.err.println("error: Missing argument to -p option.");
continue;
}
String parserName = argv[i];
// create parser
try {
parser = XMLReaderFactory.createXMLReader(parserName);
}
catch (Exception e) {
try {
Parser sax1Parser = ParserFactory.makeParser(parserName);
parser = new ParserAdapter(sax1Parser);
System.err.println("warning: Features and properties not supported on SAX1 parsers.");
}
catch (Exception ex) {
parser = null;
System.err.println("error: Unable to instantiate parser ("+parserName+")");
}
}
continue;
}
if (option.equals("x")) {
if (++i == argv.length) {
System.err.println("error: Missing argument to -x option.");
continue;
}
String number = argv[i];
try {
int value = Integer.parseInt(number);
if (value < 1) {
System.err.println("error: Repetition must be at least 1.");
continue;
}
repetition = value;
}
catch (NumberFormatException e) {
System.err.println("error: invalid number ("+number+").");
}
continue;
}
if (option.equalsIgnoreCase("n")) {
namespaces = option.equals("n");
continue;
}
if (option.equalsIgnoreCase("np")) {
namespacePrefixes = option.equals("np");
continue;
}
if (option.equalsIgnoreCase("v")) {
validation = option.equals("v");
continue;
}
if (option.equalsIgnoreCase("s")) {
schemaValidation = option.equals("s");
continue;
}
if (option.equalsIgnoreCase("f")) {
schemaFullChecking = option.equals("f");
continue;
}
if (option.equalsIgnoreCase("hs")) {
honourAllSchemaLocations = option.equals("hs");
continue;
}
if (option.equalsIgnoreCase("va")) {
validateAnnotations = option.equals("va");
continue;
}
if (option.equalsIgnoreCase("dv")) {
dynamicValidation = option.equals("dv");
continue;
}
if (option.equalsIgnoreCase("xi")) {
xincludeProcessing = option.equals("xi");
continue;
}
if (option.equalsIgnoreCase("xb")) {
xincludeFixupBaseURIs = option.equals("xb");
continue;
}
if (option.equalsIgnoreCase("xl")) {
xincludeFixupLanguage = option.equals("xl");
continue;
}
if (option.equalsIgnoreCase("m")) {
memoryUsage = option.equals("m");
continue;
}
if (option.equalsIgnoreCase("t")) {
tagginess = option.equals("t");
continue;
}
if (option.equals("-rem")) {
if (++i == argv.length) {
System.err.println("error: Missing argument to -# option.");
continue;
}
System.out.print("# ");
System.out.println(argv[i]);
continue;
}
if (option.equals("h")) {
printUsage();
continue;
}
System.err.println("error: unknown option ("+option+").");
continue;
}
// use default parser?
if (parser == null) {
// create parser
try {
parser = XMLReaderFactory.createXMLReader(DEFAULT_PARSER_NAME);
}
catch (Exception e) {
System.err.println("error: Unable to instantiate parser ("+DEFAULT_PARSER_NAME+")");
continue;
}
}
// set parser features
try {
parser.setFeature(NAMESPACES_FEATURE_ID, namespaces);
}
catch (SAXException e) {
System.err.println("warning: Parser does not support feature ("+NAMESPACES_FEATURE_ID+")");
}
try {
parser.setFeature(NAMESPACE_PREFIXES_FEATURE_ID, namespacePrefixes);
}
catch (SAXException e) {
System.err.println("warning: Parser does not support feature ("+NAMESPACE_PREFIXES_FEATURE_ID+")");
}
try {
parser.setFeature(VALIDATION_FEATURE_ID, validation);
}
catch (SAXException e) {
System.err.println("warning: Parser does not support feature ("+VALIDATION_FEATURE_ID+")");
}
try {
parser.setFeature(SCHEMA_VALIDATION_FEATURE_ID, schemaValidation);
}
catch (SAXNotRecognizedException e) {
System.err.println("warning: Parser does not recognize feature ("+SCHEMA_VALIDATION_FEATURE_ID+")");
}
catch (SAXNotSupportedException e) {
System.err.println("warning: Parser does not support feature ("+SCHEMA_VALIDATION_FEATURE_ID+")");
}
try {
parser.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, schemaFullChecking);
}
catch (SAXNotRecognizedException e) {
System.err.println("warning: Parser does not recognize feature ("+SCHEMA_FULL_CHECKING_FEATURE_ID+")");
}
catch (SAXNotSupportedException e) {
System.err.println("warning: Parser does not support feature ("+SCHEMA_FULL_CHECKING_FEATURE_ID+")");
}
try {
parser.setFeature(HONOUR_ALL_SCHEMA_LOCATIONS_ID, honourAllSchemaLocations);
}
catch (SAXNotRecognizedException e) {
System.err.println("warning: Parser does not recognize feature ("+HONOUR_ALL_SCHEMA_LOCATIONS_ID+")");
}
catch (SAXNotSupportedException e) {
System.err.println("warning: Parser does not support feature ("+HONOUR_ALL_SCHEMA_LOCATIONS_ID+")");
}
try {
parser.setFeature(VALIDATE_ANNOTATIONS_ID, validateAnnotations);
}
catch (SAXNotRecognizedException e) {
System.err.println("warning: Parser does not recognize feature ("+VALIDATE_ANNOTATIONS_ID+")");
}
catch (SAXNotSupportedException e) {
System.err.println("warning: Parser does not support feature ("+VALIDATE_ANNOTATIONS_ID+")");
}
try {
parser.setFeature(DYNAMIC_VALIDATION_FEATURE_ID, dynamicValidation);
}
catch (SAXNotRecognizedException e) {
System.err.println("warning: Parser does not recognize feature ("+DYNAMIC_VALIDATION_FEATURE_ID+")");
}
catch (SAXNotSupportedException e) {
System.err.println("warning: Parser does not support feature ("+DYNAMIC_VALIDATION_FEATURE_ID+")");
}
try {
parser.setFeature(XINCLUDE_FEATURE_ID, xincludeProcessing);
}
catch (SAXNotRecognizedException e) {
System.err.println("warning: Parser does not recognize feature ("+XINCLUDE_FEATURE_ID+")");
}
catch (SAXNotSupportedException e) {
System.err.println("warning: Parser does not support feature ("+XINCLUDE_FEATURE_ID+")");
}
try {
parser.setFeature(XINCLUDE_FIXUP_BASE_URIS_FEATURE_ID, xincludeFixupBaseURIs);
}
catch (SAXNotRecognizedException e) {
System.err.println("warning: Parser does not recognize feature ("+XINCLUDE_FIXUP_BASE_URIS_FEATURE_ID+")");
}
catch (SAXNotSupportedException e) {
System.err.println("warning: Parser does not support feature ("+XINCLUDE_FIXUP_BASE_URIS_FEATURE_ID+")");
}
try {
parser.setFeature(XINCLUDE_FIXUP_LANGUAGE_FEATURE_ID, xincludeFixupLanguage);
}
catch (SAXNotRecognizedException e) {
System.err.println("warning: Parser does not recognize feature ("+XINCLUDE_FIXUP_LANGUAGE_FEATURE_ID+")");
}
catch (SAXNotSupportedException e) {
System.err.println("warning: Parser does not support feature ("+XINCLUDE_FIXUP_LANGUAGE_FEATURE_ID+")");
}
// parse file
parser.setContentHandler(counter);
parser.setErrorHandler(counter);
try {
long timeBefore = System.currentTimeMillis();
long memoryBefore = Runtime.getRuntime().freeMemory();
for (int j = 0; j < repetition; j++) {
parser.parse(arg);
}
long memoryAfter = Runtime.getRuntime().freeMemory();
long timeAfter = System.currentTimeMillis();
long time = timeAfter - timeBefore;
long memory = memoryUsage
? memoryBefore - memoryAfter : Long.MIN_VALUE;
counter.printResults(out, arg, time, memory, tagginess,
repetition);
}
catch (SAXParseException e) {
// ignore
}
catch (Exception e) {
System.err.println("error: Parse error occurred - "+e.getMessage());
Exception se = e;
if (e instanceof SAXException) {
se = ((SAXException)e).getException();
}
if (se != null)
se.printStackTrace(System.err);
else
e.printStackTrace(System.err);
}
}
}
Main program entry point. |
protected void printError(String type,
SAXParseException ex) {
System.err.print("[");
System.err.print(type);
System.err.print("] ");
if (ex== null) {
System.out.println("!!!");
}
String systemId = ex.getSystemId();
if (systemId != null) {
int index = systemId.lastIndexOf('/");
if (index != -1)
systemId = systemId.substring(index + 1);
System.err.print(systemId);
}
System.err.print(':");
System.err.print(ex.getLineNumber());
System.err.print(':");
System.err.print(ex.getColumnNumber());
System.err.print(": ");
System.err.print(ex.getMessage());
System.err.println();
System.err.flush();
}
Prints the error message. |
public void printResults(PrintWriter out,
String uri,
long time,
long memory,
boolean tagginess,
int repetition) {
// filename.xml: 631 ms (4 elems, 0 attrs, 78 spaces, 0 chars)
out.print(uri);
out.print(": ");
if (repetition == 1) {
out.print(time);
}
else {
out.print(time);
out.print('/");
out.print(repetition);
out.print('=");
out.print(time/repetition);
}
out.print(" ms");
if (memory != Long.MIN_VALUE) {
out.print(", ");
out.print(memory);
out.print(" bytes");
}
out.print(" (");
out.print(fElements);
out.print(" elems, ");
out.print(fAttributes);
out.print(" attrs, ");
out.print(fIgnorableWhitespace);
out.print(" spaces, ");
out.print(fCharacters);
out.print(" chars)");
if (tagginess) {
out.print(' ");
long totalCharacters = fTagCharacters + fOtherCharacters
+ fCharacters + fIgnorableWhitespace;
long tagValue = fTagCharacters * 100 / totalCharacters;
out.print(tagValue);
out.print("% tagginess");
}
out.println();
out.flush();
}
|
public void processingInstruction(String target,
String data) throws SAXException {
fTagCharacters += 2; // "< ?"
fTagCharacters += target.length();
if (data != null && data.length() > 0) {
fTagCharacters++; // space
fOtherCharacters += data.length();
}
fTagCharacters += 2; // "? >"
}
|
public void startDocument() throws SAXException {
fElements = 0;
fAttributes = 0;
fCharacters = 0;
fIgnorableWhitespace = 0;
fTagCharacters = 0;
}
|
public void startElement(String uri,
String local,
String raw,
Attributes attrs) throws SAXException {
fElements++;
fTagCharacters++; // open angle bracket
fTagCharacters += raw.length();
if (attrs != null) {
int attrCount = attrs.getLength();
fAttributes += attrCount;
for (int i = 0; i < attrCount; i++) {
fTagCharacters++; // space
fTagCharacters += attrs.getQName(i).length();
fTagCharacters++; // '='
fTagCharacters++; // open quote
fOtherCharacters += attrs.getValue(i).length();
fTagCharacters++; // close quote
}
}
fTagCharacters++; // close angle bracket
}
|
public void warning(SAXParseException ex) throws SAXException {
printError("Warning", ex);
}
|