Hello,

I have converted a larger program, that has been using a different
XML-parser to Xerces and found it very cumbersome to make Xerces use an
alternative element factory. I here describe my workaround and would plead
with the development team to equip a future version of Xerces with an
addition and a minimal change, that would make such attempts much easier:

1.) The only method provided so far, to use a different Element-factory,
was "setDocumentClassName(...)", i.e. to specify an alternative class-NAME
(a String). In my app, however, for misc. reasons I needed the parser to
use a specifc, already existing element-factory, i.e. it was not sufficient
to supply a class-name, since that would only be used to generate a new
element factory, but it should re-use an already EXISTING element factory
OBJECT.

To do so a method that allows to specify a different (Deferred)DocumentImpl
as element factory was missing. After peeking into the source code I helped
myself by deriving a modified DOMParser-class, that provides a method to
specify that element factory and also overwrites the
startDocument()-method, so that this element factory is then indeed used
for parsing:

     private class ParserWrapper extends
org.apache.xerces.parsers.DOMParser {

          private DocumentImpl elFact = null;

          public void setElementFactory(DocumentImpl elFact) {
               this.elFact = elFact;
          }

          public void startDocument() {
               try {
                    this.setDeferNodeExpansion(false);
               } catch (SAXNotSupportedException ex) {
                    System.err.println("SAXNotSupportedException");
               } catch (SAXNotRecognizedException ex) {
                    System.err.println("SAXNotRecognizedException");
               }
               this.fDocument = elFact;
               this.fDocumentImpl = elFact;
               this.fDeferredDocumentImpl = null;
               this.fCurrentElementNode = elFact;
          }

     }

which is then used as:
     ...
     ParserWrapper parser = null;
     ...
     if (parser == null) parser = new ParserWrapper();
     parser.setElementFactory(elFact); // force Xerces to user OUR element
factory
     parser.parse(new org.xml.sax.InputSource(is));
     org.w3c.dom.Document doc = parser.getDocument();
     ...


2.) The second problem was, that the standard Xerces Node's and Element's
use a concept of "ownership" (ownerNode in NodeImpl and ownerDocument in
ParentNode) and require that parameter to be passed down during
initialization. My XmlElement's did not know anything about this parameter
and in order to avoid having to modify the original source all over the
place, I was using the parameterless constructor for Namespace-Support or
Serialization, resp. However, Element's without owner are not foreseen in
Xerces and produce a interesting firework of NullPointerExceptions, i.e.
one has to adjust the Element-owner to some useful value after the element
has been created, to do anything useful with it. To do so, a method
"setOwnerDocument(...)" exists, but alas it has only package visibility,
i.e. it can not be called from any of my classes.

I thus helped myself by adding a new class "OwnerSettableElementImpl", that
makes this method accessible from outside the original package. But this
requires, that one can add an additional class to an already existing
package (or jar-file), which is not always possible (depending on security
settings).

package org.apache.xerces.dom;

import org.w3c.dom.*;

public class OwnerSettableElementImpl
     extends ElementImpl
{
     /** Factory constructor. */
     public OwnerSettableElementImpl(DocumentImpl ownerDoc, String name) {
          super(ownerDoc, name);
     }

     // for ElementNSImpl
     protected OwnerSettableElementImpl() {}

     // This method is the purpose of the entire class: since
setOwnerDocument
     // is defined with package visibility only but is need in a derived
class
     // from another package, we redefine it here as protected:

     protected void setOwnerDocument(DocumentImpl doc) {
          super.setOwnerDocument(doc);
     }
} // class OwnerSettableElementImpl


With these extensions, my program now works and uses the "standard"
DOM-parser and -tree, but I dislike the holes that I had to drill into
Xerces to be able to do so very much! I would thus again like to urge the
developers of the next Xerces version to:

a.) provide a method to set an alternative element factory.

b.) make the setOwnerDocument(...) method in ElementImpl (and preferably
also in NodeImpl and ParentNode) public or at least protected.


Hope I could make myself clear...

Cheers,
Michael



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to