You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by el...@apache.org on 2002/07/16 00:16:54 UTC

cvs commit: xml-xerces/java/src/org/apache/xerces/parsers DOMBuilderImpl.java AbstractDOMParser.java

elena       2002/07/15 15:16:52

  Modified:    java/src/org/apache/xerces/parsers DOMBuilderImpl.java
                        AbstractDOMParser.java
  Log:
  Add support for DOMBuilderFilter.
  The filters are not supported with deferred DOM implementation.
  
  All the code is located in AbstractDOMParser but for performance reasons we might
  want to move this code to another class.
  
  Revision  Changes    Path
  1.15      +19 -9     xml-xerces/java/src/org/apache/xerces/parsers/DOMBuilderImpl.java
  
  Index: DOMBuilderImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/parsers/DOMBuilderImpl.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- DOMBuilderImpl.java	11 Jun 2002 17:41:25 -0000	1.14
  +++ DOMBuilderImpl.java	15 Jul 2002 22:16:52 -0000	1.15
  @@ -65,18 +65,17 @@
   import java.util.Stack;
   import java.util.Vector;
   
  +import org.apache.xerces.dom.CoreDocumentImpl;
  +
   import org.w3c.dom.DOMException;
   import org.w3c.dom.Document;
   import org.w3c.dom.Node;
  -
  -import org.apache.xerces.dom.CoreDocumentImpl;
   import org.w3c.dom.DOMErrorHandler;
   import org.w3c.dom.ls.DOMBuilder;
   import org.w3c.dom.ls.DOMEntityResolver;
   import org.w3c.dom.ls.DOMBuilderFilter;
   import org.w3c.dom.ls.DOMInputSource;
   
  -
   import org.apache.xerces.impl.Constants;
   import org.apache.xerces.util.DOMEntityResolverWrapper;
   import org.apache.xerces.util.SymbolTable;
  @@ -135,6 +134,7 @@
       // Data
       //
   
  +
       // REVISIT: this value should be null by default and should be set during creation of
       //          DOMBuilder
       protected String fSchemaType = XML_SCHEMA_VALIDATION;
  @@ -172,8 +172,10 @@
   
           fConfiguration.addRecognizedFeatures(domRecognizedFeatures);
   
  +        // turn off deferred DOM
  +        fConfiguration.setFeature(DEFER_NODE_EXPANSION, false);
  +        
           // set default values
  -
           fConfiguration.setFeature(Constants.DOM_CANONICAL_FORM, false);
           fConfiguration.setFeature(Constants.DOM_CDATA_SECTIONS, true);
           fConfiguration.setFeature(Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING, true);
  @@ -190,6 +192,7 @@
           //          DOCTYPE is present.
           //          This is similar to JAXP schemaLanguage property.         
   
  +        
   
       } // <init>(XMLParserConfiguration)
   
  @@ -226,6 +229,11 @@
       public void reset() {
           super.reset();
   
  +        // DOM Filter
  +        fSkippedElemStack.clear();
  +        fRejectedElement.clear();
  +        fFilterReject = false;
  +
   
       } // reset() 
   
  @@ -326,7 +334,7 @@
        * happens before the filter is called. 
        */
       public DOMBuilderFilter getFilter() {
  -        throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not supported");
  +        return fDOMFilter;
       }
   
       /**
  @@ -339,7 +347,10 @@
        * happens before the filter is called. 
        */
       public void setFilter(DOMBuilderFilter filter) {
  -        throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not supported");
  +        fDOMFilter = filter;
  +        if (fSkippedElemStack == null) {
  +            fSkippedElemStack = new Stack();
  +        }
       }
   
       /**
  @@ -487,7 +498,7 @@
           try {        
               parse(source);
           } catch (Exception e){
  -            // do nothing since exceptions are reported via Error handler
  +            // REVISIT: report exception via the error handler
               if (DEBUG) {            
                  e.printStackTrace();
               }
  @@ -511,7 +522,7 @@
           try {        
               parse(xmlInputSource);
           } catch (Exception e) {
  -            // do nothing since exceptions are reported via Error handler
  +            // REVISIT: report exception via the error handler
               if (DEBUG) {            
                  e.printStackTrace();
               }
  @@ -622,7 +633,6 @@
           }
   
       } // endDocument()
  -
   
   
   } // class DOMBuilderImpl
  
  
  
  1.62      +320 -47   xml-xerces/java/src/org/apache/xerces/parsers/AbstractDOMParser.java
  
  Index: AbstractDOMParser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/parsers/AbstractDOMParser.java,v
  retrieving revision 1.61
  retrieving revision 1.62
  diff -u -r1.61 -r1.62
  --- AbstractDOMParser.java	10 Jul 2002 21:31:05 -0000	1.61
  +++ AbstractDOMParser.java	15 Jul 2002 22:16:52 -0000	1.62
  @@ -105,6 +105,9 @@
   import org.w3c.dom.ProcessingInstruction;
   import org.w3c.dom.Text;
   
  +import org.w3c.dom.ls.DOMBuilderFilter;
  +import org.w3c.dom.traversal.NodeFilter;
  +
   import java.util.Stack;
   
   /**
  @@ -277,14 +280,29 @@
       protected boolean fFirstChunk = false;
   
   
  +    /** DOMBuilderFilter: specifies that element with given QNAME and all its children
  +        must be rejected */
  +    protected boolean fFilterReject = false;
  +
  +    // data
  +
       /** Base uri stack*/
       protected Stack fBaseURIStack = new Stack();
   
  -    // data
   
  +    /** DOMBuilderFilter: the QNAME of rejected element*/    
  +    protected final QName fRejectedElement = new QName();
  +
  +    /** DOMBuilderFilter: store qnames of skipped elements*/
  +    protected Stack fSkippedElemStack = null;
  +    
       /** Attribute QName. */
       private QName fAttrQName = new QName();
   
  +    // handlers
  +
  +    protected DOMBuilderFilter fDOMFilter = null;
  +
       //
       // Constructors
       //
  @@ -436,6 +454,10 @@
           fFirstChunk = false;
           fCurrentCDATASection = null;
           fCurrentCDATASectionIndex = -1;
  +
  +        fBaseURIStack.clear();
  +
  +
       } // reset()
   
       //
  @@ -474,6 +496,9 @@
           // Always create entity reference nodes to be able to recreate
           // entity as a part of doctype
            if (!fDeferNodeExpansion) {
  +             if (fFilterReject) {
  +                 return;
  +             }
               setCharacterData(true);
               EntityReference er = fDocument.createEntityReference(name);            
               
  @@ -549,7 +574,7 @@
        */
       public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
           if (!fDeferNodeExpansion) {
  -            if (fCurrentEntityDecl != null) {
  +            if (fCurrentEntityDecl != null && !fFilterReject) {
                   fCurrentEntityDecl.setEncoding(encoding);
                   fCurrentEntityDecl.setVersion(version);
               }
  @@ -578,13 +603,42 @@
               }
               return;
           }
  -        if (!fIncludeComments) {
  +        if (!fIncludeComments || fFilterReject) {
                 return;
           }
           if (!fDeferNodeExpansion) {
  -            setCharacterData(false);
               Comment comment = fDocument.createComment(text.toString());
  +
  +            setCharacterData(false);
               fCurrentNode.appendChild(comment);
  +            if (fDOMFilter !=null && 
  +                (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_COMMENT)!= 0) {
  +                short code = fDOMFilter.acceptNode(comment);
  +                switch (code) {
  +                    case DOMBuilderFilter.FILTER_INTERRUPT:{ 
  +                        throw new RuntimeException("The normal processing of the document was interrupted.");
  +                    }   
  +                    case NodeFilter.FILTER_REJECT:{
  +                        // REVISIT: the constant FILTER_REJECT should be changed when new
  +                        // DOM LS specs gets published
  +
  +                        // fall through to SKIP since comment has no children.
  +                    }
  +                    case NodeFilter.FILTER_SKIP: { 
  +                        // REVISIT: the constant FILTER_SKIP should be changed when new
  +                        // DOM LS specs gets published
  +                        fCurrentNode.removeChild(comment);
  +                        // make sure we don't loose chars if next event is characters()
  +                        fFirstChunk = true;
  +                        return;
  +                    }
  +
  +                    default: {
  +                        // accept node 
  +                    }
  +                }
  +            }
  +
           }
           else {
               int comment =
  @@ -629,11 +683,38 @@
           if (DEBUG_EVENTS) {        
               System.out.println("==>processingInstruction ("+target+")");
           }
  -        if (!fDeferNodeExpansion) {
  -            setCharacterData(false);
  +        if (!fDeferNodeExpansion) {            
  +            if (fFilterReject) {
  +                return;
  +            }
               ProcessingInstruction pi =
                   fDocument.createProcessingInstruction(target, data.toString());
  +
  +
  +            setCharacterData(false);
               fCurrentNode.appendChild(pi);
  +            if (fDOMFilter !=null && 
  +                (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_PROCESSING_INSTRUCTION)!= 0) {
  +                short code = fDOMFilter.acceptNode(pi);
  +                switch (code) {
  +                    case DOMBuilderFilter.FILTER_INTERRUPT:{ 
  +                        throw new RuntimeException("The normal processing of the document was interrupted.");
  +                    }   
  +                    case NodeFilter.FILTER_REJECT:{
  +                        // fall through to SKIP since PI has no children.
  +                    }
  +                    case NodeFilter.FILTER_SKIP: {
  +                        fCurrentNode.removeChild(pi);
  +                        // fFirstChunk must be set to true so that data
  +                        // won't be lost in the case where the child before PI is
  +                        // a text node and the next event is characters.
  +                        fFirstChunk = true;
  +                        return;
  +                    }
  +                    default: {
  +                    }
  +                }
  +            }
           }
           else {
               int pi = fDeferredDocumentImpl.
  @@ -832,6 +913,9 @@
               System.out.println("==>startElement ("+element.rawname+")");
           }
           if (!fDeferNodeExpansion) {
  +            if (fFilterReject) {
  +                return;
  +            }
               Element el = createElementNode(element);
               int attrCount = attributes.getLength();
               for (int i = 0; i < attrCount; i++) {
  @@ -876,6 +960,27 @@
               }
   
               setCharacterData(false);
  +            // filter nodes
  +            if (fDOMFilter != null) {
  +                short code = fDOMFilter.startContainer(el);
  +                switch (code) {
  +                    case DOMBuilderFilter.FILTER_INTERRUPT:{ 
  +                        throw new RuntimeException("The normal processing of the document was interrupted.");
  +                    }   
  +                    case NodeFilter.FILTER_REJECT:{ 
  +                        fFilterReject = true;
  +                        fRejectedElement.setValues(element);
  +                        return;
  +                    }
  +                    case NodeFilter.FILTER_SKIP: { 
  +                        fSkippedElemStack.push(element);
  +                        return;
  +                    }
  +                    default: {
  +                    }
  +                }
  +            }
  +
               fCurrentNode.appendChild(el);
               fCurrentNode = el;
           }
  @@ -954,6 +1059,10 @@
           }
   
           if (!fDeferNodeExpansion) {
  +
  +            if (fFilterReject) {
  +                return;
  +            }
               if (fInCDATASection && fCreateCDATANodes) {
                   if (fCurrentCDATASection == null) {
                       fCurrentCDATASection =
  @@ -1066,10 +1175,9 @@
        */
       public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
   
  -        if (!fIncludeIgnorableWhitespace) {
  +        if (!fIncludeIgnorableWhitespace || fFilterReject) {
               return;
           }
  -
           if (!fDeferNodeExpansion) {
               Node child = fCurrentNode.getLastChild();
               if (child != null && child.getNodeType() == Node.TEXT_NODE) {
  @@ -1108,15 +1216,73 @@
               System.out.println("==>endElement ("+element.rawname+")");
           }
           if (!fDeferNodeExpansion) {
  -            setCharacterData(false);
  -            fCurrentNode = fCurrentNode.getParentNode();
  +            
  +            if (fDOMFilter != null) {            
  +                if (fFilterReject) {
  +                    if (element.equals(fRejectedElement)) {
  +                     fFilterReject = false;
  +                    }
  +                    return;
  +                }
  +                if (!fSkippedElemStack.isEmpty()) {
  +                    if (fSkippedElemStack.peek().equals(element)) {
  +                        fSkippedElemStack.pop();
  +                        return;
  +                    }
  +                }
  +                setCharacterData(false);
  +                if ((fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ELEMENT)!=0) {
  +                    short code = fDOMFilter.acceptNode(fCurrentNode);
  +                    switch (code) {
  +                        case DOMBuilderFilter.FILTER_INTERRUPT:{ 
  +                            throw new RuntimeException("The normal processing of the document was interrupted.");
  +                        }   
  +                        case NodeFilter.FILTER_REJECT:{
  +                            Node parent = fCurrentNode.getParentNode();                    
  +                            parent.removeChild(fCurrentNode);
  +                            fCurrentNode = parent;
  +                            return;
  +                        }
  +                        case NodeFilter.FILTER_SKIP: { 
  +                            // make sure that if any char data is available 
  +                            // the fFirstChunk is true, so that if the next event
  +                            // is characters(), and the last node is text, we will copy
  +                            // the value already in the text node to fStringBuffer 
  +                            // (not to loose it).
  +                            fFirstChunk = true;
  +
  +                            // replace children
  +                            Node parent = fCurrentNode.getParentNode();
  +                            NodeList ls = fCurrentNode.getChildNodes();
  +                            int length = ls.getLength();
  +
  +                            for (int i=0;i<length;i++) {
  +                                parent.appendChild(ls.item(0));
  +                            }                               
  +                            parent.removeChild(fCurrentNode);
  +                            fCurrentNode = parent;
  +                            
  +                            return;
  +                        }
  +
  +                        default: { }
  +                    }
  +                }
  +                fCurrentNode = fCurrentNode.getParentNode();
  +            
  +            } // end-if DOMFilter
  +            else {
  +                setCharacterData(false);
  +                fCurrentNode = fCurrentNode.getParentNode();
  +            }
  +            
           }
           else {
               fCurrentNodeIndex =
                   fDeferredDocumentImpl.getParentNode(fCurrentNodeIndex, false);
           }
   
  -
  +        
       } // endElement(QName)
   
   
  @@ -1127,8 +1293,14 @@
        * @throws XNIException Thrown by handler to signal an error.
        */
       public void startCDATA(Augmentations augs) throws XNIException {
  -        setCharacterData(false);
  +
           fInCDATASection = true;
  +        if (!fDeferNodeExpansion) {
  +            if (fFilterReject) {
  +                return;
  +            }
  +            setCharacterData(false);
  +        }
       } // startCDATA()
   
       /**
  @@ -1141,7 +1313,36 @@
   
           fInCDATASection = false;
           if (!fDeferNodeExpansion) {
  +
  +            if (fFilterReject) {
  +                return;
  +            }
  +
               if (fCurrentCDATASection !=null) {
  +
  +                if (fDOMFilter !=null && 
  +                    (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_CDATA_SECTION)!= 0) {
  +                    short code = fDOMFilter.acceptNode(fCurrentCDATASection);
  +                    switch (code) {
  +                        case DOMBuilderFilter.FILTER_INTERRUPT:{ 
  +                            throw new RuntimeException("The normal processing of the document was interrupted.");
  +                             }   
  +                        case NodeFilter.FILTER_REJECT:{
  +                            // fall through to SKIP since CDATA section has no children.
  +                        }
  +                        case NodeFilter.FILTER_SKIP: { 
  +                            Node parent = fCurrentNode.getParentNode();                    
  +                            parent.removeChild(fCurrentCDATASection);
  +                            fCurrentNode = parent;
  +                            return;
  +                        }
  +
  +                        default: {
  +                            // accept node 
  +                        }
  +                    }
  +                }
  +
                   fCurrentNode = fCurrentNode.getParentNode();
                   fCurrentCDATASection = null;
               }
  @@ -1197,35 +1398,70 @@
               System.out.println("==>endGeneralEntity: ("+name+")");
           }
           if (!fDeferNodeExpansion) {
  +
  +            if (fFilterReject) {
  +                return;
  +            }
               setCharacterData(true); 
   
               if (fDocumentType != null) {
                   // get current entity declaration
                   NamedNodeMap entities = fDocumentType.getEntities();
                   fCurrentEntityDecl = (EntityImpl) entities.getNamedItem(name);
  -            }
  -            if (fCurrentEntityDecl != null) {            
  -                if (fCurrentEntityDecl != null && fCurrentEntityDecl.getFirstChild() == null) {
  -                    fCurrentEntityDecl.setReadOnly(false, true);
  -                    Node child = fCurrentNode.getFirstChild();
  -                    while (child != null) {
  -                        Node copy = child.cloneNode(true);
  -                        fCurrentEntityDecl.appendChild(copy);
  -                        child = child.getNextSibling();
  -                     }
  -                    fCurrentEntityDecl.setReadOnly(true, true);
  -                    
  -                    //entities.setNamedItem(fCurrentEntityDecl);
  +                if (fCurrentEntityDecl != null) {            
  +                    if (fCurrentEntityDecl != null && fCurrentEntityDecl.getFirstChild() == null) {
  +                        fCurrentEntityDecl.setReadOnly(false, true);
  +                        Node child = fCurrentNode.getFirstChild();
  +                        while (child != null) {
  +                            Node copy = child.cloneNode(true);
  +                            fCurrentEntityDecl.appendChild(copy);
  +                            child = child.getNextSibling();
  +                         }
  +                        fCurrentEntityDecl.setReadOnly(true, true);
  +
  +                        //entities.setNamedItem(fCurrentEntityDecl);
  +                    }
  +                    fCurrentEntityDecl = null;
                   }
  -                fCurrentEntityDecl = null;
  +
               }
  +
  +            boolean removeEntityRef = false;
               if (fCreateEntityRefNodes) {
                   if (fDocumentImpl != null) {                
                       // Make entity ref node read only
                       ((NodeImpl)fCurrentNode).setReadOnly(true, true);
                   }
  -                fCurrentNode = fCurrentNode.getParentNode();
  -            } else {  
  +
  +                if (fDOMFilter !=null && 
  +                    (fDOMFilter.getWhatToShow() & NodeFilter.SHOW_ENTITY_REFERENCE)!= 0) {
  +                    short code = fDOMFilter.acceptNode(fCurrentNode);
  +                    switch (code) {
  +                        case DOMBuilderFilter.FILTER_INTERRUPT:{ 
  +                            throw new RuntimeException("The normal processing of the document was interrupted.");
  +                        }   
  +                        case NodeFilter.FILTER_REJECT:{ 
  +                            Node parent = fCurrentNode.getParentNode();
  +                            parent.removeChild(fCurrentNode);
  +                            fCurrentNode = parent;
  +                            return;
  +                            
  +                        }
  +                        case NodeFilter.FILTER_SKIP: {
  +                            // make sure we don't loose chars if next event is characters()
  +                            fFirstChunk = true;
  +                            removeEntityRef = true;
  +                            break;
  +                        }
  +
  +                        default: {
  +                            fCurrentNode = fCurrentNode.getParentNode(); 
  +                        }
  +                    }
  +                }
  +            } 
  +
  +            if (!fCreateEntityRefNodes || removeEntityRef) {
                   // move entity reference children to the list of 
                   // siblings of its parent and remove entity reference
                   NodeList children = fCurrentNode.getChildNodes();
  @@ -2171,29 +2407,66 @@
           return attr;
       }
   
  -    // If data rececived in more than one chunk, the data
  -    // is stored in StringBuffer.      
  -    // This function is called then the state is changed and the 
  -    // data needs to be appended to the current node
  +    /*
  +     * When the first characters() call is received, the data is stored in
  +     * a new Text node. If right after the first characters() we receive another chunk of data, 
  +     * the data from the Text node, following the new characters are appended
  +     * to the fStringBuffer and the text node data is set to empty.
  +     * 
  +     * This function is called when the state is changed and the
  +     * data must be appended to the current node.
  +     * 
  +     * Note: if DOMFilter is set, you must make sure that if Node is skipped, 
  +     * or removed fFistChunk must be set to true, otherwise some data can be lost.     
  +     * 
  +     */
       protected void  setCharacterData(boolean sawChars){
  +
           // handle character data
           fFirstChunk = sawChars;
  -        if (fStringBuffer.length() > 0) {
  -            // if we have data in the buffer we must have created
  -            // a text node already.
  -            Node child = fCurrentNode.getLastChild();
  -            // REVISIT: should this check be performed?
  -            if (child != null && child.getNodeType() == Node.TEXT_NODE) {
  -                if (fDocumentImpl != null) {
  -                    ((TextImpl)child).replaceData(fStringBuffer.toString());
  -                }
  -                else {
  -                    ((Text)child).setData(fStringBuffer.toString());
  +        
  +
  +        // if we have data in the buffer we must have created
  +        // a text node already.
  +       
  +        Node child = fCurrentNode.getLastChild();
  +        if (child != null) {        
  +            if (fStringBuffer.length() > 0) {
  +                // REVISIT: should this check be performed?
  +                if (child.getNodeType() == Node.TEXT_NODE) {
  +                    if (fDocumentImpl != null) {
  +                        ((TextImpl)child).replaceData(fStringBuffer.toString());
  +                    }
  +                    else {
  +                        ((Text)child).setData(fStringBuffer.toString());
  +                    }
                   }
  +                // reset string buffer
  +                fStringBuffer.setLength(0);
               }
  -            // reset string buffer
  -            fStringBuffer.setLength(0);
  -        }
  +
  +            if (fDOMFilter !=null) {
  +                if ((fDOMFilter.getWhatToShow() & NodeFilter.SHOW_TEXT)!= 0) {
  +                    short code = fDOMFilter.acceptNode(child);
  +                    switch (code) {
  +                        case DOMBuilderFilter.FILTER_INTERRUPT:{ 
  +                            throw new RuntimeException("The normal processing of the document was interrupted.");
  +                        }   
  +                        case NodeFilter.FILTER_REJECT:{
  +                            // fall through to SKIP since Comment has no children.
  +                        }
  +                        case NodeFilter.FILTER_SKIP: { 
  +                            fCurrentNode.removeChild(child);
  +                            return;
  +                        }
  +                        default: {
  +                            // accept node -- do nothing
  +                        }
  +                    }
  +                }
  +            }   // end-if fDOMFilter !=null
  +
  +        } // end-if child !=null
       }
   
       
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org