[jdom-interest] Substituting a different <!DOCTYPE ...> when parsing an XML file

Sean Huo sqh at qad.com
Mon Jun 3 14:40:12 PDT 2002

                      Sean Huo                                                                                                         
                                               To:      "Adams, Dick W" <DAdams07 at sprintspectrum.com>                                  
                      06/03/02 02:25 PM        cc:                                                                                     
                                               Subject: RE: [jdom-interest] Substituting a different <!DOCTYPE ...> when  parsing an   
                                               XML file(Document link: Sean Huo)                                                       

A better solution is to provide an EntityResovler.
In your implementation of the EntityResovler, you have complete control
over how you want to resolve the dtd reference.
Here is a code fragment for parsing a xml document using JDOM.

SAXBuilder builder = new SAXBuilder(true)l
builder.setEntityResolver(new MyEnittyResolver());  // provide your own
version of EntityResolver
builder.build( ...);


                      "Adams, Dick W"                                                                                                    
                      <DAdams07 at sprintsp         To:      "'Geoff Rimmer'" <geoff.rimmer at sillyfish.com>, jdom-interest at jdom.org          
                      ectrum.com>                cc:                                                                                     
                      Sent by:                   Subject: RE: [jdom-interest] Substituting a different <!DOCTYPE ...> when  parsing an   
                      jdom-interest-admi         XML file                                                                                
                      n at jdom.org                                                                                                         
                      05/30/02 12:01 PM                                                                                                  

Excellent point.  Also, for a high volume application where the messages
relatively small, it would be helpful if we could omit the DTD/schema data
from the XML string itself so less data has to go over the network.

-----Original Message-----
From: Geoff Rimmer [mailto:geoff.rimmer at sillyfish.com]
Sent: Thursday, May 30, 2002 11:36 AM
To: jdom-interest at jdom.org
Subject: [jdom-interest] Substituting a different <!DOCTYPE ...> when
parsing an XML file

When parsing XML files with validation switched on, I think that in
95% of cases, it should be the *application* rather than the XML file
that specifies which DTD file to validate against.

For example, suppose we have an application that reads in a list of
countries from a file (countries.xml):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE countries SYSTEM "http://www.sillyfish.com/countries.dtd">

      <country name="France" />
      <country name="Belgium" />
      <country name="Italy" />
      <country name="Germany" />

where countries.dtd looks like this:

    <!ELEMENT countries (country*)>
    <!ELEMENT country EMPTY>
    <!ATTLIST country
        name CDATA #REQUIRED>

then our application can read in the data (with validation) as follows:

    // NOTE: validation switched on by using "true"
    for ( Iterator iter = new SAXBuilder( true )
            .build( new FileInputStream( "countries.xml" ) )
            .getRootElement().getChildren( "country" ); iter.hasNext(); )
        Element e = (Element)iter.next();
            "Found country: " + e.getAttributeValue( "name" ) );

and we would get the following output:

    Found country: France
    Found country: Belgium
    Found country: Italy
    Found country: Germany

No problem here.  But there's nothing to stop us sneaking in an
alternate "countries.xml" file which is in a completely different
format to that expected; for example suppose the contents of
countries.xml were as follows:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE shops SYSTEM "http://www.sillyfish.com/shops.dtd">


where shops.dtd looks like this:

    <!ELEMENT shops (shop*)>
    <!ELEMENT shop (name,sells)>
    <!ELEMENT name (#PCDATA)>
    <!ELEMENT sells (#PCDATA)>

Now, when we read in *this* version of countries.xml (which now
contains details of shops not countries) using JDOM, the validation
still does not fail.  This is because the XML file has specified a DTD
which it successfully validates against (even though it describes a
document about shops, not countries).

The Java code above will simply determine that the file contains no
<country> elements, and will therefore output nothing.  In fact it
would be totally unaware that a junk XML file had just been parsed.

What would be nice is if the Java code could specify which DTD to
validate against.  For example if SAXBuilder had a new build() method
with an extra parameter of type DocType:

     * This builds a document from the supplied input stream,
     * replacing any <!DOCTYPE...> with the specified docType.
     * If validation has been switched on, the document will
     * be validated against the specified docType irrespective
     * of what DOCTYPE is specified in the file.
    public Document build( InputStream in, DocType docType );

then we could write:

    DocType docType = new DocType(
        "countries", "http://www.sillyfish.com/countries.dtd" );

    for ( Iterator iter = new SAXBuilder( true )
            .build( new FileInputStream( "countries.xml" ), docType )
            .getRootElement().getChildren( "country" ); iter.hasNext(); )
        Element e = (Element)iter.next();
            "Found country: " + e.getAttributeValue( "name" ) );

and any bogus files would be rejected, as they would be forced to
validate against "countries.dtd" - whether they liked it or not.

Of course this would require SAXBuilder to be a bit clever when
reading in the XML file, as it would need to remove any DOCTYPE it
finds and insert a new one generated from the supplied DocType object.

My question is: what is the best way of doing this?  Is it just to
provide a utility filter class which replaces a file's DOCTYPE with

    class DocTypeReplacerInputStream extends FilterInputStream
        public DocTypeReplacerInputStream( InputStream is, DocType docType

        public int read() throws IOException

which you would use as follows:

    DocType docType = new DocType(
        "countries", "http://www.sillyfish.com/countries.dtd" );

    Document doc = new SAXBuilder( true ).build(
        new DocTypeReplacerInputStream(
            new FileInputStream( "countries.xml" ) ) );

    (I've written a very basic DocTypeReplacerInputStream class, but
    it is not exactly what you'd call sophisticated and it probably
    doesn't work with many XML files that could be thrown at it.  Has
    anyone else written a similar class?).

or is it to do as suggested above, namely to have extra build()
methods in SAXBuilder so that a replacement DocType can be specified
(and then make the DocTypeReplacerInputStream functionality part of

Personally I think it would be such a useful thing to have that it
*should* be part of SAXBuilder (as I have described above), but I
would be interested to hear what other people think.

Geoff Rimmer <> geoff.rimmer at sillyfish.com <> www.sillyfish.com
www.sillyfish.com/phone - Make savings on your BT and Telewest phone calls
UPDATED 09/05/2002: 508 destinations, 12 schemes (with contact details)
To control your jdom-interest membership:

To control your jdom-interest membership:

More information about the jdom-interest mailing list