| /* |
| * reserved comment block |
| * DO NOT REMOVE OR ALTER! |
| */ |
| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 1999-2003 The Apache Software Foundation. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Xerces" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache", |
| * nor may "Apache" appear in their name, without prior written |
| * permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 2002, International |
| * Business Machines, Inc., http://www.apache.org. For more |
| * information on the Apache Software Foundation, please see |
| * <http://www.apache.org/>. |
| */ |
| |
| package com.sun.org.apache.xerces.internal.impl.dtd; |
| |
| import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; |
| import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; |
| import com.sun.org.apache.xerces.internal.util.XMLSymbols; |
| import com.sun.org.apache.xerces.internal.xni.Augmentations; |
| import com.sun.org.apache.xerces.internal.xni.NamespaceContext; |
| import com.sun.org.apache.xerces.internal.xni.QName; |
| import com.sun.org.apache.xerces.internal.xni.XMLAttributes; |
| import com.sun.org.apache.xerces.internal.xni.XNIException; |
| |
| /** |
| * The DTD validator. The validator implements a document |
| * filter: receiving document events from the scanner; validating |
| * the content and structure; augmenting the InfoSet, if applicable; |
| * and notifying the parser of the information resulting from the |
| * validation process. |
| * <p> Formerly, this component also handled DTD events and grammar construction. |
| * To facilitate the development of a meaningful DTD grammar caching/preparsing |
| * framework, this functionality has been moved into the XMLDTDLoader |
| * class. Therefore, this class no longer implements the DTDFilter |
| * or DTDContentModelFilter interfaces. |
| * <p> |
| * This component requires the following features and properties from the |
| * component manager that uses it: |
| * <ul> |
| * <li>http://xml.org/sax/features/namespaces</li> |
| * <li>http://xml.org/sax/features/validation</li> |
| * <li>http://apache.org/xml/features/validation/dynamic</li> |
| * <li>http://apache.org/xml/properties/internal/symbol-table</li> |
| * <li>http://apache.org/xml/properties/internal/error-reporter</li> |
| * <li>http://apache.org/xml/properties/internal/grammar-pool</li> |
| * <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li> |
| * </ul> |
| * |
| * @xerces.internal |
| * |
| * @author Elena Litani, IBM |
| * @author Michael Glavassevich, IBM |
| * |
| |
| */ |
| public class XML11NSDTDValidator extends XML11DTDValidator { |
| |
| /** Attribute QName. */ |
| private QName fAttributeQName = new QName(); |
| |
| /** Bind namespaces */ |
| protected final void startNamespaceScope(QName element, XMLAttributes attributes, Augmentations augs) |
| throws XNIException { |
| |
| // add new namespace context |
| fNamespaceContext.pushContext(); |
| |
| if (element.prefix == XMLSymbols.PREFIX_XMLNS) { |
| fErrorReporter.reportError( |
| XMLMessageFormatter.XMLNS_DOMAIN, |
| "ElementXMLNSPrefix", |
| new Object[] { element.rawname }, |
| XMLErrorReporter.SEVERITY_FATAL_ERROR); |
| } |
| |
| // search for new namespace bindings |
| int length = attributes.getLength(); |
| for (int i = 0; i < length; i++) { |
| String localpart = attributes.getLocalName(i); |
| String prefix = attributes.getPrefix(i); |
| // when it's of form xmlns="..." or xmlns:prefix="...", |
| // it's a namespace declaration. but prefix:xmlns="..." isn't. |
| if (prefix == XMLSymbols.PREFIX_XMLNS || prefix == XMLSymbols.EMPTY_STRING |
| && localpart == XMLSymbols.PREFIX_XMLNS) { |
| |
| // get the internalized value of this attribute |
| String uri = fSymbolTable.addSymbol(attributes.getValue(i)); |
| |
| // 1. "xmlns" can't be bound to any namespace |
| if (prefix == XMLSymbols.PREFIX_XMLNS && localpart == XMLSymbols.PREFIX_XMLNS) { |
| fErrorReporter.reportError( |
| XMLMessageFormatter.XMLNS_DOMAIN, |
| "CantBindXMLNS", |
| new Object[] { attributes.getQName(i)}, |
| XMLErrorReporter.SEVERITY_FATAL_ERROR); |
| } |
| |
| // 2. the namespace for "xmlns" can't be bound to any prefix |
| if (uri == NamespaceContext.XMLNS_URI) { |
| fErrorReporter.reportError( |
| XMLMessageFormatter.XMLNS_DOMAIN, |
| "CantBindXMLNS", |
| new Object[] { attributes.getQName(i)}, |
| XMLErrorReporter.SEVERITY_FATAL_ERROR); |
| } |
| |
| // 3. "xml" can't be bound to any other namespace than it's own |
| if (localpart == XMLSymbols.PREFIX_XML) { |
| if (uri != NamespaceContext.XML_URI) { |
| fErrorReporter.reportError( |
| XMLMessageFormatter.XMLNS_DOMAIN, |
| "CantBindXML", |
| new Object[] { attributes.getQName(i)}, |
| XMLErrorReporter.SEVERITY_FATAL_ERROR); |
| } |
| } |
| // 4. the namespace for "xml" can't be bound to any other prefix |
| else { |
| if (uri == NamespaceContext.XML_URI) { |
| fErrorReporter.reportError( |
| XMLMessageFormatter.XMLNS_DOMAIN, |
| "CantBindXML", |
| new Object[] { attributes.getQName(i)}, |
| XMLErrorReporter.SEVERITY_FATAL_ERROR); |
| } |
| } |
| |
| prefix = localpart != XMLSymbols.PREFIX_XMLNS ? localpart : XMLSymbols.EMPTY_STRING; |
| |
| // Declare prefix in context. Removing the association between a prefix and a |
| // namespace name is permitted in XML 1.1, so if the uri value is the empty string, |
| // the prefix is being unbound. -- mrglavas |
| fNamespaceContext.declarePrefix(prefix, uri.length() != 0 ? uri : null); |
| } |
| } |
| |
| // bind the element |
| String prefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING; |
| element.uri = fNamespaceContext.getURI(prefix); |
| if (element.prefix == null && element.uri != null) { |
| element.prefix = XMLSymbols.EMPTY_STRING; |
| } |
| if (element.prefix != null && element.uri == null) { |
| fErrorReporter.reportError( |
| XMLMessageFormatter.XMLNS_DOMAIN, |
| "ElementPrefixUnbound", |
| new Object[] { element.prefix, element.rawname }, |
| XMLErrorReporter.SEVERITY_FATAL_ERROR); |
| } |
| |
| // bind the attributes |
| for (int i = 0; i < length; i++) { |
| attributes.getName(i, fAttributeQName); |
| String aprefix = fAttributeQName.prefix != null ? fAttributeQName.prefix : XMLSymbols.EMPTY_STRING; |
| String arawname = fAttributeQName.rawname; |
| if (arawname == XMLSymbols.PREFIX_XMLNS) { |
| fAttributeQName.uri = fNamespaceContext.getURI(XMLSymbols.PREFIX_XMLNS); |
| attributes.setName(i, fAttributeQName); |
| } else if (aprefix != XMLSymbols.EMPTY_STRING) { |
| fAttributeQName.uri = fNamespaceContext.getURI(aprefix); |
| if (fAttributeQName.uri == null) { |
| fErrorReporter.reportError( |
| XMLMessageFormatter.XMLNS_DOMAIN, |
| "AttributePrefixUnbound", |
| new Object[] { element.rawname, arawname, aprefix }, |
| XMLErrorReporter.SEVERITY_FATAL_ERROR); |
| } |
| attributes.setName(i, fAttributeQName); |
| } |
| } |
| |
| // verify that duplicate attributes don't exist |
| // Example: <foo xmlns:a='NS' xmlns:b='NS' a:attr='v1' b:attr='v2'/> |
| int attrCount = attributes.getLength(); |
| for (int i = 0; i < attrCount - 1; i++) { |
| String auri = attributes.getURI(i); |
| if (auri == null || auri == NamespaceContext.XMLNS_URI) { |
| continue; |
| } |
| String alocalpart = attributes.getLocalName(i); |
| for (int j = i + 1; j < attrCount; j++) { |
| String blocalpart = attributes.getLocalName(j); |
| String buri = attributes.getURI(j); |
| if (alocalpart == blocalpart && auri == buri) { |
| fErrorReporter.reportError( |
| XMLMessageFormatter.XMLNS_DOMAIN, |
| "AttributeNSNotUnique", |
| new Object[] { element.rawname, alocalpart, auri }, |
| XMLErrorReporter.SEVERITY_FATAL_ERROR); |
| } |
| } |
| } |
| |
| } // startNamespaceScope(QName,XMLAttributes) |
| |
| /** Handles end element. */ |
| protected void endNamespaceScope(QName element, Augmentations augs, boolean isEmpty) |
| throws XNIException { |
| |
| // bind element |
| String eprefix = element.prefix != null ? element.prefix : XMLSymbols.EMPTY_STRING; |
| element.uri = fNamespaceContext.getURI(eprefix); |
| if (element.uri != null) { |
| element.prefix = eprefix; |
| } |
| |
| // call handlers |
| if (fDocumentHandler != null) { |
| if (!isEmpty) { |
| fDocumentHandler.endElement(element, augs); |
| } |
| } |
| |
| // pop context |
| fNamespaceContext.popContext(); |
| |
| } // endNamespaceScope(QName,boolean) |
| } |