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]