org.apache.xerces.dom.DOMNormalizer Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xerces.dom;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Vector;
import org.apache.xerces.impl.Constants;
import org.apache.xerces.impl.RevalidationHandler;
import org.apache.xerces.impl.dtd.XMLDTDLoader;
import org.apache.xerces.impl.dtd.XMLDTDValidator;
import org.apache.xerces.impl.dv.XSSimpleType;
import org.apache.xerces.impl.xs.util.SimpleLocator;
import org.apache.xerces.util.AugmentationsImpl;
import org.apache.xerces.util.NamespaceSupport;
import org.apache.xerces.util.SymbolTable;
import org.apache.xerces.util.XML11Char;
import org.apache.xerces.util.XMLChar;
import org.apache.xerces.util.XMLSymbols;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLDocumentHandler;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.grammars.XMLGrammarDescription;
import org.apache.xerces.xni.parser.XMLComponent;
import org.apache.xerces.xni.parser.XMLDocumentSource;
import org.apache.xerces.xs.AttributePSVI;
import org.apache.xerces.xs.ElementPSVI;
import org.apache.xerces.xs.XSTypeDefinition;
import org.w3c.dom.Attr;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMError;
import org.w3c.dom.DOMErrorHandler;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Entity;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
/**
* This class adds implementation for normalizeDocument method.
* It acts as if the document was going through a save and load cycle, putting
* the document in a "normal" form. The actual result depends on the features being set
* and governing what operations actually take place. See setNormalizationFeature for details.
* Noticeably this method normalizes Text nodes, makes the document "namespace wellformed",
* according to the algorithm described below in pseudo code, by adding missing namespace
* declaration attributes and adding or changing namespace prefixes, updates the replacement
* tree of EntityReference nodes, normalizes attribute values, etc.
* Mutation events, when supported, are generated to reflect the changes occuring on the
* document.
* See Namespace normalization for details on how namespace declaration attributes and prefixes
* are normalized.
*
* NOTE: There is an initial support for DOM revalidation with XML Schema as a grammar.
* The tree might not be validated correctly if entityReferences, CDATA sections are
* present in the tree. The PSVI information is not exposed, normalized data (including element
* default content is not available).
*
* @xerces.experimental
*
* @author Elena Litani, IBM
* @author Neeraj Bajaj, Sun Microsystems, inc.
* @version $Id: DOMNormalizer.java 1085513 2011-03-25 18:50:09Z mrglavas $
*/
public class DOMNormalizer implements XMLDocumentHandler {
//
// constants
//
/** Debug normalize document*/
protected final static boolean DEBUG_ND = false;
/** Debug namespace fix up algorithm*/
protected final static boolean DEBUG = false;
/** Debug document handler events */
protected final static boolean DEBUG_EVENTS = false;
/** prefix added by namespace fixup algorithm should follow a pattern "NS" + index*/
protected final static String PREFIX = "NS";
//
// Data
//
protected DOMConfigurationImpl fConfiguration = null;
protected CoreDocumentImpl fDocument = null;
protected final XMLAttributesProxy fAttrProxy = new XMLAttributesProxy();
protected final QName fQName = new QName();
/** Validation handler represents validator instance. */
protected RevalidationHandler fValidationHandler;
/** symbol table */
protected SymbolTable fSymbolTable;
/** error handler. may be null. */
protected DOMErrorHandler fErrorHandler;
/**
* Cached {@link DOMError} impl.
* The same object is re-used to report multiple errors.
*/
private final DOMErrorImpl fError = new DOMErrorImpl();
// Validation against namespace aware grammar
protected boolean fNamespaceValidation = false;
// Update PSVI information in the tree
protected boolean fPSVI = false;
/** The namespace context of this document: stores namespaces in scope */
protected final NamespaceContext fNamespaceContext = new NamespaceSupport();
/** Stores all namespace bindings on the current element */
protected final NamespaceContext fLocalNSBinder = new NamespaceSupport();
/** list of attributes */
protected final ArrayList fAttributeList = new ArrayList(5);
/** DOM Locator - for namespace fixup algorithm */
protected final DOMLocatorImpl fLocator = new DOMLocatorImpl();
/** for setting the PSVI */
protected Node fCurrentNode = null;
private final QName fAttrQName = new QName();
// attribute value normalization
final XMLString fNormalizedValue = new XMLString(new char[16], 0, 0);
/**
* If the user stops the process, this exception will be thrown.
*/
public static final RuntimeException abort = new RuntimeException();
/** Empty string to pass to the validator. **/
public static final XMLString EMPTY_STRING = new XMLString();
// Check if element content is all "ignorable whitespace"
private boolean fAllWhitespace = false;
// Constructor
//
public DOMNormalizer(){}
/**
* Normalizes document.
* Note: reset() must be called before this method.
*/
protected void normalizeDocument(CoreDocumentImpl document, DOMConfigurationImpl config) {
fDocument = document;
fConfiguration = config;
fAllWhitespace = false;
fNamespaceValidation = false;
String xmlVersion = fDocument.getXmlVersion();
String schemaType = null;
String [] schemaLocations = null;
// intialize and reset DOMNormalizer component
//
fSymbolTable = (SymbolTable) fConfiguration.getProperty(DOMConfigurationImpl.SYMBOL_TABLE);
// reset namespace context
fNamespaceContext.reset();
fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) {
String schemaLang = (String)fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_LANGUAGE);
if (schemaLang != null && schemaLang.equals(Constants.NS_XMLSCHEMA)) {
schemaType = XMLGrammarDescription.XML_SCHEMA;
fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA, true);
fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA_FULL_CHECKING, true);
// report fatal error on DOM Level 1 nodes
fNamespaceValidation = true;
// check if we need to fill in PSVI
fPSVI = ((fConfiguration.features & DOMConfigurationImpl.PSVI) !=0)?true:false;
}
else {
schemaType = XMLGrammarDescription.XML_DTD;
if (schemaLang != null) {
schemaLocations = (String []) fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_SOURCE);
}
fConfiguration.setDTDValidatorFactory(xmlVersion);
fValidationHandler = CoreDOMImplementationImpl.singleton.getValidator(schemaType, xmlVersion);
fPSVI = false;
}
fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
// reset ID table
fDocument.clearIdentifiers();
if (fValidationHandler != null) {
// reset the validation handler
((XMLComponent) fValidationHandler).reset(fConfiguration);
}
}
else {
fValidationHandler = null;
}
fErrorHandler = (DOMErrorHandler) fConfiguration.getParameter(Constants.DOM_ERROR_HANDLER);
if (fValidationHandler != null) {
fValidationHandler.setDocumentHandler(this);
fValidationHandler.startDocument(
new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI,
-1, -1 ), fDocument.encoding, fNamespaceContext, null);
fValidationHandler.xmlDecl(fDocument.getXmlVersion(),
fDocument.getXmlEncoding(), fDocument.getXmlStandalone() ? "yes" : "no", null);
}
try {
if (schemaType == XMLGrammarDescription.XML_DTD) {
processDTD(xmlVersion, schemaLocations != null ? schemaLocations[0] : null);
}
Node kid, next;
for (kid = fDocument.getFirstChild(); kid != null; kid = next) {
next = kid.getNextSibling();
kid = normalizeNode(kid);
if (kid != null) { // don't advance
next = kid;
}
}
// release resources
if (fValidationHandler != null) {
fValidationHandler.endDocument(null);
fValidationHandler.setDocumentHandler(null);
CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
fValidationHandler = null;
}
}
catch (RuntimeException e) {
// release resources
if (fValidationHandler != null) {
fValidationHandler.setDocumentHandler(null);
CoreDOMImplementationImpl.singleton.releaseValidator(schemaType, xmlVersion, fValidationHandler);
fValidationHandler = null;
}
if (e == abort) {
return; // processing aborted by the user
}
throw e; // otherwise re-throw.
}
}
/**
*
* This method acts as if the document was going through a save
* and load cycle, putting the document in a "normal" form. The actual result
* depends on the features being set and governing what operations actually
* take place. See setNormalizationFeature for details. Noticeably this method
* normalizes Text nodes, makes the document "namespace wellformed",
* according to the algorithm described below in pseudo code, by adding missing
* namespace declaration attributes and adding or changing namespace prefixes, updates
* the replacement tree of EntityReference nodes,normalizes attribute values, etc.
*
* @param node Modified node or null. If node is returned, we need
* to normalize again starting on the node returned.
* @return the normalized Node
*/
protected Node normalizeNode (Node node){
int type = node.getNodeType();
boolean wellformed;
fLocator.fRelatedNode=node;
switch (type) {
case Node.DOCUMENT_TYPE_NODE: {
if (DEBUG_ND) {
System.out.println("==>normalizeNode:{doctype}");
}
// REVISIT: well-formedness encoding info
break;
}
case Node.ELEMENT_NODE: {
if (DEBUG_ND) {
System.out.println("==>normalizeNode:{element} "+node.getNodeName());
}
//do the name check only when version of the document was changed &
//application has set the value of well-formed features to true
if (fDocument.errorChecking) {
if ( ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) &&
fDocument.isXMLVersionChanged()){
if (fNamespaceValidation){
wellformed = CoreDocumentImpl.isValidQName(node.getPrefix() , node.getLocalName(), fDocument.isXML11Version());
}
else {
wellformed = CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version());
}
if (!wellformed){
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"wf-invalid-character-in-node-name",
new Object[]{"Element", node.getNodeName()});
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
"wf-invalid-character-in-node-name");
}
}
}
// push namespace context
fNamespaceContext.pushContext();
fLocalNSBinder.reset();
ElementImpl elem = (ElementImpl)node;
if (elem.needsSyncChildren()) {
elem.synchronizeChildren();
}
AttributeMap attributes = (elem.hasAttributes()) ? (AttributeMap) elem.getAttributes() : null;
// fix namespaces and remove default attributes
if ((fConfiguration.features & DOMConfigurationImpl.NAMESPACES) !=0) {
// fix namespaces
// normalize attribute values
// remove default attributes
namespaceFixUp(elem, attributes);
if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) {
// Namespace declarations may have been added by namespace fix-up. Need
// to fetch the AttributeMap again if it contained no attributes prior
// to namespace fix-up.
if (attributes == null) {
attributes = (elem.hasAttributes()) ? (AttributeMap) elem.getAttributes() : null;
}
if (attributes != null) {
for (int i = 0; i < attributes.getLength(); ++i) {
Attr att = (Attr)attributes.getItem(i);
if (XMLSymbols.PREFIX_XMLNS.equals(att.getPrefix()) ||
XMLSymbols.PREFIX_XMLNS.equals(att.getName())) {
elem.removeAttributeNode(att);
--i;
}
}
}
}
} else {
if ( attributes!=null ) {
for ( int i=0; inormalizeNode:{comments}");
}
if ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0) {
Node prevSibling = node.getPreviousSibling();
Node parent = node.getParentNode();
// remove the comment node
parent.removeChild(node);
if (prevSibling != null && prevSibling.getNodeType() == Node.TEXT_NODE) {
Node nextSibling = prevSibling.getNextSibling();
if (nextSibling != null && nextSibling.getNodeType() == Node.TEXT_NODE) {
((TextImpl)nextSibling).insertData(0, prevSibling.getNodeValue());
parent.removeChild(prevSibling);
return nextSibling;
}
}
}//if comment node need not be removed
else {
if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){
String commentdata = ((Comment)node).getData();
// check comments for invalid xml chracter as per the version
// of the document
isCommentWF(fErrorHandler, fError, fLocator, commentdata, fDocument.isXML11Version());
}
if (fValidationHandler != null) {
// Don't bother filling an XMLString with the text of the comment.
// We only send the comment event to the validator handler so that
// when the schema-type is DTD an error will be reported for a
// comment appearing in EMPTY content.
fValidationHandler.comment(EMPTY_STRING, null);
}
}//end-else if comment node is not to be removed.
break;
}
case Node.ENTITY_REFERENCE_NODE: {
if (DEBUG_ND) {
System.out.println("==>normalizeNode:{entityRef} "+node.getNodeName());
}
if ((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0) {
Node prevSibling = node.getPreviousSibling();
Node parent = node.getParentNode();
((EntityReferenceImpl)node).setReadOnly(false, true);
expandEntityRef (parent, node);
parent.removeChild(node);
Node next = (prevSibling != null)?prevSibling.getNextSibling():parent.getFirstChild();
// The list of children #text -> &ent;
// and entity has a first child as a text
// we should not advance
if (prevSibling != null && next != null && prevSibling.getNodeType() == Node.TEXT_NODE &&
next.getNodeType() == Node.TEXT_NODE) {
return prevSibling; // Don't advance
}
return next;
} else {
if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) &&
fDocument.isXMLVersionChanged()){
CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version());
}
// REVISIT: traverse entity reference and send appropriate calls to the validator
// (no normalization should be performed for the children).
}
break;
}
case Node.CDATA_SECTION_NODE: {
if (DEBUG_ND) {
System.out.println("==>normalizeNode:{cdata}");
}
if ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) {
// convert CDATA to TEXT nodes
Node prevSibling = node.getPreviousSibling();
if (prevSibling != null && prevSibling.getNodeType() == Node.TEXT_NODE){
((Text)prevSibling).appendData(node.getNodeValue());
node.getParentNode().removeChild(node);
return prevSibling; //don't advance
}
else {
Text text = fDocument.createTextNode(node.getNodeValue());
Node parent = node.getParentNode();
node = parent.replaceChild(text, node);
return text; //don't advance
}
}
// send characters call for CDATA
if (fValidationHandler != null) {
// set error node in the dom error wrapper
// so if error occurs we can report an error node
fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
fCurrentNode = node;
fValidationHandler.startCDATA(null);
fValidationHandler.characterData(node.getNodeValue(), null);
fValidationHandler.endCDATA(null);
}
String value = node.getNodeValue();
if ((fConfiguration.features & DOMConfigurationImpl.SPLITCDATA) != 0) {
int index;
Node parent = node.getParentNode();
if (fDocument.errorChecking) {
isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version());
}
while ( (index=value.indexOf("]]>")) >= 0 ) {
node.setNodeValue(value.substring(0, index+2));
value = value.substring(index +2);
Node firstSplitNode = node;
Node newChild = fDocument.createCDATASection(value);
parent.insertBefore(newChild, node.getNextSibling());
node = newChild;
// issue warning
fLocator.fRelatedNode = firstSplitNode;
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"cdata-sections-splitted",
null);
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_WARNING,
"cdata-sections-splitted");
}
}
else if (fDocument.errorChecking) {
// check well-formedness
isCDataWF(fErrorHandler, fError, fLocator, value, fDocument.isXML11Version());
}
break;
}
case Node.TEXT_NODE: {
if (DEBUG_ND) {
System.out.println("==>normalizeNode(text):{"+node.getNodeValue()+"}");
}
// If node is a text node, we need to check for one of two
// conditions:
// 1) There is an adjacent text node
// 2) There is no adjacent text node, but node is
// an empty text node.
Node next = node.getNextSibling();
// If an adjacent text node, merge it with this node
if ( next!=null && next.getNodeType() == Node.TEXT_NODE ) {
((Text)node).appendData(next.getNodeValue());
node.getParentNode().removeChild( next );
// We don't need to check well-formness here since we are not yet
// done with this node.
return node; // Don't advance;
} else if (node.getNodeValue().length()==0) {
// If kid is empty, remove it
node.getParentNode().removeChild( node );
} else {
// validator.characters() call and well-formness
// Don't send characters or check well-formness in the following cases:
// 1. entities is false, next child is entity reference: expand tree first
// 2. comments is false, and next child is comment
// 3. cdata is false, and next child is cdata
short nextType = (next != null)?next.getNodeType():-1;
if (nextType == -1 || !(((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0 &&
nextType == Node.ENTITY_NODE) ||
((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0 &&
nextType == Node.COMMENT_NODE) ||
((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) &&
nextType == Node.CDATA_SECTION_NODE)) {
if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) ){
isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version());
}
if (fValidationHandler != null) {
fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
fCurrentNode = node;
fValidationHandler.characterData(node.getNodeValue(), null);
if (!fNamespaceValidation) {
if (fAllWhitespace) {
fAllWhitespace = false;
((TextImpl)node).setIgnorableWhitespace(true);
}
else {
((TextImpl)node).setIgnorableWhitespace(false);
}
}
if (DEBUG_ND) {
System.out.println("=====>characterData(),"+nextType);
}
}
}
else {
if (DEBUG_ND) {
System.out.println("=====>don't send characters(),"+nextType);
}
}
}
break;
}
case Node.PROCESSING_INSTRUCTION_NODE: {
//do the well-formed valid PI target name , data check when application has set the value of well-formed feature to true
if (fDocument.errorChecking && (fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0 ) {
ProcessingInstruction pinode = (ProcessingInstruction)node ;
String target = pinode.getTarget();
//1.check PI target name
if(fDocument.isXML11Version()){
wellformed = XML11Char.isXML11ValidName(target);
}
else{
wellformed = XMLChar.isValidName(target);
}
if (!wellformed) {
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"wf-invalid-character-in-node-name",
new Object[]{"Element", node.getNodeName()});
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
"wf-invalid-character-in-node-name");
}
//2. check PI data
//processing isntruction data may have certain characters
//which may not be valid XML character
isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), fDocument.isXML11Version());
}
if (fValidationHandler != null) {
// Don't bother filling an XMLString with the data section of the
// processing instruction. We only send the processing instruction
// event to the validator handler so that when the schema-type is
// DTD an error will be reported for a processing instruction
// appearing in EMPTY content.
fValidationHandler.processingInstruction(((ProcessingInstruction) node).getTarget(), EMPTY_STRING, null);
}
}//end case Node.PROCESSING_INSTRUCTION_NODE
}//end of switch
return null;
}//normalizeNode
private void processDTD(String xmlVersion, String schemaLocation) {
String rootName = null;
String publicId = null;
String systemId = schemaLocation;
String baseSystemId = fDocument.getDocumentURI();
String internalSubset = null;
DocumentType docType = fDocument.getDoctype();
if (docType != null) {
rootName = docType.getName();
publicId = docType.getPublicId();
if (systemId == null || systemId.length() == 0) {
systemId = docType.getSystemId();
}
internalSubset = docType.getInternalSubset();
}
// If the DOM doesn't have a DocumentType node we may still
// be able to fetch a DTD if the application provided a URI
else {
Element elem = fDocument.getDocumentElement();
if (elem == null) return;
rootName = elem.getNodeName();
if (systemId == null || systemId.length() == 0) return;
}
XMLDTDLoader loader = null;
try {
fValidationHandler.doctypeDecl(rootName, publicId, systemId, null);
loader = CoreDOMImplementationImpl.singleton.getDTDLoader(xmlVersion);
loader.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true);
loader.setEntityResolver(fConfiguration.getEntityResolver());
loader.setErrorHandler(fConfiguration.getErrorHandler());
loader.loadGrammarWithContext((XMLDTDValidator) fValidationHandler, rootName,
publicId, systemId, baseSystemId, internalSubset);
}
// REVISIT: Should probably report this exception to the error handler.
catch (IOException e) {
}
finally {
if (loader != null) {
CoreDOMImplementationImpl.singleton.releaseDTDLoader(xmlVersion, loader);
}
}
} // processDTD(String, String)
protected final void expandEntityRef (Node parent, Node reference){
Node kid, next;
for (kid = reference.getFirstChild(); kid != null; kid = next) {
next = kid.getNextSibling();
parent.insertBefore(kid, reference);
}
}
// fix namespaces
// normalize attribute values
// remove default attributes
// check attribute names if the version of the document changed.
protected final void namespaceFixUp (ElementImpl element, AttributeMap attributes){
if (DEBUG) {
System.out.println("[ns-fixup] element:" +element.getNodeName()+
" uri: "+element.getNamespaceURI());
}
// ------------------------------------
// pick up local namespace declarations
//
//
//
//
// ------------------------------------
String value, uri, prefix;
if (attributes != null) {
// Record all valid local declarations
for (int k = 0; k < attributes.getLength(); ++k) {
Attr attr = (Attr)attributes.getItem(k);
uri = attr.getNamespaceURI();
if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
// namespace attribute
value = attr.getNodeValue();
if (value == null) {
value=XMLSymbols.EMPTY_STRING;
}
// Check for invalid namespace declaration:
if (fDocument.errorChecking && value.equals(NamespaceContext.XMLNS_URI)) {
//A null value for locale is passed to formatMessage,
//which means that the default locale will be used
fLocator.fRelatedNode = attr;
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,"CantBindXMLNS",null );
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, "CantBindXMLNS");
} else {
// XML 1.0 Attribute value normalization
// value = normalizeAttributeValue(value, attr);
prefix = attr.getPrefix();
prefix = (prefix == null ||
prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
String localpart = fSymbolTable.addSymbol( attr.getLocalName());
if (prefix == XMLSymbols.PREFIX_XMLNS) { //xmlns:prefix
value = fSymbolTable.addSymbol(value);
if (value.length() != 0) {
fNamespaceContext.declarePrefix(localpart, value);
} else {
// REVISIT: issue error on invalid declarations
// xmlns:foo = ""
}
//removeDefault (attr, attributes);
continue;
} else { // (localpart == fXmlnsSymbol && prefix == fEmptySymbol) -- xmlns
// empty prefix is always bound ("" or some string)
value = fSymbolTable.addSymbol(value);
fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value.length() != 0 ? value : null);
//removeDefault (attr, attributes);
continue;
}
} // end-else: valid declaration
} // end-if: namespace attribute
}
}
// ---------------------------------------------------------
// Fix up namespaces for element: per DOM L3
// Need to consider the following cases:
//
// case 1:
// We create another element body bound to the "http://xsl" namespace
// as well as namespace attribute rebounding xsl to another namespace.
//
// Need to make sure that the new namespace decl value is changed to
// "http://xsl"
//
// ---------------------------------------------------------
// check if prefix/namespace is correct for current element
// ---------------------------------------------------------
uri = element.getNamespaceURI();
prefix = element.getPrefix();
if (uri != null) { // Element has a namespace
uri = fSymbolTable.addSymbol(uri);
prefix = (prefix == null ||
prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
if (fNamespaceContext.getURI(prefix) == uri) {
// The xmlns:prefix=namespace or xmlns="default" was declared at parent.
// The binder always stores mapping of empty prefix to "".
} else {
// the prefix is either undeclared
// or
// conflict: the prefix is bound to another URI
addNamespaceDecl(prefix, uri, element);
fLocalNSBinder.declarePrefix(prefix, uri);
fNamespaceContext.declarePrefix(prefix, uri);
}
} else { // Element has no namespace
if (element.getLocalName() == null) {
// Error: DOM Level 1 node!
if (fNamespaceValidation) {
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName",
new Object[]{element.getNodeName()});
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR,
"NullLocalElementName");
} else {
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName",
new Object[]{element.getNodeName()});
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
"NullLocalElementName");
}
} else { // uri=null and no colon (DOM L2 node)
uri = fNamespaceContext.getURI(XMLSymbols.EMPTY_STRING);
if (uri !=null && uri.length() > 0) {
// undeclare default namespace declaration (before that element
// bound to non-zero length uir), but adding xmlns="" decl
addNamespaceDecl (XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING, element);
fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, null);
fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
}
}
}
// -----------------------------------------
// Fix up namespaces for attributes: per DOM L3
// check if prefix/namespace is correct the attributes
// -----------------------------------------
if (attributes != null) {
// clone content of the attributes
attributes.cloneMap(fAttributeList);
for (int i = 0; i < fAttributeList.size(); i++) {
Attr attr = (Attr) fAttributeList.get(i);
fLocator.fRelatedNode = attr;
if (DEBUG) {
System.out.println("==>[ns-fixup] process attribute: "+attr.getNodeName());
}
// normalize attribute value
attr.normalize();
value = attr.getValue();
uri = attr.getNamespaceURI();
// make sure that value is never null.
if (value == null) {
value = XMLSymbols.EMPTY_STRING;
}
//---------------------------------------
// check if value of the attribute is namespace well-formed
//---------------------------------------
if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
isAttrValueWF(fErrorHandler, fError, fLocator, attributes, attr, value, fDocument.isXML11Version());
if (fDocument.isXMLVersionChanged()) {
boolean wellformed;
if (fNamespaceValidation){
wellformed = CoreDocumentImpl.isValidQName(attr.getPrefix(), attr.getLocalName(), fDocument.isXML11Version());
}
else {
wellformed = CoreDocumentImpl.isXMLName(attr.getNodeName(), fDocument.isXML11Version());
}
if (!wellformed) {
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"wf-invalid-character-in-node-name",
new Object[]{"Attr", attr.getNodeName()});
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
"wf-invalid-character-in-node-name");
}
}
}
if (uri != null) { // attribute has namespace !=null
prefix = attr.getPrefix();
prefix = (prefix == null ||
prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix);
/*String localpart =*/ fSymbolTable.addSymbol( attr.getLocalName());
// ---------------------------------------
// skip namespace declarations
// ---------------------------------------
// REVISIT: can we assume that "uri" is from some symbol
// table, and compare by reference? -SG
if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) {
continue;
}
// ---------------------------------------
// remove default attributes
// ---------------------------------------
/*
if (removeDefault(attr, attributes)) {
continue;
}
*/
// XML 1.0 Attribute value normalization
//value = normalizeAttributeValue(value, attr);
// reset id-attributes
((AttrImpl)attr).setIdAttribute(false);
uri = fSymbolTable.addSymbol(uri);
// find if for this prefix a URI was already declared
String declaredURI = fNamespaceContext.getURI(prefix);
if (prefix == XMLSymbols.EMPTY_STRING || declaredURI != uri) {
// attribute has no prefix (default namespace decl does not apply to attributes)
// OR
// attribute prefix is not declared
// OR
// conflict: attribute has a prefix that conficlicts with a binding
// already active in scope
// Find if any prefix for attributes namespace URI is available
// in the scope
String declaredPrefix = fNamespaceContext.getPrefix(uri);
if (declaredPrefix !=null && declaredPrefix !=XMLSymbols.EMPTY_STRING) {
// use the prefix that was found (declared previously for this URI
prefix = declaredPrefix;
} else {
if (prefix != XMLSymbols.EMPTY_STRING && fLocalNSBinder.getURI(prefix) == null) {
// the current prefix is not null and it has no in scope declaration
// use this prefix
} else {
// find a prefix following the pattern "NS" +index (starting at 1)
// make sure this prefix is not declared in the current scope.
int counter = 1;
prefix = fSymbolTable.addSymbol(PREFIX +counter++);
while (fLocalNSBinder.getURI(prefix)!=null) {
prefix = fSymbolTable.addSymbol(PREFIX +counter++);
}
}
// add declaration for the new prefix
addNamespaceDecl(prefix, uri, element);
value = fSymbolTable.addSymbol(value);
fLocalNSBinder.declarePrefix(prefix, value);
fNamespaceContext.declarePrefix(prefix, uri);
}
// change prefix for this attribute
attr.setPrefix(prefix);
}
} else { // attribute uri == null
// XML 1.0 Attribute value normalization
//value = normalizeAttributeValue(value, attr);
// reset id-attributes
((AttrImpl)attr).setIdAttribute(false);
if (attr.getLocalName() == null) {
// It is an error if document has DOM L1 nodes.
if (fNamespaceValidation) {
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"NullLocalAttrName", new Object[]{attr.getNodeName()});
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR,
"NullLocalAttrName");
} else {
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN,
"NullLocalAttrName", new Object[]{attr.getNodeName()});
reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR,
"NullLocalAttrName");
}
} else {
// uri=null and no colon
// no fix up is needed: default namespace decl does not
// ---------------------------------------
// remove default attributes
// ---------------------------------------
// removeDefault(attr, attributes);
}
}
}
} // end loop for attributes
}
/**
* Adds a namespace attribute or replaces the value of existing namespace
* attribute with the given prefix and value for URI.
* In case prefix is empty will add/update default namespace declaration.
*
* @param prefix
* @param uri
* @exception IOException
*/
protected final void addNamespaceDecl(String prefix, String uri, ElementImpl element){
if (DEBUG) {
System.out.println("[ns-fixup] addNamespaceDecl ["+prefix+"]");
}
if (prefix == XMLSymbols.EMPTY_STRING) {
if (DEBUG) {
System.out.println("=>add xmlns=\""+uri+"\" declaration");
}
element.setAttributeNS(NamespaceContext.XMLNS_URI, XMLSymbols.PREFIX_XMLNS, uri);
} else {
if (DEBUG) {
System.out.println("=>add xmlns:"+prefix+"=\""+uri+"\" declaration");
}
element.setAttributeNS(NamespaceContext.XMLNS_URI, "xmlns:"+prefix, uri);
}
}
//
// Methods for well-formness checking
//
/**
* Check if CDATA section is well-formed
* @param datavalue
* @param isXML11Version = true if XML 1.1
*/
public static final void isCDataWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator,
String datavalue, boolean isXML11Version)
{
if (datavalue == null || (datavalue.length() == 0) ) {
return;
}
char [] dataarray = datavalue.toCharArray();
int datalength = dataarray.length;
// version of the document is XML 1.1
if (isXML11Version) {
// we need to check all chracters as per production rules of XML11
int i = 0;
while(i < datalength){
char c = dataarray[i++];
if ( XML11Char.isXML11Invalid(c) ) {
// check if this is a supplemental character
if (XMLChar.isHighSurrogate(c) && i < datalength) {
char c2 = dataarray[i++];
if (XMLChar.isLowSurrogate(c2) &&
XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
continue;
}
}
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.XML_DOMAIN,
"InvalidCharInCDSect",
new Object[] { Integer.toString(c, 16)});
reportDOMError(
errorHandler,
error,
locator,
msg,
DOMError.SEVERITY_ERROR,
"wf-invalid-character");
}
else if (c == ']') {
int count = i;
if (count < datalength && dataarray[count] == ']') {
while (++count < datalength && dataarray[count] == ']') {
// do nothing
}
if (count < datalength && dataarray[count] == '>') {
// CDEndInContent
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, "CDEndInContent", null);
reportDOMError(errorHandler, error, locator,msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
}
}
}
}
} // version of the document is XML 1.0
else {
// we need to check all chracters as per production rules of XML 1.0
int i = 0;
while (i < datalength) {
char c = dataarray[i++];
if( XMLChar.isInvalid(c) ) {
// check if this is a supplemental character
if (XMLChar.isHighSurrogate(c) && i < datalength) {
char c2 = dataarray[i++];
if (XMLChar.isLowSurrogate(c2) &&
XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
continue;
}
}
// Note: The key InvalidCharInCDSect from XMLMessages.properties
// is being used to obtain the message and DOM error type
// "wf-invalid-character" is used. Also per DOM it is error but
// as per XML spec. it is fatal error
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.XML_DOMAIN,
"InvalidCharInCDSect",
new Object[]{Integer.toString(c, 16)});
reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
}
else if (c==']') {
int count = i;
if ( count< datalength && dataarray[count]==']' ) {
while (++count < datalength && dataarray[count]==']' ) {
// do nothing
}
if ( count < datalength && dataarray[count]=='>' ) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, "CDEndInContent", null);
reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
}
}
}
}
} // end-else fDocument.isXMLVersion()
} // isCDataWF
/**
* NON-DOM: check for valid XML characters as per the XML version
* @param datavalue
* @param isXML11Version = true if XML 1.1
*/
public static final void isXMLCharWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator,
String datavalue, boolean isXML11Version)
{
if ( datavalue == null || (datavalue.length() == 0) ) {
return;
}
char [] dataarray = datavalue.toCharArray();
int datalength = dataarray.length;
// version of the document is XML 1.1
if(isXML11Version){
//we need to check all characters as per production rules of XML11
int i = 0 ;
while (i < datalength) {
if(XML11Char.isXML11Invalid(dataarray[i++])){
// check if this is a supplemental character
char ch = dataarray[i-1];
if (XMLChar.isHighSurrogate(ch) && i < datalength) {
char ch2 = dataarray[i++];
if (XMLChar.isLowSurrogate(ch2) &&
XMLChar.isSupplemental(XMLChar.supplemental(ch, ch2))) {
continue;
}
}
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, "InvalidXMLCharInDOM",
new Object[]{Integer.toString(dataarray[i-1], 16)});
reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR,
"wf-invalid-character");
}
}
} // version of the document is XML 1.0
else{
// we need to check all characters as per production rules of XML 1.0
int i = 0 ;
while (i < datalength) {
if( XMLChar.isInvalid(dataarray[i++]) ) {
// check if this is a supplemental character
char ch = dataarray[i-1];
if (XMLChar.isHighSurrogate(ch) && i < datalength) {
char ch2 = dataarray[i++];
if (XMLChar.isLowSurrogate(ch2) &&
XMLChar.isSupplemental(XMLChar.supplemental(ch, ch2))) {
continue;
}
}
String msg = DOMMessageFormatter.formatMessage(
DOMMessageFormatter.DOM_DOMAIN, "InvalidXMLCharInDOM",
new Object[]{Integer.toString(dataarray[i-1], 16)});
reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR,
"wf-invalid-character");
}
}
} // end-else fDocument.isXMLVersion()
} // isXMLCharWF
/**
* NON-DOM: check if value of the comment is well-formed
* @param datavalue
* @param isXML11Version = true if XML 1.1
*/
public static final void isCommentWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator,
String datavalue, boolean isXML11Version)
{
if ( datavalue == null || (datavalue.length() == 0) ) {
return;
}
char [] dataarray = datavalue.toCharArray();
int datalength = dataarray.length ;
// version of the document is XML 1.1
if (isXML11Version) {
// we need to check all chracters as per production rules of XML11
int i = 0 ;
while (i < datalength){
char c = dataarray[i++];
if ( XML11Char.isXML11Invalid(c) ) {
// check if this is a supplemental character
if (XMLChar.isHighSurrogate(c) && i < datalength) {
char c2 = dataarray[i++];
if (XMLChar.isLowSurrogate(c2) &&
XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
continue;
}
}
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,
"InvalidCharInComment",
new Object [] {Integer.toString(dataarray[i-1], 16)});
reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
}
else if (c == '-' && i < datalength && dataarray[i] == '-') {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,
"DashDashInComment", null);
// invalid: '--' in comment
reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
}
}
} // version of the document is XML 1.0
else {
// we need to check all chracters as per production rules of XML 1.0
int i = 0;
while (i < datalength){
char c = dataarray[i++];
if( XMLChar.isInvalid(c) ){
// check if this is a supplemental character
if (XMLChar.isHighSurrogate(c) && i < datalength) {
char c2 = dataarray[i++];
if (XMLChar.isLowSurrogate(c2) &&
XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) {
continue;
}
}
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,
"InvalidCharInComment", new Object [] {Integer.toString(dataarray[i-1], 16)});
reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character");
}
else if (c == '-' && istrongly
* recommended that a locator be supplied that can
* at least report the system identifier of the
* document.
* @param encoding The auto-detected IANA encoding name of the entity
* stream. This value will be null in those situations
* where the entity encoding is not auto-detected (e.g.
* internal entities or a document entity that is
* parsed from a java.io.Reader).
* @param namespaceContext
* The namespace context in effect at the
* start of this document.
* This object represents the current context.
* Implementors of this class are responsible
* for copying the namespace bindings from the
* the current context (and its parent contexts)
* if that information is important.
*
* @param augs Additional information that may include infoset augmentations
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void startDocument(XMLLocator locator, String encoding,
NamespaceContext namespaceContext,
Augmentations augs)
throws XNIException{
}
/**
* Notifies of the presence of an XMLDecl line in the document. If
* present, this method will be called immediately following the
* startDocument call.
*
* @param version The XML version.
* @param encoding The IANA encoding name of the document, or null if
* not specified.
* @param standalone The standalone value, or null if not specified.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
throws XNIException{
}
/**
* Notifies of the presence of the DOCTYPE line in the document.
*
* @param rootElement
* The name of the root element.
* @param publicId The public identifier if an external DTD or null
* if the external DTD is specified using SYSTEM.
* @param systemId The system identifier if an external DTD, null
* otherwise.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs)
throws XNIException{
}
/**
* A comment.
*
* @param text The text in the comment.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by application to signal an error.
*/
public void comment(XMLString text, Augmentations augs) throws XNIException{
}
/**
* A processing instruction. Processing instructions consist of a
* target name and, optionally, text data. The data is only meaningful
* to the application.
*
* Typically, a processing instruction's data will contain a series
* of pseudo-attributes. These pseudo-attributes follow the form of
* element attributes but are not parsed or presented
* to the application as anything other than text. The application is
* responsible for parsing the data.
*
* @param target The target.
* @param data The data or null if none specified.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void processingInstruction(String target, XMLString data, Augmentations augs)
throws XNIException{
}
/**
* The start of an element.
*
* @param element The name of the element.
* @param attributes The element attributes.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
throws XNIException {
Element currentElement = (Element) fCurrentNode;
int attrCount = attributes.getLength();
if (DEBUG_EVENTS) {
System.out.println("==>startElement: " +element+
" attrs.length="+attrCount);
}
for (int i = 0; i < attrCount; i++) {
attributes.getName(i, fAttrQName);
Attr attr = null;
attr = currentElement.getAttributeNodeNS(fAttrQName.uri, fAttrQName.localpart);
if (attr == null) {
// Must be a non-namespace aware DOM Level 1 node.
attr = currentElement.getAttributeNode(fAttrQName.rawname);
}
AttributePSVI attrPSVI =
(AttributePSVI) attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI);
if (attrPSVI != null) {
//REVISIT: instead we should be using augmentations:
// to set/retrieve Id attributes
XSTypeDefinition decl = attrPSVI.getMemberTypeDefinition();
boolean id = false;
if (decl != null) {
id = ((XSSimpleType)decl).isIDType();
}
else {
decl = attrPSVI.getTypeDefinition();
if (decl != null) {
id = ((XSSimpleType)decl).isIDType();
}
}
if (id) {
((ElementImpl)currentElement).setIdAttributeNode(attr, true);
}
if (fPSVI) {
((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
}
// Updating the TypeInfo for this attribute.
((AttrImpl) attr).setType(decl);
if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
// datatype-normalization
// NOTE: The specified value MUST be set after we set
// the node value because that turns the "specified"
// flag to "true" which may overwrite a "false"
// value from the attribute list.
final String normalizedValue = attrPSVI.getSchemaNormalizedValue();
if (normalizedValue != null) {
boolean specified = attr.getSpecified();
attr.setValue(normalizedValue);
if (!specified) {
((AttrImpl) attr).setSpecified(specified);
}
}
}
}
else { // DTD
String type = null;
boolean isDeclared = Boolean.TRUE.equals(attributes.getAugmentations(i).getItem (Constants.ATTRIBUTE_DECLARED));
// For DOM Level 3 TypeInfo, the type name must
// be null if this attribute has not been declared
// in the DTD.
if (isDeclared) {
type = attributes.getType(i);
if ("ID".equals (type)) {
((ElementImpl) currentElement).setIdAttributeNode(attr, true);
}
}
// Updating the TypeInfo for this attribute.
((AttrImpl) attr).setType(type);
}
}
}
/**
* An empty element.
*
* @param element The name of the element.
* @param attributes The element attributes.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>emptyElement: " +element);
}
startElement(element, attributes, augs);
endElement(element, augs);
}
/**
* This method notifies the start of a general entity.
*
* Note: This method is not called for entity references
* appearing as part of attribute values.
*
* @param name The name of the general entity.
* @param identifier The resource identifier.
* @param encoding The auto-detected IANA encoding name of the entity
* stream. This value will be null in those situations
* where the entity encoding is not auto-detected (e.g.
* internal entities or a document entity that is
* parsed from a java.io.Reader).
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException Thrown by handler to signal an error.
*/
public void startGeneralEntity(String name,
XMLResourceIdentifier identifier,
String encoding,
Augmentations augs) throws XNIException{
}
/**
* Notifies of the presence of a TextDecl line in an entity. If present,
* this method will be called immediately following the startEntity call.
*
* Note: This method will never be called for the
* document entity; it is only called for external general entities
* referenced in document content.
*
* Note: This method is not called for entity references
* appearing as part of attribute values.
*
* @param version The XML version, or null if not specified.
* @param encoding The IANA encoding name of the entity.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void textDecl(String version, String encoding, Augmentations augs) throws XNIException{
}
/**
* This method notifies the end of a general entity.
*
* Note: This method is not called for entity references
* appearing as part of attribute values.
*
* @param name The name of the entity.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void endGeneralEntity(String name, Augmentations augs) throws XNIException{
}
/**
* Character content.
*
* @param text The content.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void characters(XMLString text, Augmentations augs) throws XNIException{
}
/**
* Ignorable whitespace. For this method to be called, the document
* source must have some way of determining that the text containing
* only whitespace characters should be considered ignorable. For
* example, the validator can determine if a length of whitespace
* characters in the document are ignorable based on the element
* content model.
*
* @param text The ignorable whitespace.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException{
fAllWhitespace = true;
}
/**
* The end of an element.
*
* @param element The name of the element.
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void endElement(QName element, Augmentations augs) throws XNIException {
if (DEBUG_EVENTS) {
System.out.println("==>endElement: " + element);
}
if (augs != null) {
ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI);
if (elementPSVI != null) {
ElementImpl elementNode = (ElementImpl) fCurrentNode;
if (fPSVI) {
((PSVIElementNSImpl) fCurrentNode).setPSVI(elementPSVI);
}
// Updating the TypeInfo for this element.
if (elementNode instanceof ElementNSImpl) {
XSTypeDefinition type = elementPSVI.getMemberTypeDefinition();
if (type == null) {
type = elementPSVI.getTypeDefinition();
}
((ElementNSImpl) elementNode).setType(type);
}
// include element default content (if one is available)
String normalizedValue = elementPSVI.getSchemaNormalizedValue();
if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
if (normalizedValue !=null)
elementNode.setTextContent(normalizedValue);
}
else {
// NOTE: this is a hack: it is possible that DOM had an empty element
// and validator sent default value using characters(), which we don't
// implement. Thus, here we attempt to add the default value.
String text = elementNode.getTextContent();
if (text.length() == 0) {
// default content could be provided
if (normalizedValue !=null)
elementNode.setTextContent(normalizedValue);
}
}
return;
}
}
// DTD; elements have no type.
if (fCurrentNode instanceof ElementNSImpl) {
((ElementNSImpl) fCurrentNode).setType(null);
}
}
/**
* The start of a CDATA section.
*
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void startCDATA(Augmentations augs) throws XNIException{
}
/**
* The end of a CDATA section.
*
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void endCDATA(Augmentations augs) throws XNIException{
}
/**
* The end of the document.
*
* @param augs Additional information that may include infoset augmentations
*
* @exception XNIException
* Thrown by handler to signal an error.
*/
public void endDocument(Augmentations augs) throws XNIException{
}
/** Sets the document source. */
public void setDocumentSource(XMLDocumentSource source){
}
/** Returns the document source. */
public XMLDocumentSource getDocumentSource(){
return null;
}
} // DOMNormalizer class