mrglavas    2004/08/15 18:05:01

  Modified:    java/src/org/apache/xerces/xinclude XIncludeHandler.java
               java/src/org/apache/xerces/impl/msg
                        XIncludeMessages.properties
  Log:
  The XInclude 1.0 CR [1] states that: "It is a fatal error to attempt to

  replace an xi:include element appearing as the document (top-level)

  element in the source infoset with something other than a list of zero

  or more comments, zero or more processing instructions, and one

  element."

  

  We were allowing merged infosets with multiple or no root elements

  to pass through as well as those containing non-whitespace

  characters and unexpanded entity references outside of the root.

  This should be fixed for now except for an edge case involving

  text includes.

  

  [1] http://www.w3.org/TR/xinclude/#creating-result
  
  Revision  Changes    Path
  1.34      +105 -37   
xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeHandler.java
  
  Index: XIncludeHandler.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xerces/java/src/org/apache/xerces/xinclude/XIncludeHandler.java,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- XIncludeHandler.java      13 Aug 2004 19:15:30 -0000      1.33
  +++ XIncludeHandler.java      16 Aug 2004 01:05:01 -0000      1.34
  @@ -35,6 +35,7 @@
   import org.apache.xerces.util.URI;
   import org.apache.xerces.util.XMLAttributesImpl;
   import org.apache.xerces.util.XMLResourceIdentifierImpl;
  +import org.apache.xerces.util.XMLChar;
   import org.apache.xerces.util.XMLSymbols;
   import org.apache.xerces.util.URI.MalformedURIException;
   import org.apache.xerces.xni.Augmentations;
  @@ -273,9 +274,12 @@
       // used for passing features on to child XIncludeHandler objects
       protected ParserConfigurationSettings fSettings;
   
  -    // The current element depth.  We start at depth 0 (before we've reached any 
elements)
  +    // The current element depth.  We start at depth 0 (before we've reached any 
elements).
       // The first element is at depth 1.
       private int fDepth;
  +    
  +    // The current element depth of the result infoset.
  +    private int fResultDepth;
   
       // this value must be at least 1
       private static final int INITIAL_SIZE = 8;
  @@ -307,6 +311,9 @@
   
       // track whether a DTD is being parsed
       private boolean fInDTD;
  +    
  +    // track whether the root element of the result infoset has been processed
  +    private boolean fSeenRootElement;
   
       // Constructors
   
  @@ -336,11 +343,13 @@
           throws XNIException {
           fNamespaceContext = null;
           fDepth = 0;
  +        fResultDepth = 0;
           fNotations = new Vector();
           fUnparsedEntities = new Vector();
           fParentRelativeURI = null;
           fIsXML11 = false;
           fInDTD = false;
  +        fSeenRootElement = false;
   
           fBaseURIScope.clear();
           fBaseURI.clear();
  @@ -786,19 +795,26 @@
                       "FallbackChild",
                       new Object[] { element.rawname });
               }
  -            if (fDocumentHandler != null
  -                    && getState() == STATE_NORMAL_PROCESSING) {
  +            if (getState() == STATE_NORMAL_PROCESSING) {
  +                if (fResultDepth++ == 0 && isRootDocument()) {
  +                    checkMultipleRootElements();
  +                }
  +                if (fDocumentHandler != null) {
  +                    augs = modifyAugmentations(augs);
  +                    attributes = processAttributes(attributes);
  +                    fDocumentHandler.startElement(element, attributes, augs);
  +                }            
  +            }
  +        }
  +        else if (getState() == STATE_NORMAL_PROCESSING) {
  +            if (fResultDepth++ == 0 && isRootDocument()) {
  +                checkMultipleRootElements();
  +            }
  +            if (fDocumentHandler != null) {
                   augs = modifyAugmentations(augs);
                   attributes = processAttributes(attributes);
                   fDocumentHandler.startElement(element, attributes, augs);
  -            }
  -        }
  -        else if (
  -            fDocumentHandler != null
  -                && getState() == STATE_NORMAL_PROCESSING) {
  -            augs = modifyAugmentations(augs);
  -            attributes = processAttributes(attributes);
  -            fDocumentHandler.startElement(element, attributes, augs);
  +            }            
           }
       }
   
  @@ -838,20 +854,27 @@
                       "FallbackChild",
                       new Object[] { element.rawname });
               }
  -            if (fDocumentHandler != null
  -                    && getState() == STATE_NORMAL_PROCESSING) {
  +            if (getState() == STATE_NORMAL_PROCESSING) {
  +                if (fResultDepth == 0 && isRootDocument()) {
  +                    checkMultipleRootElements();
  +                }
  +                if (fDocumentHandler != null) {
  +                    augs = modifyAugmentations(augs);
  +                    attributes = processAttributes(attributes);
  +                    fDocumentHandler.emptyElement(element, attributes, augs);
  +                }
  +            }
  +        }
  +        else if (getState() == STATE_NORMAL_PROCESSING) {
  +            if (fResultDepth == 0 && isRootDocument()) {
  +                checkMultipleRootElements();
  +            }
  +            if (fDocumentHandler != null) {
                   augs = modifyAugmentations(augs);
                   attributes = processAttributes(attributes);
                   fDocumentHandler.emptyElement(element, attributes, augs);
               }
           }
  -        else if (
  -            fDocumentHandler != null
  -                && getState() == STATE_NORMAL_PROCESSING) {
  -            augs = modifyAugmentations(augs);
  -            attributes = processAttributes(attributes);
  -            fDocumentHandler.emptyElement(element, attributes, augs);
  -        }
           // reset the out of scope stack elements
           setSawFallback(fDepth + 1, false);
           setSawInclude(fDepth + 1, false);
  @@ -885,6 +908,7 @@
           else if (
               fDocumentHandler != null
                   && getState() == STATE_NORMAL_PROCESSING) {
  +            --fResultDepth;
               fDocumentHandler.endElement(element, augs);
           }
   
  @@ -913,9 +937,15 @@
           String encoding,
           Augmentations augs)
           throws XNIException {
  -        if (fDocumentHandler != null
  -            && getState() == STATE_NORMAL_PROCESSING) {
  -            fDocumentHandler.startGeneralEntity(name, resId, encoding, augs);
  +        if (getState() == STATE_NORMAL_PROCESSING) {
  +            if (fResultDepth == 0 && isRootDocument()) {
  +                if (augs != null && 
Boolean.TRUE.equals(augs.getItem(Constants.ENTITY_SKIPPED))) {
  +                    reportFatalError("UnexpandedEntityReferenceIllegal");
  +                }
  +            }
  +            else if (fDocumentHandler != null) {
  +                fDocumentHandler.startGeneralEntity(name, resId, encoding, augs);
  +            }
           }
       }
   
  @@ -930,48 +960,61 @@
       public void endGeneralEntity(String name, Augmentations augs)
           throws XNIException {
           if (fDocumentHandler != null
  -            && getState() == STATE_NORMAL_PROCESSING) {
  +            && getState() == STATE_NORMAL_PROCESSING
  +            && (fResultDepth != 0 || !isRootDocument())) {
               fDocumentHandler.endGeneralEntity(name, augs);
           }
       }
   
       public void characters(XMLString text, Augmentations augs)
           throws XNIException {
  -        if (fDocumentHandler != null
  -            && getState() == STATE_NORMAL_PROCESSING) {
  -            // we need to change the depth like this so that modifyAugmentations() 
works
  -            fDepth++;
  -            augs = modifyAugmentations(augs);
  -            fDocumentHandler.characters(text, augs);
  -            fDepth--;
  +        if (getState() == STATE_NORMAL_PROCESSING) {
  +            if (fResultDepth == 0 && isRootDocument()) {
  +                checkWhitespace(text);
  +            }
  +            else if (fDocumentHandler != null) {
  +                // we need to change the depth like this so that 
modifyAugmentations() works
  +                fDepth++;
  +                augs = modifyAugmentations(augs);
  +                fDocumentHandler.characters(text, augs);
  +                fDepth--;
  +            }
           }
       }
   
       public void ignorableWhitespace(XMLString text, Augmentations augs)
           throws XNIException {
           if (fDocumentHandler != null
  -            && getState() == STATE_NORMAL_PROCESSING) {
  +            && getState() == STATE_NORMAL_PROCESSING
  +            && (fResultDepth != 0 || !isRootDocument())) {
               fDocumentHandler.ignorableWhitespace(text, augs);
           }
       }
   
       public void startCDATA(Augmentations augs) throws XNIException {
           if (fDocumentHandler != null
  -            && getState() == STATE_NORMAL_PROCESSING) {
  +            && getState() == STATE_NORMAL_PROCESSING
  +            && (fResultDepth != 0 || !isRootDocument())) {
               fDocumentHandler.startCDATA(augs);
           }
       }
   
       public void endCDATA(Augmentations augs) throws XNIException {
           if (fDocumentHandler != null
  -            && getState() == STATE_NORMAL_PROCESSING) {
  +            && getState() == STATE_NORMAL_PROCESSING
  +            && (fResultDepth != 0 || !isRootDocument())) {
               fDocumentHandler.endCDATA(augs);
           }
       }
   
       public void endDocument(Augmentations augs) throws XNIException {
  -        if (isRootDocument() && fDocumentHandler != null) {
  -            fDocumentHandler.endDocument(augs);
  +        if (isRootDocument()) {
  +            if (!fSeenRootElement) {
  +                reportFatalError("RootElementRequired");
  +            }
  +            if (fDocumentHandler != null) {
  +                fDocumentHandler.endDocument(augs);
  +            }
           }
       }
   
  @@ -2174,6 +2217,31 @@
           else {
               fParentXIncludeHandler.checkAndSendNotation(not);
           }
  +    }
  +    
  +    /**
  +     * Checks whether the string only contains white space characters.
  +     * 
  +     * @param value the text to check
  +     */
  +    private void checkWhitespace(XMLString value) {
  +        int end = value.offset + value.length;
  +        for (int i = value.offset; i < end; ++i) {
  +            if (!XMLChar.isSpace(value.ch[i])) {
  +                reportFatalError("ContentIllegalAtTopLevel");
  +                return;
  +            }
  +        }
  +    }
  +    
  +    /**
  +     * Checks whether the root element has already been processed.
  +     */
  +    private void checkMultipleRootElements() {
  +        if (fSeenRootElement) {
  +            reportFatalError("MultipleRootElements");
  +        }
  +        fSeenRootElement = true;
       }
   
       // It would be nice if we didn't have to repeat code like this, but there's no 
interface that has
  
  
  
  1.10      +4 -0      
xml-xerces/java/src/org/apache/xerces/impl/msg/XIncludeMessages.properties
  
  Index: XIncludeMessages.properties
  ===================================================================
  RCS file: 
/home/cvs/xml-xerces/java/src/org/apache/xerces/impl/msg/XIncludeMessages.properties,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- XIncludeMessages.properties       20 Jul 2004 04:09:26 -0000      1.9
  +++ XIncludeMessages.properties       16 Aug 2004 01:05:01 -0000      1.10
  @@ -19,6 +19,10 @@
   XpointerMissing = xpointer attribute must be present when href attribute is absent.
   AcceptMalformed = Characters outside the range #x20 through #x7E are not allowed in 
the value of the 'accept' attribute of an 'include' element.
   AcceptLanguageMalformed = Characters outside the range #x20 through #x7E are not 
allowed in the value of the 'accept-language' attribute of an 'include' element.
  +RootElementRequired = The root element is required in a well-formed document.
  +MultipleRootElements = A well-formed document must not contain multiple root 
elements.
  +ContentIllegalAtTopLevel = The replacement of an 'include' element appearing as the 
document element in the top-level source infoset cannot contain characters.
  +UnexpandedEntityReferenceIllegal = The replacement of an 'include' element 
appearing as the document element in the top-level source infoset cannot contain 
unexpanded entity references.
   
   # Messages from erroneous set-up
   IncompatibleNamespaceContext = The type of the NamespaceContext is incompatible 
with using XInclude; it must be an instance of XIncludeNamespaceSupport
  
  
  

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

Reply via email to