<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 6.00.2600.0" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=#ffffff>
<DIV><FONT face=Arial size=2><FONT size=2>
<P>Hi,</P>
<P> </P>
<P>I'm not sure this is specifically a jdom question, but in the (slightly
modified) code from the Java & XML </P>
<P>below for dtd validation, I would like to return a boolean yes/no
to valid or not valid. How do I do that, given that </P>
<P>not valid throws an error exeception?</P>
<P>-manythanks, brian </P>
<P> </P>
<P> </P>
<P>/*-- </P>
<P>Copyright (C) 2001 Brett McLaughlin.</P>
<P>All rights reserved.</P>
<P></P>
<P>Redistribution and use in source and binary forms, with or without</P>
<P>modification, are permitted provided that the following conditions</P>
<P>are met:</P>
<P></P>
<P>1. Redistributions of source code must retain the above copyright</P>
<P>notice, this list of conditions, and the following disclaimer.</P>
<P></P>
<P>2. Redistributions in binary form must reproduce the above copyright</P>
<P>notice, this list of conditions, and the disclaimer that follows </P>
<P>these conditions in the documentation and/or other materials </P>
<P>provided with the distribution.</P>
<P>3. The name "Java and XML" must not be used to endorse or promote
products</P>
<P>derived from this software without prior written permission. For</P>
<P>written permission, please contact brett@newInstance.com.</P>
<P></P>
<P>In addition, we request (but do not require) that you include in the </P>
<P>end-user documentation provided with the redistribution and/or in the </P>
<P>software itself an acknowledgement equivalent to the following:</P>
<P>"This product includes software developed for the</P>
<P>'Java and XML' book, by Brett McLaughlin (O'Reilly & Associates)."</P>
<P>THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED</P>
<P>WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES</P>
<P>OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</P>
<P>DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT</P>
<P>CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,</P>
<P>SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT</P>
<P>LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF</P>
<P>USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND</P>
<P>ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</P>
<P>OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT</P>
<P>OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF</P>
<P>SUCH DAMAGE.</P>
<P>*/</P>
<P>//package javaxml2;</P>
<P>import java.io.IOException;</P>
<P>import java.util.HashMap;</P>
<P>import java.util.Iterator;</P>
<P>import java.util.Map;</P>
<P>import org.xml.sax.Attributes;</P>
<P>import org.xml.sax.ContentHandler;</P>
<P>import org.xml.sax.ErrorHandler;</P>
<P>import org.xml.sax.InputSource;</P>
<P>import org.xml.sax.Locator;</P>
<P>import org.xml.sax.SAXException;</P>
<P>import org.xml.sax.SAXParseException;</P>
<P>import org.xml.sax.XMLReader;</P>
<P>import org.xml.sax.helpers.XMLReaderFactory;</P>
<P>// This is an XML book - no need for explicit Swing imports</P>
<P>import java.awt.*;</P>
<P>import javax.swing.*;</P>
<P>import javax.swing.tree.*;</P>
<P>/**</P>
<P>* <b><code>SAXTreeValidator</code></b> uses Swing to
graphically</P>
<P>* display an XML document, and performs validation.</P>
<P>*/</P>
<P>public class SAXValidator {</P>
<P>/** Default parser to use */</P>
<P>private String vendorParserClass = </P>
<P>"org.apache.xerces.parsers.SAXParser";</P>
<P>/** The base tree to render */</P>
<P>private JTree jTree;</P>
<P>/** Tree model to use */</P>
<P>DefaultTreeModel defaultTreeModel;</P>
<P>/**</P>
<P>* <p> This initializes the needed Swing settings. </p></P>
<P>*/</P>
<P>public SAXValidator() {</P>
<P>// Handle Swing setup</P>
<P>//super("SAX Tree Validator");</P>
<P>//setSize(600, 450);</P>
<P>}</P>
<P>/**</P>
<P>* <p> This will construct the tree using Swing. </p></P>
<P>*</P>
<P>* @param filename <code>String</code> path to XML document.</P>
<P>*/</P>
<P>public void init(String xmlURI) throws IOException, SAXException {</P>
<P>DefaultMutableTreeNode base = </P>
<P>new DefaultMutableTreeNode("XML Document: " + </P>
<P>xmlURI);</P>
<P></P>
<P>// Build the tree model</P>
<P>defaultTreeModel = new DefaultTreeModel(base);</P>
<P>//jTree = new JTree(defaultTreeModel);</P>
<P>// Construct the tree hierarchy</P>
<P>buildTree(defaultTreeModel, base, xmlURI);</P>
<P></P>
<P>}</P>
<P>/**</P>
<P>* <p>This handles building the Swing UI tree.</p></P>
<P>*</P>
<P>* @param treeModel Swing component to build upon.</P>
<P>* @param base tree node to build on.</P>
<P>* @param xmlURI URI to build XML document from.</P>
<P>* @throws <code>IOException</code> - when reading the XML URI
fails.</P>
<P>* @throws <code>SAXException</code> - when errors in parsing
occur.</P>
<P>*/</P>
<P>public void buildTree(DefaultTreeModel treeModel, </P>
<P>DefaultMutableTreeNode base, String xmlURI) </P>
<P>throws IOException, SAXException {</P>
<P>// Create instances needed for parsing</P>
<P>XMLReader reader = </P>
<P>XMLReaderFactory.createXMLReader(vendorParserClass);</P>
<P>ContentHandler jTreeContentHandler = </P>
<P>new JValidatorContentHandler(treeModel, base);</P>
<P>ErrorHandler jTreeErrorHandler = new JValidatorErrorHandler();</P>
<P>// Register content handler</P>
<P>reader.setContentHandler(jTreeContentHandler);</P>
<P>// Register error handler</P>
<P>reader.setErrorHandler(jTreeErrorHandler);</P>
<P>// Turn on validation</P>
<P>reader.setFeature("http://xml.org/sax/features/validation", true);</P>
<P></P>
<P>//
reader.setFeature("http://apache.org/xml/features/validation/schema-full-checking",
true);</P>
<P>// Parse</P>
<P>InputSource inputSource = </P>
<P>new InputSource(xmlURI);</P>
<P>reader.parse(inputSource);</P>
<P>}</P>
<P>/**</P>
<P>* <p> Static entry point for running the viewer. </p></P>
<P>*/</P>
<P>public static void main(String[] args) {</P>
<P>try {</P>
<P>if (args.length != 1) {</P>
<P>System.out.println(</P>
<P>"Usage: java javaxml2.SAXTreeViewer " +</P>
<P>"[XML Document URI]");</P>
<P>System.exit(0);</P>
<P>}</P>
<P>SAXValidator viewer = new SAXValidator();</P>
<P></P>
<P>viewer.init(args[0]);</P>
<P>System.out.println(args[0] + " Validated");</P>
<P>// viewer.setVisible(true);</P>
<P>} catch (Exception e) {</P>
<P>e.printStackTrace();</P>
<P>}</P>
<P>}</P>
<P>}</P>
<P>/**</P>
<P>* <b><code>JValidatorContentHandler</code></b>
implements the SAX</P>
<P>* <code>ContentHandler</code> interface and defines callback</P>
<P>* behavior for the SAX callbacks associated with an XML</P>
<P>* document's content, bulding up JTree nodes.</P>
<P>*/</P>
<P>class JValidatorContentHandler implements ContentHandler {</P>
<P>/** Hold onto the locator for location information */</P>
<P>private Locator locator;</P>
<P>/** Store URI to prefix mappings */</P>
<P>private Map namespaceMappings;</P>
<P>/** Tree Model to add nodes to */</P>
<P>private DefaultTreeModel treeModel;</P>
<P>/** Current node to add sub-nodes to */</P>
<P>private DefaultMutableTreeNode current;</P>
<P>/**</P>
<P>* <p> Set up for working with the JTree. </p></P>
<P>*</P>
<P>* @param treeModel tree to add nodes to.</P>
<P>* @param base node to start adding sub-nodes to.</P>
<P>*/</P>
<P>public JValidatorContentHandler(DefaultTreeModel treeModel, </P>
<P>DefaultMutableTreeNode base) {</P>
<P>this.treeModel = treeModel;</P>
<P>this.current = base;</P>
<P>this.namespaceMappings = new HashMap();</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* Provide reference to <code>Locator</code> which provides</P>
<P>* information about where in a document callbacks occur.</P>
<P>* </p></P>
<P>*</P>
<P>* @param locator <code>Locator</code> object tied to callback</P>
<P>* process</P>
<P>*/</P>
<P>public void setDocumentLocator(Locator locator) {</P>
<P>// Save this for later use</P>
<P>this.locator = locator;</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This indicates the start of a Document parse-this precedes</P>
<P>* all callbacks in all SAX Handlers with the sole exception</P>
<P>* of <code>{@link #setDocumentLocator}</code>.</P>
<P>* </p></P>
<P>*</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void startDocument() throws SAXException {</P>
<P>// No visual events occur here</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This indicates the end of a Document parse-this occurs after</P>
<P>* all callbacks in all SAX Handlers.</code>.</P>
<P>* </p></P>
<P>*</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void endDocument() throws SAXException {</P>
<P>// No visual events occur here</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This indicates that a processing instruction (other than</P>
<P>* the XML declaration) has been encountered.</P>
<P>* </p></P>
<P>*</P>
<P>* @param target <code>String</code> target of PI</P>
<P>* @param data <code>String</code containing all data sent to the
PI.</P>
<P>* This typically looks like one or more attribute value</P>
<P>* pairs.</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void processingInstruction(String target, String data)</P>
<P>throws SAXException {</P>
<P>DefaultMutableTreeNode pi = </P>
<P>new DefaultMutableTreeNode("PI (target = '" + target +</P>
<P>"', data = '" + data + "')");</P>
<P>current.add(pi);</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This indicates the beginning of an XML Namespace prefix</P>
<P>* mapping. Although this typically occurs within the root element</P>
<P>* of an XML document, it can occur at any point within the</P>
<P>* document. Note that a prefix mapping on an element triggers</P>
<P>* this callback <i>before</i> the callback for the actual
element</P>
<P>* itself (<code>{@link #startElement}</code>) occurs.</P>
<P>* </p></P>
<P>*</P>
<P>* @param prefix <code>String</code> prefix used for the
namespace</P>
<P>* being reported</P>
<P>* @param uri <code>String</code> URI for the namespace</P>
<P>* being reported</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void startPrefixMapping(String prefix, String uri) {</P>
<P>// No visual events occur here.</P>
<P>namespaceMappings.put(uri, prefix);</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This indicates the end of a prefix mapping, when the namespace</P>
<P>* reported in a <code>{@link #startPrefixMapping}</code>
callback</P>
<P>* is no longer available.</P>
<P>* </p></P>
<P>*</P>
<P>* @param prefix <code>String</code> of namespace being
reported</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void endPrefixMapping(String prefix) {</P>
<P>// No visual events occur here.</P>
<P>for (Iterator i = namespaceMappings.keySet().iterator(); </P>
<P>i.hasNext(); ) {</P>
<P>String uri = (String)i.next();</P>
<P>String thisPrefix = (String)namespaceMappings.get(uri);</P>
<P>if (prefix.equals(thisPrefix)) {</P>
<P>namespaceMappings.remove(uri);</P>
<P>break;</P>
<P>}</P>
<P>}</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This reports the occurrence of an actual element. It includes</P>
<P>* the element's attributes, with the exception of XML vocabulary</P>
<P>* specific attributes, such as</P>
<P>* <code>xmlns:[namespace prefix]</code> and</P>
<P>* <code>xsi:schemaLocation</code>.</P>
<P>* </p></P>
<P>*</P>
<P>* @param namespaceURI <code>String</code> namespace URI this
element</P>
<P>* is associated with, or an empty <code>String</code></P>
<P>* @param localName <code>String</code> name of element (with
no</P>
<P>* namespace prefix, if one is present)</P>
<P>* @param qName <code>String</code> XML 1.0 version of element
name:</P>
<P>* [namespace prefix]:[localName]</P>
<P>* @param atts <code>Attributes</code> list for this element</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void startElement(String namespaceURI, String localName,</P>
<P>String qName, Attributes atts)</P>
<P>throws SAXException {</P>
<P>DefaultMutableTreeNode element = </P>
<P>new DefaultMutableTreeNode("Element: " + localName);</P>
<P>current.add(element);</P>
<P>current = element;</P>
<P>// Determine namespace</P>
<P>if (namespaceURI.length() > 0) {</P>
<P>String prefix = </P>
<P>(String)namespaceMappings.get(namespaceURI);</P>
<P>if (prefix.equals("")) {</P>
<P>prefix = "[None]";</P>
<P>}</P>
<P>DefaultMutableTreeNode namespace =</P>
<P>new DefaultMutableTreeNode("Namespace: prefix = '" +</P>
<P>prefix + "', URI = '" + namespaceURI + "'");</P>
<P>current.add(namespace);</P>
<P>}</P>
<P>// Process attributes</P>
<P>for (int i=0; i<atts.getLength(); i++) {</P>
<P>DefaultMutableTreeNode attribute =</P>
<P>new DefaultMutableTreeNode("Attribute (name = '" +</P>
<P>atts.getLocalName(i) + </P>
<P>"', value = '" +</P>
<P>atts.getValue(i) + "')");</P>
<P>String attURI = atts.getURI(i);</P>
<P>if (attURI.length() > 0) {</P>
<P>String attPrefix = </P>
<P>(String)namespaceMappings.get(namespaceURI);</P>
<P>if (attPrefix.equals("")) {</P>
<P>attPrefix = "[None]";</P>
<P>}</P>
<P>DefaultMutableTreeNode attNamespace =</P>
<P>new DefaultMutableTreeNode("Namespace: prefix = '" +</P>
<P>attPrefix + "', URI = '" + attURI + "'");</P>
<P>attribute.add(attNamespace); </P>
<P>}</P>
<P>current.add(attribute);</P>
<P>}</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* Indicates the end of an element</P>
<P>* (<code>&lt;/[element name]&gt;</code>) is reached. Note
that</P>
<P>* the parser does not distinguish between empty</P>
<P>* elements and non-empty elements, so this occurs uniformly.</P>
<P>* </p></P>
<P>*</P>
<P>* @param namespaceURI <code>String</code> URI of namespace
this</P>
<P>* element is associated with</P>
<P>* @param localName <code>String</code> name of element without
prefix</P>
<P>* @param qName <code>String</code> name of element in XML 1.0
form</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void endElement(String namespaceURI, String localName,</P>
<P>String qName)</P>
<P>throws SAXException {</P>
<P>// Walk back up the tree</P>
<P>current = (DefaultMutableTreeNode)current.getParent();</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This reports character data (within an element).</P>
<P>* </p></P>
<P>*</P>
<P>* @param ch <code>char[]</code> character array with character
data</P>
<P>* @param start <code>int</code> index in array where data
starts.</P>
<P>* @param length <code>int</code> index in array where data
ends.</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void characters(char[] ch, int start, int length)</P>
<P>throws SAXException {</P>
<P>String s = new String(ch, start, length);</P>
<P>DefaultMutableTreeNode data =</P>
<P>new DefaultMutableTreeNode("Character Data: '" + s + "'");</P>
<P>current.add(data);</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This reports whitespace that can be ignored in the</P>
<P>* originating document. This is typically invoked only when</P>
<P>* validation is ocurring in the parsing process.</P>
<P>* </p></P>
<P>*</P>
<P>* @param ch <code>char[]</code> character array with character
data</P>
<P>* @param start <code>int</code> index in array where data
starts.</P>
<P>* @param end <code>int</code> index in array where data ends.</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void ignorableWhitespace(char[] ch, int start, int length)</P>
<P>throws SAXException {</P>
<P></P>
<P>// This is ignorable, so don't display it</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This reports an entity that is skipped by the parser. This</P>
<P>* should only occur for non-validating parsers, and then is still</P>
<P>* implementation-dependent behavior.</P>
<P>* </p></P>
<P>*</P>
<P>* @param name <code>String</code> name of entity being
skipped</P>
<P>* @throws <code>SAXException</code> when things go wrong</P>
<P>*/</P>
<P>public void skippedEntity(String name) throws SAXException {</P>
<P>DefaultMutableTreeNode skipped =</P>
<P>new DefaultMutableTreeNode("Skipped Entity: '" + name + "'");</P>
<P>current.add(skipped);</P>
<P>}</P>
<P>}</P>
<P>/**</P>
<P>* <b><code>JValidatorErrorHandler</code></b>
implements the SAX</P>
<P>* <code>ErrorHandler</code> interface and defines callback</P>
<P>* behavior for the SAX callbacks associated with an XML</P>
<P>* document's warnings and errors.</P>
<P>*/</P>
<P>class JValidatorErrorHandler implements ErrorHandler {</P>
<P>/**</P>
<P>* <p></P>
<P>* This will report a warning that has occurred; this indicates</P>
<P>* that while no XML rules were "broken", something appears</P>
<P>* to be incorrect or missing.</P>
<P>* </p></P>
<P>*</P>
<P>* @param exception <code>SAXParseException</code> that
occurred.</P>
<P>* @throws <code>SAXException</code> when things go wrong </P>
<P>*/</P>
<P>public void warning(SAXParseException exception)</P>
<P>throws SAXException {</P>
<P></P>
<P>System.out.println("**Parsing Warning**\n" +</P>
<P>" Line: " + </P>
<P>exception.getLineNumber() + "\n" +</P>
<P>" URI: " + </P>
<P>exception.getSystemId() + "\n" +</P>
<P>" Message: " + </P>
<P>exception.getMessage()); </P>
<P>throw new SAXException("Warning encountered");</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This will report an error that has occurred; this indicates</P>
<P>* that a rule was broken, typically in validation, but that</P>
<P>* parsing can reasonably continue.</P>
<P>* </p></P>
<P>*</P>
<P>* @param exception <code>SAXParseException</code> that
occurred.</P>
<P>* @throws <code>SAXException</code> when things go wrong </P>
<P>*/</P>
<P>public void error(SAXParseException exception)</P>
<P>throws SAXException {</P>
<P></P>
<P>System.out.println("**Parsing Error**\n" +</P>
<P>" Line: " + </P>
<P>exception.getLineNumber() + "\n" +</P>
<P>" URI: " + </P>
<P>exception.getSystemId() + "\n" +</P>
<P>" Message: " + </P>
<P>exception.getMessage());</P>
<P>throw new SAXException("Error encountered");</P>
<P>}</P>
<P>/**</P>
<P>* <p></P>
<P>* This will report a fatal error that has occurred; this indicates</P>
<P>* that a rule has been broken that makes continued parsing either</P>
<P>* impossible or an almost certain waste of time.</P>
<P>* </p></P>
<P>*</P>
<P>* @param exception <code>SAXParseException</code> that
occurred.</P>
<P>* @throws <code>SAXException</code> when things go wrong </P>
<P>*/</P>
<P>public void fatalError(SAXParseException exception)</P>
<P>throws SAXException {</P>
<P></P>
<P>System.out.println("**Parsing Fatal Error**\n" +</P>
<P>" Line: " + </P>
<P>exception.getLineNumber() + "\n" +</P>
<P>" URI: " + </P>
<P>exception.getSystemId() + "\n" +</P>
<P>" Message: " + </P>
<P>exception.getMessage()); </P>
<P>throw new SAXException("Fatal Error encountered");</P>
<P>}</P>
<P>}</P></FONT></FONT></DIV></BODY></HTML>