0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.xerces.dom;
0019:
0020: import java.io.IOException;
0021: import java.util.Vector;
0022:
0023: import org.apache.xerces.impl.Constants;
0024: import org.apache.xerces.impl.RevalidationHandler;
0025: import org.apache.xerces.impl.dtd.XMLDTDLoader;
0026: import org.apache.xerces.impl.dtd.XMLDTDValidator;
0027: import org.apache.xerces.impl.dv.XSSimpleType;
0028: import org.apache.xerces.impl.xs.util.SimpleLocator;
0029: import org.apache.xerces.util.AugmentationsImpl;
0030: import org.apache.xerces.util.NamespaceSupport;
0031: import org.apache.xerces.util.SymbolTable;
0032: import org.apache.xerces.util.XML11Char;
0033: import org.apache.xerces.util.XMLChar;
0034: import org.apache.xerces.util.XMLSymbols;
0035: import org.apache.xerces.xni.Augmentations;
0036: import org.apache.xerces.xni.NamespaceContext;
0037: import org.apache.xerces.xni.QName;
0038: import org.apache.xerces.xni.XMLAttributes;
0039: import org.apache.xerces.xni.XMLDocumentHandler;
0040: import org.apache.xerces.xni.XMLLocator;
0041: import org.apache.xerces.xni.XMLResourceIdentifier;
0042: import org.apache.xerces.xni.XMLString;
0043: import org.apache.xerces.xni.XNIException;
0044: import org.apache.xerces.xni.grammars.XMLGrammarDescription;
0045: import org.apache.xerces.xni.parser.XMLComponent;
0046: import org.apache.xerces.xni.parser.XMLDocumentSource;
0047: import org.apache.xerces.xs.AttributePSVI;
0048: import org.apache.xerces.xs.ElementPSVI;
0049: import org.apache.xerces.xs.XSTypeDefinition;
0050: import org.w3c.dom.Attr;
0051: import org.w3c.dom.Comment;
0052: import org.w3c.dom.DOMError;
0053: import org.w3c.dom.DOMErrorHandler;
0054: import org.w3c.dom.Document;
0055: import org.w3c.dom.DocumentType;
0056: import org.w3c.dom.Element;
0057: import org.w3c.dom.Entity;
0058: import org.w3c.dom.NamedNodeMap;
0059: import org.w3c.dom.Node;
0060: import org.w3c.dom.NodeList;
0061: import org.w3c.dom.ProcessingInstruction;
0062: import org.w3c.dom.Text;
0063:
0064: /**
0065: * This class adds implementation for normalizeDocument method.
0066: * It acts as if the document was going through a save and load cycle, putting
0067: * the document in a "normal" form. The actual result depends on the features being set
0068: * and governing what operations actually take place. See setNormalizationFeature for details.
0069: * Noticeably this method normalizes Text nodes, makes the document "namespace wellformed",
0070: * according to the algorithm described below in pseudo code, by adding missing namespace
0071: * declaration attributes and adding or changing namespace prefixes, updates the replacement
0072: * tree of EntityReference nodes, normalizes attribute values, etc.
0073: * Mutation events, when supported, are generated to reflect the changes occuring on the
0074: * document.
0075: * See Namespace normalization for details on how namespace declaration attributes and prefixes
0076: * are normalized.
0077: *
0078: * NOTE: There is an initial support for DOM revalidation with XML Schema as a grammar.
0079: * The tree might not be validated correctly if entityReferences, CDATA sections are
0080: * present in the tree. The PSVI information is not exposed, normalized data (including element
0081: * default content is not available).
0082: *
0083: * @xerces.experimental
0084: *
0085: * @author Elena Litani, IBM
0086: * @author Neeraj Bajaj, Sun Microsystems, inc.
0087: * @version $Id: DOMNormalizer.java 541770 2007-05-25 20:17:48Z mrglavas $
0088: */
0089: public class DOMNormalizer implements XMLDocumentHandler {
0090:
0091: //
0092: // constants
0093: //
0094: /** Debug normalize document*/
0095: protected final static boolean DEBUG_ND = false;
0096: /** Debug namespace fix up algorithm*/
0097: protected final static boolean DEBUG = false;
0098: /** Debug document handler events */
0099: protected final static boolean DEBUG_EVENTS = false;
0100:
0101: /** prefix added by namespace fixup algorithm should follow a pattern "NS" + index*/
0102: protected final static String PREFIX = "NS";
0103:
0104: //
0105: // Data
0106: //
0107: protected DOMConfigurationImpl fConfiguration = null;
0108: protected CoreDocumentImpl fDocument = null;
0109: protected final XMLAttributesProxy fAttrProxy = new XMLAttributesProxy();
0110: protected final QName fQName = new QName();
0111:
0112: /** Validation handler represents validator instance. */
0113: protected RevalidationHandler fValidationHandler;
0114:
0115: /** symbol table */
0116: protected SymbolTable fSymbolTable;
0117: /** error handler. may be null. */
0118: protected DOMErrorHandler fErrorHandler;
0119:
0120: /**
0121: * Cached {@link DOMError} impl.
0122: * The same object is re-used to report multiple errors.
0123: */
0124: private final DOMErrorImpl fError = new DOMErrorImpl();
0125:
0126: // Validation against namespace aware grammar
0127: protected boolean fNamespaceValidation = false;
0128:
0129: // Update PSVI information in the tree
0130: protected boolean fPSVI = false;
0131:
0132: /** The namespace context of this document: stores namespaces in scope */
0133: protected final NamespaceContext fNamespaceContext = new NamespaceSupport();
0134:
0135: /** Stores all namespace bindings on the current element */
0136: protected final NamespaceContext fLocalNSBinder = new NamespaceSupport();
0137:
0138: /** list of attributes */
0139: protected final Vector fAttributeList = new Vector(5, 10);
0140:
0141: /** DOM Locator - for namespace fixup algorithm */
0142: protected final DOMLocatorImpl fLocator = new DOMLocatorImpl();
0143:
0144: /** for setting the PSVI */
0145: protected Node fCurrentNode = null;
0146: private QName fAttrQName = new QName();
0147:
0148: // attribute value normalization
0149: final XMLString fNormalizedValue = new XMLString(new char[16], 0, 0);
0150:
0151: /**
0152: * If the user stops the process, this exception will be thrown.
0153: */
0154: public static final RuntimeException abort = new RuntimeException();
0155:
0156: /** Empty string to pass to the validator. **/
0157: public static final XMLString EMPTY_STRING = new XMLString();
0158:
0159: // Check if element content is all "ignorable whitespace"
0160: private boolean fAllWhitespace = false;
0161:
0162: // Constructor
0163: //
0164:
0165: public DOMNormalizer() {
0166: }
0167:
0168: /**
0169: * Normalizes document.
0170: * Note: reset() must be called before this method.
0171: */
0172: protected void normalizeDocument(CoreDocumentImpl document,
0173: DOMConfigurationImpl config) {
0174:
0175: fDocument = document;
0176: fConfiguration = config;
0177: fAllWhitespace = false;
0178: fNamespaceValidation = false;
0179:
0180: String xmlVersion = fDocument.getXmlVersion();
0181: String schemaType = null;
0182: String[] schemaLocations = null;
0183:
0184: // intialize and reset DOMNormalizer component
0185: //
0186: fSymbolTable = (SymbolTable) fConfiguration
0187: .getProperty(DOMConfigurationImpl.SYMBOL_TABLE);
0188: // reset namespace context
0189: fNamespaceContext.reset();
0190: fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, null);
0191:
0192: if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) {
0193: String schemaLang = (String) fConfiguration
0194: .getProperty(DOMConfigurationImpl.JAXP_SCHEMA_LANGUAGE);
0195:
0196: if (schemaLang != null
0197: && schemaLang.equals(Constants.NS_XMLSCHEMA)) {
0198: schemaType = XMLGrammarDescription.XML_SCHEMA;
0199: fValidationHandler = CoreDOMImplementationImpl.singleton
0200: .getValidator(schemaType, xmlVersion);
0201: fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA,
0202: true);
0203: fConfiguration
0204: .setFeature(
0205: DOMConfigurationImpl.SCHEMA_FULL_CHECKING,
0206: true);
0207: // report fatal error on DOM Level 1 nodes
0208: fNamespaceValidation = true;
0209:
0210: // check if we need to fill in PSVI
0211: fPSVI = ((fConfiguration.features & DOMConfigurationImpl.PSVI) != 0) ? true
0212: : false;
0213: } else {
0214: schemaType = XMLGrammarDescription.XML_DTD;
0215: if (schemaLang != null) {
0216: schemaLocations = (String[]) fConfiguration
0217: .getProperty(DOMConfigurationImpl.JAXP_SCHEMA_SOURCE);
0218: }
0219: fConfiguration.setDTDValidatorFactory(xmlVersion);
0220: fValidationHandler = CoreDOMImplementationImpl.singleton
0221: .getValidator(schemaType, xmlVersion);
0222: fPSVI = false;
0223: }
0224:
0225: fConfiguration.setFeature(
0226: DOMConfigurationImpl.XERCES_VALIDATION, true);
0227:
0228: // reset ID table
0229: fDocument.clearIdentifiers();
0230:
0231: if (fValidationHandler != null) {
0232: // reset the validation handler
0233: ((XMLComponent) fValidationHandler)
0234: .reset(fConfiguration);
0235: }
0236: } else {
0237: fValidationHandler = null;
0238: }
0239:
0240: fErrorHandler = (DOMErrorHandler) fConfiguration
0241: .getParameter(Constants.DOM_ERROR_HANDLER);
0242: if (fValidationHandler != null) {
0243: fValidationHandler.setDocumentHandler(this );
0244: fValidationHandler.startDocument(new SimpleLocator(
0245: fDocument.fDocumentURI, fDocument.fDocumentURI, -1,
0246: -1), fDocument.encoding, fNamespaceContext, null);
0247: fValidationHandler.xmlDecl(fDocument.getXmlVersion(),
0248: fDocument.getXmlEncoding(), fDocument
0249: .getXmlStandalone() ? "yes" : "no", null);
0250: }
0251: try {
0252: if (schemaType == XMLGrammarDescription.XML_DTD) {
0253: processDTD(xmlVersion,
0254: schemaLocations != null ? schemaLocations[0]
0255: : null);
0256: }
0257:
0258: Node kid, next;
0259: for (kid = fDocument.getFirstChild(); kid != null; kid = next) {
0260: next = kid.getNextSibling();
0261: kid = normalizeNode(kid);
0262: if (kid != null) { // don't advance
0263: next = kid;
0264: }
0265: }
0266:
0267: // release resources
0268: if (fValidationHandler != null) {
0269: fValidationHandler.endDocument(null);
0270: fValidationHandler.setDocumentHandler(null);
0271: CoreDOMImplementationImpl.singleton.releaseValidator(
0272: schemaType, xmlVersion, fValidationHandler);
0273: fValidationHandler = null;
0274: }
0275: } catch (RuntimeException e) {
0276: // release resources
0277: if (fValidationHandler != null) {
0278: fValidationHandler.setDocumentHandler(null);
0279: CoreDOMImplementationImpl.singleton.releaseValidator(
0280: schemaType, xmlVersion, fValidationHandler);
0281: fValidationHandler = null;
0282: }
0283: if (e == abort) {
0284: return; // processing aborted by the user
0285: }
0286: throw e; // otherwise re-throw.
0287: }
0288: }
0289:
0290: /**
0291: *
0292: * This method acts as if the document was going through a save
0293: * and load cycle, putting the document in a "normal" form. The actual result
0294: * depends on the features being set and governing what operations actually
0295: * take place. See setNormalizationFeature for details. Noticeably this method
0296: * normalizes Text nodes, makes the document "namespace wellformed",
0297: * according to the algorithm described below in pseudo code, by adding missing
0298: * namespace declaration attributes and adding or changing namespace prefixes, updates
0299: * the replacement tree of EntityReference nodes,normalizes attribute values, etc.
0300: *
0301: * @param node Modified node or null. If node is returned, we need
0302: * to normalize again starting on the node returned.
0303: * @return the normalized Node
0304: */
0305: protected Node normalizeNode(Node node) {
0306:
0307: int type = node.getNodeType();
0308: boolean wellformed;
0309: fLocator.fRelatedNode = node;
0310:
0311: switch (type) {
0312: case Node.DOCUMENT_TYPE_NODE: {
0313: if (DEBUG_ND) {
0314: System.out.println("==>normalizeNode:{doctype}");
0315: }
0316: // REVISIT: well-formedness encoding info
0317: break;
0318: }
0319:
0320: case Node.ELEMENT_NODE: {
0321: if (DEBUG_ND) {
0322: System.out.println("==>normalizeNode:{element} "
0323: + node.getNodeName());
0324: }
0325:
0326: //do the name check only when version of the document was changed &
0327: //application has set the value of well-formed features to true
0328: if (fDocument.errorChecking) {
0329: if (((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)
0330: && fDocument.isXMLVersionChanged()) {
0331: if (fNamespaceValidation) {
0332: wellformed = CoreDocumentImpl.isValidQName(node
0333: .getPrefix(), node.getLocalName(),
0334: fDocument.isXML11Version());
0335: } else {
0336: wellformed = CoreDocumentImpl.isXMLName(node
0337: .getNodeName(), fDocument
0338: .isXML11Version());
0339: }
0340: if (!wellformed) {
0341: String msg = DOMMessageFormatter.formatMessage(
0342: DOMMessageFormatter.DOM_DOMAIN,
0343: "wf-invalid-character-in-node-name",
0344: new Object[] { "Element",
0345: node.getNodeName() });
0346: reportDOMError(fErrorHandler, fError, fLocator,
0347: msg, DOMError.SEVERITY_ERROR,
0348: "wf-invalid-character-in-node-name");
0349: }
0350: }
0351: }
0352: // push namespace context
0353: fNamespaceContext.pushContext();
0354: fLocalNSBinder.reset();
0355:
0356: ElementImpl elem = (ElementImpl) node;
0357: if (elem.needsSyncChildren()) {
0358: elem.synchronizeChildren();
0359: }
0360: AttributeMap attributes = (elem.hasAttributes()) ? (AttributeMap) elem
0361: .getAttributes()
0362: : null;
0363:
0364: // fix namespaces and remove default attributes
0365: if ((fConfiguration.features & DOMConfigurationImpl.NAMESPACES) != 0) {
0366: // fix namespaces
0367: // normalize attribute values
0368: // remove default attributes
0369: namespaceFixUp(elem, attributes);
0370:
0371: if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0
0372: && attributes != null) {
0373: for (int i = 0; i < attributes.getLength(); ++i) {
0374: Attr att = (Attr) attributes.getItem(i);
0375: if (XMLSymbols.PREFIX_XMLNS.equals(att
0376: .getPrefix())
0377: || XMLSymbols.PREFIX_XMLNS.equals(att
0378: .getName())) {
0379: elem.removeAttributeNode(att);
0380: --i;
0381: }
0382: }
0383: }
0384:
0385: } else {
0386: if (attributes != null) {
0387: for (int i = 0; i < attributes.getLength(); ++i) {
0388: Attr attr = (Attr) attributes.item(i);
0389: //removeDefault(attr, attributes);
0390: attr.normalize();
0391: if (fDocument.errorChecking
0392: && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
0393: isAttrValueWF(fErrorHandler, fError,
0394: fLocator, attributes, attr, attr
0395: .getValue(), fDocument
0396: .isXML11Version());
0397: if (fDocument.isXMLVersionChanged()) {
0398: if (fNamespaceValidation) {
0399: wellformed = CoreDocumentImpl
0400: .isValidQName(
0401: node.getPrefix(),
0402: node.getLocalName(),
0403: fDocument
0404: .isXML11Version());
0405: } else {
0406: wellformed = CoreDocumentImpl
0407: .isXMLName(
0408: node.getNodeName(),
0409: fDocument
0410: .isXML11Version());
0411: }
0412: if (!wellformed) {
0413: String msg = DOMMessageFormatter
0414: .formatMessage(
0415: DOMMessageFormatter.DOM_DOMAIN,
0416: "wf-invalid-character-in-node-name",
0417: new Object[] {
0418: "Attr",
0419: node
0420: .getNodeName() });
0421: reportDOMError(fErrorHandler,
0422: fError, fLocator, msg,
0423: DOMError.SEVERITY_ERROR,
0424: "wf-invalid-character-in-node-name");
0425: }
0426: }
0427: }
0428: }
0429: }
0430: }
0431:
0432: if (fValidationHandler != null) {
0433: // REVISIT: possible solutions to discard default content are:
0434: // either we pass some flag to XML Schema validator
0435: // or rely on the PSVI information.
0436: fAttrProxy.setAttributes(attributes, fDocument, elem);
0437: updateQName(elem, fQName); // updates global qname
0438: // set error node in the dom error wrapper
0439: // so if error occurs we can report an error node
0440: fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
0441: fCurrentNode = node;
0442: // call re-validation handler
0443: fValidationHandler.startElement(fQName, fAttrProxy,
0444: null);
0445: }
0446:
0447: // normalize children
0448: Node kid, next;
0449: for (kid = elem.getFirstChild(); kid != null; kid = next) {
0450: next = kid.getNextSibling();
0451: kid = normalizeNode(kid);
0452: if (kid != null) {
0453: next = kid; // don't advance
0454: }
0455: }
0456: if (DEBUG_ND) {
0457: // normalized subtree
0458: System.out.println("***The children of {"
0459: + node.getNodeName() + "} are normalized");
0460: for (kid = elem.getFirstChild(); kid != null; kid = next) {
0461: next = kid.getNextSibling();
0462: System.out.println(kid.getNodeName() + "["
0463: + kid.getNodeValue() + "]");
0464: }
0465:
0466: }
0467:
0468: if (fValidationHandler != null) {
0469: updateQName(elem, fQName); // updates global qname
0470: //
0471: // set error node in the dom error wrapper
0472: // so if error occurs we can report an error node
0473: fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
0474: fCurrentNode = node;
0475: fValidationHandler.endElement(fQName, null);
0476: }
0477:
0478: // pop namespace context
0479: fNamespaceContext.popContext();
0480:
0481: break;
0482: }
0483:
0484: case Node.COMMENT_NODE: {
0485: if (DEBUG_ND) {
0486: System.out.println("==>normalizeNode:{comments}");
0487: }
0488:
0489: if ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0) {
0490: Node prevSibling = node.getPreviousSibling();
0491: Node parent = node.getParentNode();
0492: // remove the comment node
0493: parent.removeChild(node);
0494: if (prevSibling != null
0495: && prevSibling.getNodeType() == Node.TEXT_NODE) {
0496: Node nextSibling = prevSibling.getNextSibling();
0497: if (nextSibling != null
0498: && nextSibling.getNodeType() == Node.TEXT_NODE) {
0499: ((TextImpl) nextSibling).insertData(0,
0500: prevSibling.getNodeValue());
0501: parent.removeChild(prevSibling);
0502: return nextSibling;
0503: }
0504: }
0505: }//if comment node need not be removed
0506: else {
0507: if (fDocument.errorChecking
0508: && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
0509: String commentdata = ((Comment) node).getData();
0510: // check comments for invalid xml chracter as per the version
0511: // of the document
0512: isCommentWF(fErrorHandler, fError, fLocator,
0513: commentdata, fDocument.isXML11Version());
0514: }
0515: if (fValidationHandler != null) {
0516: // Don't bother filling an XMLString with the text of the comment.
0517: // We only send the comment event to the validator handler so that
0518: // when the schema-type is DTD an error will be reported for a
0519: // comment appearing in EMPTY content.
0520: fValidationHandler.comment(EMPTY_STRING, null);
0521: }
0522: }//end-else if comment node is not to be removed.
0523: break;
0524: }
0525: case Node.ENTITY_REFERENCE_NODE: {
0526: if (DEBUG_ND) {
0527: System.out.println("==>normalizeNode:{entityRef} "
0528: + node.getNodeName());
0529: }
0530:
0531: if ((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0) {
0532: Node prevSibling = node.getPreviousSibling();
0533: Node parent = node.getParentNode();
0534: ((EntityReferenceImpl) node).setReadOnly(false, true);
0535: expandEntityRef(parent, node);
0536: parent.removeChild(node);
0537: Node next = (prevSibling != null) ? prevSibling
0538: .getNextSibling() : parent.getFirstChild();
0539: // The list of children #text -> &ent;
0540: // and entity has a first child as a text
0541: // we should not advance
0542: if (prevSibling != null && next != null
0543: && prevSibling.getNodeType() == Node.TEXT_NODE
0544: && next.getNodeType() == Node.TEXT_NODE) {
0545: return prevSibling; // Don't advance
0546: }
0547: return next;
0548: } else {
0549: if (fDocument.errorChecking
0550: && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)
0551: && fDocument.isXMLVersionChanged()) {
0552: CoreDocumentImpl.isXMLName(node.getNodeName(),
0553: fDocument.isXML11Version());
0554: }
0555: // REVISIT: traverse entity reference and send appropriate calls to the validator
0556: // (no normalization should be performed for the children).
0557: }
0558: break;
0559: }
0560:
0561: case Node.CDATA_SECTION_NODE: {
0562: if (DEBUG_ND) {
0563: System.out.println("==>normalizeNode:{cdata}");
0564: }
0565:
0566: if ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) {
0567: // convert CDATA to TEXT nodes
0568: Node prevSibling = node.getPreviousSibling();
0569: if (prevSibling != null
0570: && prevSibling.getNodeType() == Node.TEXT_NODE) {
0571: ((Text) prevSibling)
0572: .appendData(node.getNodeValue());
0573: node.getParentNode().removeChild(node);
0574: return prevSibling; //don't advance
0575: } else {
0576: Text text = fDocument.createTextNode(node
0577: .getNodeValue());
0578: Node parent = node.getParentNode();
0579: node = parent.replaceChild(text, node);
0580: return text; //don't advance
0581:
0582: }
0583: }
0584:
0585: // send characters call for CDATA
0586: if (fValidationHandler != null) {
0587: // set error node in the dom error wrapper
0588: // so if error occurs we can report an error node
0589: fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
0590: fCurrentNode = node;
0591: fValidationHandler.startCDATA(null);
0592: fValidationHandler.characterData(node.getNodeValue(),
0593: null);
0594: fValidationHandler.endCDATA(null);
0595: }
0596: String value = node.getNodeValue();
0597:
0598: if ((fConfiguration.features & DOMConfigurationImpl.SPLITCDATA) != 0) {
0599: int index;
0600: Node parent = node.getParentNode();
0601: if (fDocument.errorChecking) {
0602: isXMLCharWF(fErrorHandler, fError, fLocator, node
0603: .getNodeValue(), fDocument.isXML11Version());
0604: }
0605: while ((index = value.indexOf("]]>")) >= 0) {
0606: node.setNodeValue(value.substring(0, index + 2));
0607: value = value.substring(index + 2);
0608:
0609: Node firstSplitNode = node;
0610: Node newChild = fDocument.createCDATASection(value);
0611: parent
0612: .insertBefore(newChild, node
0613: .getNextSibling());
0614: node = newChild;
0615: // issue warning
0616: fLocator.fRelatedNode = firstSplitNode;
0617: String msg = DOMMessageFormatter.formatMessage(
0618: DOMMessageFormatter.DOM_DOMAIN,
0619: "cdata-sections-splitted", null);
0620: reportDOMError(fErrorHandler, fError, fLocator,
0621: msg, DOMError.SEVERITY_WARNING,
0622: "cdata-sections-splitted");
0623: }
0624:
0625: } else if (fDocument.errorChecking) {
0626: // check well-formedness
0627: isCDataWF(fErrorHandler, fError, fLocator, value,
0628: fDocument.isXML11Version());
0629: }
0630: break;
0631: }
0632:
0633: case Node.TEXT_NODE: {
0634: if (DEBUG_ND) {
0635: System.out.println("==>normalizeNode(text):{"
0636: + node.getNodeValue() + "}");
0637: }
0638: // If node is a text node, we need to check for one of two
0639: // conditions:
0640: // 1) There is an adjacent text node
0641: // 2) There is no adjacent text node, but node is
0642: // an empty text node.
0643: Node next = node.getNextSibling();
0644: // If an adjacent text node, merge it with this node
0645: if (next != null && next.getNodeType() == Node.TEXT_NODE) {
0646: ((Text) node).appendData(next.getNodeValue());
0647: node.getParentNode().removeChild(next);
0648: // We don't need to check well-formness here since we are not yet
0649: // done with this node.
0650:
0651: return node; // Don't advance;
0652: } else if (node.getNodeValue().length() == 0) {
0653: // If kid is empty, remove it
0654: node.getParentNode().removeChild(node);
0655: } else {
0656: // validator.characters() call and well-formness
0657: // Don't send characters or check well-formness in the following cases:
0658: // 1. entities is false, next child is entity reference: expand tree first
0659: // 2. comments is false, and next child is comment
0660: // 3. cdata is false, and next child is cdata
0661:
0662: short nextType = (next != null) ? next.getNodeType()
0663: : -1;
0664: if (nextType == -1
0665: || !(((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0 && nextType == Node.ENTITY_NODE)
0666: || ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0 && nextType == Node.COMMENT_NODE) || ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0)
0667: && nextType == Node.CDATA_SECTION_NODE)) {
0668: if (fDocument.errorChecking
0669: && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
0670: isXMLCharWF(fErrorHandler, fError, fLocator,
0671: node.getNodeValue(), fDocument
0672: .isXML11Version());
0673: }
0674: if (fValidationHandler != null) {
0675: fConfiguration.fErrorHandlerWrapper.fCurrentNode = node;
0676: fCurrentNode = node;
0677: fValidationHandler.characterData(node
0678: .getNodeValue(), null);
0679: if (!fNamespaceValidation) {
0680: if (fAllWhitespace) {
0681: fAllWhitespace = false;
0682: ((TextImpl) node)
0683: .setIgnorableWhitespace(true);
0684: } else {
0685: ((TextImpl) node)
0686: .setIgnorableWhitespace(false);
0687: }
0688: }
0689: if (DEBUG_ND) {
0690: System.out.println("=====>characterData(),"
0691: + nextType);
0692: }
0693: }
0694: } else {
0695: if (DEBUG_ND) {
0696: System.out
0697: .println("=====>don't send characters(),"
0698: + nextType);
0699:
0700: }
0701: }
0702: }
0703: break;
0704: }
0705: case Node.PROCESSING_INSTRUCTION_NODE: {
0706:
0707: //do the well-formed valid PI target name , data check when application has set the value of well-formed feature to true
0708: if (fDocument.errorChecking
0709: && (fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) {
0710: ProcessingInstruction pinode = (ProcessingInstruction) node;
0711:
0712: String target = pinode.getTarget();
0713: //1.check PI target name
0714: if (fDocument.isXML11Version()) {
0715: wellformed = XML11Char.isXML11ValidName(target);
0716: } else {
0717: wellformed = XMLChar.isValidName(target);
0718: }
0719:
0720: if (!wellformed) {
0721: String msg = DOMMessageFormatter.formatMessage(
0722: DOMMessageFormatter.DOM_DOMAIN,
0723: "wf-invalid-character-in-node-name",
0724: new Object[] { "Element",
0725: node.getNodeName() });
0726: reportDOMError(fErrorHandler, fError, fLocator,
0727: msg, DOMError.SEVERITY_ERROR,
0728: "wf-invalid-character-in-node-name");
0729: }
0730:
0731: //2. check PI data
0732: //processing isntruction data may have certain characters
0733: //which may not be valid XML character
0734: isXMLCharWF(fErrorHandler, fError, fLocator, pinode
0735: .getData(), fDocument.isXML11Version());
0736: }
0737:
0738: if (fValidationHandler != null) {
0739: // Don't bother filling an XMLString with the data section of the
0740: // processing instruction. We only send the processing instruction
0741: // event to the validator handler so that when the schema-type is
0742: // DTD an error will be reported for a processing instruction
0743: // appearing in EMPTY content.
0744: fValidationHandler.processingInstruction(
0745: ((ProcessingInstruction) node).getTarget(),
0746: EMPTY_STRING, null);
0747: }
0748: }//end case Node.PROCESSING_INSTRUCTION_NODE
0749:
0750: }//end of switch
0751: return null;
0752: }//normalizeNode
0753:
0754: private void processDTD(String xmlVersion, String schemaLocation) {
0755:
0756: String rootName = null;
0757: String publicId = null;
0758: String systemId = schemaLocation;
0759: String baseSystemId = fDocument.getDocumentURI();
0760: String internalSubset = null;
0761:
0762: DocumentType docType = fDocument.getDoctype();
0763: if (docType != null) {
0764: rootName = docType.getName();
0765: publicId = docType.getPublicId();
0766: if (systemId == null || systemId.length() == 0) {
0767: systemId = docType.getSystemId();
0768: }
0769: internalSubset = docType.getInternalSubset();
0770: }
0771: // If the DOM doesn't have a DocumentType node we may still
0772: // be able to fetch a DTD if the application provided a URI
0773: else {
0774: Element elem = fDocument.getDocumentElement();
0775: if (elem == null)
0776: return;
0777: rootName = elem.getNodeName();
0778: if (systemId == null || systemId.length() == 0)
0779: return;
0780: }
0781:
0782: XMLDTDLoader loader = null;
0783: try {
0784: fValidationHandler.doctypeDecl(rootName, publicId,
0785: systemId, null);
0786: loader = CoreDOMImplementationImpl.singleton
0787: .getDTDLoader(xmlVersion);
0788: loader.setFeature(DOMConfigurationImpl.XERCES_VALIDATION,
0789: true);
0790: loader
0791: .setEntityResolver(fConfiguration
0792: .getEntityResolver());
0793: loader.setErrorHandler(fConfiguration.getErrorHandler());
0794: loader.loadGrammarWithContext(
0795: (XMLDTDValidator) fValidationHandler, rootName,
0796: publicId, systemId, baseSystemId, internalSubset);
0797: }
0798: // REVISIT: Should probably report this exception to the error handler.
0799: catch (IOException e) {
0800: } finally {
0801: if (loader != null) {
0802: CoreDOMImplementationImpl.singleton.releaseDTDLoader(
0803: xmlVersion, loader);
0804: }
0805: }
0806: } // processDTD(String, String)
0807:
0808: protected final void expandEntityRef(Node parent, Node reference) {
0809: Node kid, next;
0810: for (kid = reference.getFirstChild(); kid != null; kid = next) {
0811: next = kid.getNextSibling();
0812: parent.insertBefore(kid, reference);
0813: }
0814: }
0815:
0816: // fix namespaces
0817: // normalize attribute values
0818: // remove default attributes
0819: // check attribute names if the version of the document changed.
0820:
0821: protected final void namespaceFixUp(ElementImpl element,
0822: AttributeMap attributes) {
0823: if (DEBUG) {
0824: System.out.println("[ns-fixup] element:"
0825: + element.getNodeName() + " uri: "
0826: + element.getNamespaceURI());
0827: }
0828:
0829: // ------------------------------------
0830: // pick up local namespace declarations
0831: // <xsl:stylesheet xmlns:xsl="http://xslt">
0832: // <!-- add the following via DOM
0833: // body is bound to http://xslt
0834: // -->
0835: // <xsl:body xmlns:xsl="http://bound"/>
0836: //
0837: // ------------------------------------
0838:
0839: String value, uri, prefix;
0840: if (attributes != null) {
0841:
0842: // Record all valid local declarations
0843: for (int k = 0; k < attributes.getLength(); ++k) {
0844: Attr attr = (Attr) attributes.getItem(k);
0845: uri = attr.getNamespaceURI();
0846: if (uri != null
0847: && uri.equals(NamespaceContext.XMLNS_URI)) {
0848: // namespace attribute
0849: value = attr.getNodeValue();
0850: if (value == null) {
0851: value = XMLSymbols.EMPTY_STRING;
0852: }
0853:
0854: // Check for invalid namespace declaration:
0855: if (fDocument.errorChecking
0856: && value.equals(NamespaceContext.XMLNS_URI)) {
0857: //A null value for locale is passed to formatMessage,
0858: //which means that the default locale will be used
0859: fLocator.fRelatedNode = attr;
0860: String msg = DOMMessageFormatter.formatMessage(
0861: DOMMessageFormatter.XML_DOMAIN,
0862: "CantBindXMLNS", null);
0863: reportDOMError(fErrorHandler, fError, fLocator,
0864: msg, DOMError.SEVERITY_ERROR,
0865: "CantBindXMLNS");
0866: } else {
0867: // XML 1.0 Attribute value normalization
0868: // value = normalizeAttributeValue(value, attr);
0869: prefix = attr.getPrefix();
0870: prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING
0871: : fSymbolTable.addSymbol(prefix);
0872: String localpart = fSymbolTable.addSymbol(attr
0873: .getLocalName());
0874: if (prefix == XMLSymbols.PREFIX_XMLNS) { //xmlns:prefix
0875:
0876: value = fSymbolTable.addSymbol(value);
0877: if (value.length() != 0) {
0878: fNamespaceContext.declarePrefix(
0879: localpart, value);
0880: } else {
0881: // REVISIT: issue error on invalid declarations
0882: // xmlns:foo = ""
0883:
0884: }
0885: //removeDefault (attr, attributes);
0886: continue;
0887: } else { // (localpart == fXmlnsSymbol && prefix == fEmptySymbol) -- xmlns
0888: // empty prefix is always bound ("" or some string)
0889: value = fSymbolTable.addSymbol(value);
0890: fNamespaceContext.declarePrefix(
0891: XMLSymbols.EMPTY_STRING, value
0892: .length() != 0 ? value
0893: : null);
0894: //removeDefault (attr, attributes);
0895: continue;
0896: }
0897: } // end-else: valid declaration
0898: } // end-if: namespace attribute
0899: }
0900: }
0901:
0902: // ---------------------------------------------------------
0903: // Fix up namespaces for element: per DOM L3
0904: // Need to consider the following cases:
0905: //
0906: // case 1: <xsl:stylesheet xmlns:xsl="http://xsl">
0907: // We create another element body bound to the "http://xsl" namespace
0908: // as well as namespace attribute rebounding xsl to another namespace.
0909: // <xsl:body xmlns:xsl="http://another">
0910: // Need to make sure that the new namespace decl value is changed to
0911: // "http://xsl"
0912: //
0913: // ---------------------------------------------------------
0914: // check if prefix/namespace is correct for current element
0915: // ---------------------------------------------------------
0916:
0917: uri = element.getNamespaceURI();
0918: prefix = element.getPrefix();
0919: if (uri != null) { // Element has a namespace
0920: uri = fSymbolTable.addSymbol(uri);
0921: prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING
0922: : fSymbolTable.addSymbol(prefix);
0923: if (fNamespaceContext.getURI(prefix) == uri) {
0924: // The xmlns:prefix=namespace or xmlns="default" was declared at parent.
0925: // The binder always stores mapping of empty prefix to "".
0926: } else {
0927: // the prefix is either undeclared
0928: // or
0929: // conflict: the prefix is bound to another URI
0930: addNamespaceDecl(prefix, uri, element);
0931: fLocalNSBinder.declarePrefix(prefix, uri);
0932: fNamespaceContext.declarePrefix(prefix, uri);
0933: }
0934: } else { // Element has no namespace
0935: if (element.getLocalName() == null) {
0936:
0937: // Error: DOM Level 1 node!
0938: if (fNamespaceValidation) {
0939: String msg = DOMMessageFormatter.formatMessage(
0940: DOMMessageFormatter.DOM_DOMAIN,
0941: "NullLocalElementName",
0942: new Object[] { element.getNodeName() });
0943: reportDOMError(fErrorHandler, fError, fLocator,
0944: msg, DOMError.SEVERITY_FATAL_ERROR,
0945: "NullLocalElementName");
0946: } else {
0947: String msg = DOMMessageFormatter.formatMessage(
0948: DOMMessageFormatter.DOM_DOMAIN,
0949: "NullLocalElementName",
0950: new Object[] { element.getNodeName() });
0951: reportDOMError(fErrorHandler, fError, fLocator,
0952: msg, DOMError.SEVERITY_ERROR,
0953: "NullLocalElementName");
0954: }
0955:
0956: } else { // uri=null and no colon (DOM L2 node)
0957: uri = fNamespaceContext.getURI(XMLSymbols.EMPTY_STRING);
0958: if (uri != null && uri.length() > 0) {
0959: // undeclare default namespace declaration (before that element
0960: // bound to non-zero length uir), but adding xmlns="" decl
0961: addNamespaceDecl(XMLSymbols.EMPTY_STRING,
0962: XMLSymbols.EMPTY_STRING, element);
0963: fLocalNSBinder.declarePrefix(
0964: XMLSymbols.EMPTY_STRING, null);
0965: fNamespaceContext.declarePrefix(
0966: XMLSymbols.EMPTY_STRING, null);
0967: }
0968: }
0969: }
0970:
0971: // -----------------------------------------
0972: // Fix up namespaces for attributes: per DOM L3
0973: // check if prefix/namespace is correct the attributes
0974: // -----------------------------------------
0975: if (attributes != null) {
0976:
0977: // clone content of the attributes
0978: attributes.cloneMap(fAttributeList);
0979: for (int i = 0; i < fAttributeList.size(); i++) {
0980: Attr attr = (Attr) fAttributeList.elementAt(i);
0981: fLocator.fRelatedNode = attr;
0982:
0983: if (DEBUG) {
0984: System.out
0985: .println("==>[ns-fixup] process attribute: "
0986: + attr.getNodeName());
0987: }
0988: // normalize attribute value
0989: attr.normalize();
0990: value = attr.getValue();
0991: uri = attr.getNamespaceURI();
0992:
0993: // make sure that value is never null.
0994: if (value == null) {
0995: value = XMLSymbols.EMPTY_STRING;
0996: }
0997:
0998: //---------------------------------------
0999: // check if value of the attribute is namespace well-formed
1000: //---------------------------------------
1001: if (fDocument.errorChecking
1002: && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) {
1003: isAttrValueWF(fErrorHandler, fError, fLocator,
1004: attributes, attr, value, fDocument
1005: .isXML11Version());
1006: if (fDocument.isXMLVersionChanged()) {
1007: boolean wellformed;
1008: if (fNamespaceValidation) {
1009: wellformed = CoreDocumentImpl.isValidQName(
1010: attr.getPrefix(), attr
1011: .getLocalName(), fDocument
1012: .isXML11Version());
1013: } else {
1014: wellformed = CoreDocumentImpl.isXMLName(
1015: attr.getNodeName(), fDocument
1016: .isXML11Version());
1017: }
1018: if (!wellformed) {
1019: String msg = DOMMessageFormatter
1020: .formatMessage(
1021: DOMMessageFormatter.DOM_DOMAIN,
1022: "wf-invalid-character-in-node-name",
1023: new Object[] { "Attr",
1024: attr.getNodeName() });
1025: reportDOMError(fErrorHandler, fError,
1026: fLocator, msg,
1027: DOMError.SEVERITY_ERROR,
1028: "wf-invalid-character-in-node-name");
1029: }
1030: }
1031: }
1032:
1033: if (uri != null) { // attribute has namespace !=null
1034: prefix = attr.getPrefix();
1035: prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING
1036: : fSymbolTable.addSymbol(prefix);
1037: /*String localpart =*/fSymbolTable.addSymbol(attr
1038: .getLocalName());
1039:
1040: // ---------------------------------------
1041: // skip namespace declarations
1042: // ---------------------------------------
1043: // REVISIT: can we assume that "uri" is from some symbol
1044: // table, and compare by reference? -SG
1045: if (uri != null
1046: && uri.equals(NamespaceContext.XMLNS_URI)) {
1047: continue;
1048: }
1049:
1050: // ---------------------------------------
1051: // remove default attributes
1052: // ---------------------------------------
1053: /*
1054: if (removeDefault(attr, attributes)) {
1055: continue;
1056: }
1057: */
1058: // XML 1.0 Attribute value normalization
1059: //value = normalizeAttributeValue(value, attr);
1060: // reset id-attributes
1061: ((AttrImpl) attr).setIdAttribute(false);
1062:
1063: uri = fSymbolTable.addSymbol(uri);
1064:
1065: // find if for this prefix a URI was already declared
1066: String declaredURI = fNamespaceContext
1067: .getURI(prefix);
1068:
1069: if (prefix == XMLSymbols.EMPTY_STRING
1070: || declaredURI != uri) {
1071: // attribute has no prefix (default namespace decl does not apply to attributes)
1072: // OR
1073: // attribute prefix is not declared
1074: // OR
1075: // conflict: attribute has a prefix that conficlicts with a binding
1076: // already active in scope
1077:
1078: // Find if any prefix for attributes namespace URI is available
1079: // in the scope
1080: String declaredPrefix = fNamespaceContext
1081: .getPrefix(uri);
1082: if (declaredPrefix != null
1083: && declaredPrefix != XMLSymbols.EMPTY_STRING) {
1084:
1085: // use the prefix that was found (declared previously for this URI
1086: prefix = declaredPrefix;
1087: } else {
1088: if (prefix != XMLSymbols.EMPTY_STRING
1089: && fLocalNSBinder.getURI(prefix) == null) {
1090: // the current prefix is not null and it has no in scope declaration
1091:
1092: // use this prefix
1093: } else {
1094:
1095: // find a prefix following the pattern "NS" +index (starting at 1)
1096: // make sure this prefix is not declared in the current scope.
1097: int counter = 1;
1098: prefix = fSymbolTable.addSymbol(PREFIX
1099: + counter++);
1100: while (fLocalNSBinder.getURI(prefix) != null) {
1101: prefix = fSymbolTable
1102: .addSymbol(PREFIX
1103: + counter++);
1104: }
1105:
1106: }
1107: // add declaration for the new prefix
1108: addNamespaceDecl(prefix, uri, element);
1109: value = fSymbolTable.addSymbol(value);
1110: fLocalNSBinder.declarePrefix(prefix, value);
1111: fNamespaceContext
1112: .declarePrefix(prefix, uri);
1113: }
1114:
1115: // change prefix for this attribute
1116: attr.setPrefix(prefix);
1117: }
1118: } else { // attribute uri == null
1119:
1120: // XML 1.0 Attribute value normalization
1121: //value = normalizeAttributeValue(value, attr);
1122:
1123: // reset id-attributes
1124: ((AttrImpl) attr).setIdAttribute(false);
1125:
1126: if (attr.getLocalName() == null) {
1127: // It is an error if document has DOM L1 nodes.
1128: if (fNamespaceValidation) {
1129: String msg = DOMMessageFormatter
1130: .formatMessage(
1131: DOMMessageFormatter.DOM_DOMAIN,
1132: "NullLocalAttrName",
1133: new Object[] { attr
1134: .getNodeName() });
1135: reportDOMError(fErrorHandler, fError,
1136: fLocator, msg,
1137: DOMError.SEVERITY_FATAL_ERROR,
1138: "NullLocalAttrName");
1139: } else {
1140: String msg = DOMMessageFormatter
1141: .formatMessage(
1142: DOMMessageFormatter.DOM_DOMAIN,
1143: "NullLocalAttrName",
1144: new Object[] { attr
1145: .getNodeName() });
1146: reportDOMError(fErrorHandler, fError,
1147: fLocator, msg,
1148: DOMError.SEVERITY_ERROR,
1149: "NullLocalAttrName");
1150: }
1151: } else {
1152: // uri=null and no colon
1153: // no fix up is needed: default namespace decl does not
1154:
1155: // ---------------------------------------
1156: // remove default attributes
1157: // ---------------------------------------
1158: // removeDefault(attr, attributes);
1159: }
1160: }
1161: }
1162: } // end loop for attributes
1163: }
1164:
1165: /**
1166: * Adds a namespace attribute or replaces the value of existing namespace
1167: * attribute with the given prefix and value for URI.
1168: * In case prefix is empty will add/update default namespace declaration.
1169: *
1170: * @param prefix
1171: * @param uri
1172: * @exception IOException
1173: */
1174:
1175: protected final void addNamespaceDecl(String prefix, String uri,
1176: ElementImpl element) {
1177: if (DEBUG) {
1178: System.out.println("[ns-fixup] addNamespaceDecl [" + prefix
1179: + "]");
1180: }
1181: if (prefix == XMLSymbols.EMPTY_STRING) {
1182: if (DEBUG) {
1183: System.out.println("=>add xmlns=\"" + uri
1184: + "\" declaration");
1185: }
1186: element.setAttributeNS(NamespaceContext.XMLNS_URI,
1187: XMLSymbols.PREFIX_XMLNS, uri);
1188: } else {
1189: if (DEBUG) {
1190: System.out.println("=>add xmlns:" + prefix + "=\""
1191: + uri + "\" declaration");
1192: }
1193: element.setAttributeNS(NamespaceContext.XMLNS_URI, "xmlns:"
1194: + prefix, uri);
1195: }
1196: }
1197:
1198: //
1199: // Methods for well-formness checking
1200: //
1201:
1202: /**
1203: * Check if CDATA section is well-formed
1204: * @param datavalue
1205: * @param isXML11Version = true if XML 1.1
1206: */
1207: public static final void isCDataWF(DOMErrorHandler errorHandler,
1208: DOMErrorImpl error, DOMLocatorImpl locator,
1209: String datavalue, boolean isXML11Version) {
1210: if (datavalue == null || (datavalue.length() == 0)) {
1211: return;
1212: }
1213:
1214: char[] dataarray = datavalue.toCharArray();
1215: int datalength = dataarray.length;
1216:
1217: // version of the document is XML 1.1
1218: if (isXML11Version) {
1219: // we need to check all chracters as per production rules of XML11
1220: int i = 0;
1221: while (i < datalength) {
1222: char c = dataarray[i++];
1223: if (XML11Char.isXML11Invalid(c)) {
1224: // check if this is a supplemental character
1225: if (XMLChar.isHighSurrogate(c) && i < datalength) {
1226: char c2 = dataarray[i++];
1227: if (XMLChar.isLowSurrogate(c2)
1228: && XMLChar.isSupplemental(XMLChar
1229: .supplemental(c, c2))) {
1230: continue;
1231: }
1232: }
1233: String msg = DOMMessageFormatter.formatMessage(
1234: DOMMessageFormatter.XML_DOMAIN,
1235: "InvalidCharInCDSect",
1236: new Object[] { Integer.toString(c, 16) });
1237: reportDOMError(errorHandler, error, locator, msg,
1238: DOMError.SEVERITY_ERROR,
1239: "wf-invalid-character");
1240: } else if (c == ']') {
1241: int count = i;
1242: if (count < datalength && dataarray[count] == ']') {
1243: while (++count < datalength
1244: && dataarray[count] == ']') {
1245: // do nothing
1246: }
1247: if (count < datalength
1248: && dataarray[count] == '>') {
1249: // CDEndInContent
1250: String msg = DOMMessageFormatter
1251: .formatMessage(
1252: DOMMessageFormatter.XML_DOMAIN,
1253: "CDEndInContent", null);
1254: reportDOMError(errorHandler, error,
1255: locator, msg,
1256: DOMError.SEVERITY_ERROR,
1257: "wf-invalid-character");
1258: }
1259: }
1260:
1261: }
1262: }
1263: } // version of the document is XML 1.0
1264: else {
1265: // we need to check all chracters as per production rules of XML 1.0
1266: int i = 0;
1267: while (i < datalength) {
1268: char c = dataarray[i++];
1269: if (XMLChar.isInvalid(c)) {
1270: // check if this is a supplemental character
1271: if (XMLChar.isHighSurrogate(c) && i < datalength) {
1272: char c2 = dataarray[i++];
1273: if (XMLChar.isLowSurrogate(c2)
1274: && XMLChar.isSupplemental(XMLChar
1275: .supplemental(c, c2))) {
1276: continue;
1277: }
1278: }
1279: // Note: The key InvalidCharInCDSect from XMLMessages.properties
1280: // is being used to obtain the message and DOM error type
1281: // "wf-invalid-character" is used. Also per DOM it is error but
1282: // as per XML spec. it is fatal error
1283: String msg = DOMMessageFormatter.formatMessage(
1284: DOMMessageFormatter.XML_DOMAIN,
1285: "InvalidCharInCDSect",
1286: new Object[] { Integer.toString(c, 16) });
1287: reportDOMError(errorHandler, error, locator, msg,
1288: DOMError.SEVERITY_ERROR,
1289: "wf-invalid-character");
1290: } else if (c == ']') {
1291: int count = i;
1292: if (count < datalength && dataarray[count] == ']') {
1293: while (++count < datalength
1294: && dataarray[count] == ']') {
1295: // do nothing
1296: }
1297: if (count < datalength
1298: && dataarray[count] == '>') {
1299: String msg = DOMMessageFormatter
1300: .formatMessage(
1301: DOMMessageFormatter.XML_DOMAIN,
1302: "CDEndInContent", null);
1303: reportDOMError(errorHandler, error,
1304: locator, msg,
1305: DOMError.SEVERITY_ERROR,
1306: "wf-invalid-character");
1307: }
1308: }
1309:
1310: }
1311: }
1312: } // end-else fDocument.isXMLVersion()
1313:
1314: } // isCDataWF
1315:
1316: /**
1317: * NON-DOM: check for valid XML characters as per the XML version
1318: * @param datavalue
1319: * @param isXML11Version = true if XML 1.1
1320: */
1321: public static final void isXMLCharWF(DOMErrorHandler errorHandler,
1322: DOMErrorImpl error, DOMLocatorImpl locator,
1323: String datavalue, boolean isXML11Version) {
1324: if (datavalue == null || (datavalue.length() == 0)) {
1325: return;
1326: }
1327:
1328: char[] dataarray = datavalue.toCharArray();
1329: int datalength = dataarray.length;
1330:
1331: // version of the document is XML 1.1
1332: if (isXML11Version) {
1333: //we need to check all characters as per production rules of XML11
1334: int i = 0;
1335: while (i < datalength) {
1336: if (XML11Char.isXML11Invalid(dataarray[i++])) {
1337: // check if this is a supplemental character
1338: char ch = dataarray[i - 1];
1339: if (XMLChar.isHighSurrogate(ch) && i < datalength) {
1340: char ch2 = dataarray[i++];
1341: if (XMLChar.isLowSurrogate(ch2)
1342: && XMLChar.isSupplemental(XMLChar
1343: .supplemental(ch, ch2))) {
1344: continue;
1345: }
1346: }
1347: String msg = DOMMessageFormatter.formatMessage(
1348: DOMMessageFormatter.DOM_DOMAIN,
1349: "InvalidXMLCharInDOM",
1350: new Object[] { Integer.toString(
1351: dataarray[i - 1], 16) });
1352: reportDOMError(errorHandler, error, locator, msg,
1353: DOMError.SEVERITY_ERROR,
1354: "wf-invalid-character");
1355: }
1356: }
1357: } // version of the document is XML 1.0
1358: else {
1359: // we need to check all characters as per production rules of XML 1.0
1360: int i = 0;
1361: while (i < datalength) {
1362: if (XMLChar.isInvalid(dataarray[i++])) {
1363: // check if this is a supplemental character
1364: char ch = dataarray[i - 1];
1365: if (XMLChar.isHighSurrogate(ch) && i < datalength) {
1366: char ch2 = dataarray[i++];
1367: if (XMLChar.isLowSurrogate(ch2)
1368: && XMLChar.isSupplemental(XMLChar
1369: .supplemental(ch, ch2))) {
1370: continue;
1371: }
1372: }
1373: String msg = DOMMessageFormatter.formatMessage(
1374: DOMMessageFormatter.DOM_DOMAIN,
1375: "InvalidXMLCharInDOM",
1376: new Object[] { Integer.toString(
1377: dataarray[i - 1], 16) });
1378: reportDOMError(errorHandler, error, locator, msg,
1379: DOMError.SEVERITY_ERROR,
1380: "wf-invalid-character");
1381: }
1382: }
1383: } // end-else fDocument.isXMLVersion()
1384:
1385: } // isXMLCharWF
1386:
1387: /**
1388: * NON-DOM: check if value of the comment is well-formed
1389: * @param datavalue
1390: * @param isXML11Version = true if XML 1.1
1391: */
1392: public static final void isCommentWF(DOMErrorHandler errorHandler,
1393: DOMErrorImpl error, DOMLocatorImpl locator,
1394: String datavalue, boolean isXML11Version) {
1395: if (datavalue == null || (datavalue.length() == 0)) {
1396: return;
1397: }
1398:
1399: char[] dataarray = datavalue.toCharArray();
1400: int datalength = dataarray.length;
1401:
1402: // version of the document is XML 1.1
1403: if (isXML11Version) {
1404: // we need to check all chracters as per production rules of XML11
1405: int i = 0;
1406: while (i < datalength) {
1407: char c = dataarray[i++];
1408: if (XML11Char.isXML11Invalid(c)) {
1409: // check if this is a supplemental character
1410: if (XMLChar.isHighSurrogate(c) && i < datalength) {
1411: char c2 = dataarray[i++];
1412: if (XMLChar.isLowSurrogate(c2)
1413: && XMLChar.isSupplemental(XMLChar
1414: .supplemental(c, c2))) {
1415: continue;
1416: }
1417: }
1418: String msg = DOMMessageFormatter.formatMessage(
1419: DOMMessageFormatter.XML_DOMAIN,
1420: "InvalidCharInComment",
1421: new Object[] { Integer.toString(
1422: dataarray[i - 1], 16) });
1423: reportDOMError(errorHandler, error, locator, msg,
1424: DOMError.SEVERITY_ERROR,
1425: "wf-invalid-character");
1426: } else if (c == '-' && i < datalength
1427: && dataarray[i] == '-') {
1428: String msg = DOMMessageFormatter.formatMessage(
1429: DOMMessageFormatter.XML_DOMAIN,
1430: "DashDashInComment", null);
1431: // invalid: '--' in comment
1432: reportDOMError(errorHandler, error, locator, msg,
1433: DOMError.SEVERITY_ERROR,
1434: "wf-invalid-character");
1435: }
1436: }
1437: } // version of the document is XML 1.0
1438: else {
1439: // we need to check all chracters as per production rules of XML 1.0
1440: int i = 0;
1441: while (i < datalength) {
1442: char c = dataarray[i++];
1443: if (XMLChar.isInvalid(c)) {
1444: // check if this is a supplemental character
1445: if (XMLChar.isHighSurrogate(c) && i < datalength) {
1446: char c2 = dataarray[i++];
1447: if (XMLChar.isLowSurrogate(c2)
1448: && XMLChar.isSupplemental(XMLChar
1449: .supplemental(c, c2))) {
1450: continue;
1451: }
1452: }
1453: String msg = DOMMessageFormatter.formatMessage(
1454: DOMMessageFormatter.XML_DOMAIN,
1455: "InvalidCharInComment",
1456: new Object[] { Integer.toString(
1457: dataarray[i - 1], 16) });
1458: reportDOMError(errorHandler, error, locator, msg,
1459: DOMError.SEVERITY_ERROR,
1460: "wf-invalid-character");
1461: } else if (c == '-' && i < datalength
1462: && dataarray[i] == '-') {
1463: String msg = DOMMessageFormatter.formatMessage(
1464: DOMMessageFormatter.XML_DOMAIN,
1465: "DashDashInComment", null);
1466: // invalid: '--' in comment
1467: reportDOMError(errorHandler, error, locator, msg,
1468: DOMError.SEVERITY_ERROR,
1469: "wf-invalid-character");
1470: }
1471: }
1472:
1473: } // end-else fDocument.isXMLVersion()
1474:
1475: } // isCommentWF
1476:
1477: /** NON-DOM: check if attribute value is well-formed
1478: * @param attributes
1479: * @param a
1480: * @param value
1481: */
1482: public static final void isAttrValueWF(
1483: DOMErrorHandler errorHandler, DOMErrorImpl error,
1484: DOMLocatorImpl locator, NamedNodeMap attributes, Attr a,
1485: String value, boolean xml11Version) {
1486: if (a instanceof AttrImpl && ((AttrImpl) a).hasStringValue()) {
1487: isXMLCharWF(errorHandler, error, locator, value,
1488: xml11Version);
1489: } else {
1490: NodeList children = a.getChildNodes();
1491: //check each child node of the attribute's value
1492: for (int j = 0; j < children.getLength(); j++) {
1493: Node child = children.item(j);
1494: //If the attribute's child is an entity refernce
1495: if (child.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
1496: Document owner = a.getOwnerDocument();
1497: Entity ent = null;
1498: //search for the entity in the docType
1499: //of the attribute's ownerDocument
1500: if (owner != null) {
1501: DocumentType docType = owner.getDoctype();
1502: if (docType != null) {
1503: NamedNodeMap entities = docType
1504: .getEntities();
1505: ent = (Entity) entities.getNamedItemNS("*",
1506: child.getNodeName());
1507: }
1508: }
1509: //If the entity was not found issue a fatal error
1510: if (ent == null) {
1511: String msg = DOMMessageFormatter.formatMessage(
1512: DOMMessageFormatter.DOM_DOMAIN,
1513: "UndeclaredEntRefInAttrValue",
1514: new Object[] { a.getNodeName() });
1515: reportDOMError(errorHandler, error, locator,
1516: msg, DOMError.SEVERITY_ERROR,
1517: "UndeclaredEntRefInAttrValue");
1518: }
1519: } else {
1520: // Text node
1521: isXMLCharWF(errorHandler, error, locator, child
1522: .getNodeValue(), xml11Version);
1523: }
1524: }
1525: }
1526: }
1527:
1528: /**
1529: * Reports a DOM error to the user handler.
1530: *
1531: * If the error is fatal, the processing will be always aborted.
1532: */
1533: public static final void reportDOMError(
1534: DOMErrorHandler errorHandler, DOMErrorImpl error,
1535: DOMLocatorImpl locator, String message, short severity,
1536: String type) {
1537: if (errorHandler != null) {
1538: error.reset();
1539: error.fMessage = message;
1540: error.fSeverity = severity;
1541: error.fLocator = locator;
1542: error.fType = type;
1543: error.fRelatedData = locator.fRelatedNode;
1544:
1545: if (!errorHandler.handleError(error))
1546: throw abort;
1547: }
1548: if (severity == DOMError.SEVERITY_FATAL_ERROR)
1549: throw abort;
1550: }
1551:
1552: protected final void updateQName(Node node, QName qname) {
1553:
1554: String prefix = node.getPrefix();
1555: String namespace = node.getNamespaceURI();
1556: String localName = node.getLocalName();
1557: // REVISIT: the symbols are added too often: start/endElement
1558: // and in the namespaceFixup. Should reduce number of calls to symbol table.
1559: qname.prefix = (prefix != null && prefix.length() != 0) ? fSymbolTable
1560: .addSymbol(prefix)
1561: : null;
1562: qname.localpart = (localName != null) ? fSymbolTable
1563: .addSymbol(localName) : null;
1564: qname.rawname = fSymbolTable.addSymbol(node.getNodeName());
1565: qname.uri = (namespace != null) ? fSymbolTable
1566: .addSymbol(namespace) : null;
1567: }
1568:
1569: /* REVISIT: remove this method if DOM does not change spec.
1570: * Performs partial XML 1.0 attribute value normalization and replaces
1571: * attribute value if the value is changed after the normalization.
1572: * DOM defines that normalizeDocument acts as if the document was going
1573: * through a save and load cycle, given that serializer will not escape
1574: * any '\n' or '\r' characters on load those will be normalized.
1575: * Thus during normalize document we need to do the following:
1576: * - perform "2.11 End-of-Line Handling"
1577: * - replace #xD, #xA, #x9 with #x20 (white space).
1578: * Note: This alg. won't attempt to resolve entity references or character entity
1579: * references, since '&' will be escaped during serialization and during loading
1580: * this won't be recognized as entity reference, i.e. attribute value "&foo;" will
1581: * be serialized as "&foo;" and thus after loading will be "&foo;" again.
1582: * @param value current attribute value
1583: * @param attr current attribute
1584: * @return String the value (could be original if normalization did not change
1585: * the string)
1586: */
1587: final String normalizeAttributeValue(String value, Attr attr) {
1588: if (!attr.getSpecified()) {
1589: // specified attributes should already have a normalized form
1590: // since those were added by validator
1591: return value;
1592: }
1593: int end = value.length();
1594: // ensure capacity
1595: if (fNormalizedValue.ch.length < end) {
1596: fNormalizedValue.ch = new char[end];
1597: }
1598: fNormalizedValue.length = 0;
1599: boolean normalized = false;
1600: for (int i = 0; i < end; i++) {
1601: char c = value.charAt(i);
1602: if (c == 0x0009 || c == 0x000A) {
1603: fNormalizedValue.ch[fNormalizedValue.length++] = ' ';
1604: normalized = true;
1605: } else if (c == 0x000D) {
1606: normalized = true;
1607: fNormalizedValue.ch[fNormalizedValue.length++] = ' ';
1608: int next = i + 1;
1609: if (next < end && value.charAt(next) == 0x000A)
1610: i = next; // skip following xA
1611: } else {
1612: fNormalizedValue.ch[fNormalizedValue.length++] = c;
1613: }
1614: }
1615: if (normalized) {
1616: value = fNormalizedValue.toString();
1617: attr.setValue(value);
1618: }
1619: return value;
1620: }
1621:
1622: protected final class XMLAttributesProxy implements XMLAttributes {
1623: protected AttributeMap fAttributes;
1624: protected CoreDocumentImpl fDocument;
1625: protected ElementImpl fElement;
1626:
1627: protected final Vector fDTDTypes = new Vector(5);
1628: protected final Vector fAugmentations = new Vector(5);
1629:
1630: public void setAttributes(AttributeMap attributes,
1631: CoreDocumentImpl doc, ElementImpl elem) {
1632: fDocument = doc;
1633: fAttributes = attributes;
1634: fElement = elem;
1635: if (attributes != null) {
1636: int length = attributes.getLength();
1637: fDTDTypes.setSize(length);
1638: fAugmentations.setSize(length);
1639: // REVISIT: this implementation does not store any value in augmentations
1640: // and basically not keeping augs in parallel to attributes map
1641: // untill all attributes are added (default attributes)
1642: for (int i = 0; i < length; i++) {
1643: fAugmentations.setElementAt(
1644: new AugmentationsImpl(), i);
1645: }
1646: } else {
1647: fDTDTypes.setSize(0);
1648: fAugmentations.setSize(0);
1649: }
1650: }
1651:
1652: /**
1653: * This method adds default declarations
1654: * @see org.apache.xerces.xni.XMLAttributes#addAttribute(QName, String, String)
1655: */
1656: public int addAttribute(QName qname, String attrType,
1657: String attrValue) {
1658: int index = fElement.getXercesAttribute(qname.uri,
1659: qname.localpart);
1660: // add defaults to the tree
1661: if (index < 0) {
1662: // the default attribute was removed by a user and needed to
1663: // be added back
1664: AttrImpl attr = (AttrImpl) ((CoreDocumentImpl) fElement
1665: .getOwnerDocument()).createAttributeNS(
1666: qname.uri, qname.rawname, qname.localpart);
1667: // REVISIT: the following should also update ID table
1668: attr.setNodeValue(attrValue);
1669: index = fElement.setXercesAttributeNode(attr);
1670: fDTDTypes.insertElementAt(attrType, index);
1671: fAugmentations.insertElementAt(new AugmentationsImpl(),
1672: index);
1673: attr.setSpecified(false);
1674: } else {
1675: // default attribute is in the tree
1676: // we don't need to do anything since prefix was already fixed
1677: // at the namespace fixup time and value must be same value, otherwise
1678: // attribute will be treated as specified and we will never reach
1679: // this method.
1680:
1681: }
1682: return index;
1683: }
1684:
1685: public void removeAllAttributes() {
1686: // REVISIT: implement
1687: }
1688:
1689: public void removeAttributeAt(int attrIndex) {
1690: // REVISIT: implement
1691: }
1692:
1693: public int getLength() {
1694: return (fAttributes != null) ? fAttributes.getLength() : 0;
1695: }
1696:
1697: public int getIndex(String qName) {
1698: // REVISIT: implement
1699: return -1;
1700: }
1701:
1702: public int getIndex(String uri, String localPart) {
1703: // REVISIT: implement
1704: return -1;
1705: }
1706:
1707: public void setName(int attrIndex, QName attrName) {
1708: // REVISIT: implement
1709: }
1710:
1711: public void getName(int attrIndex, QName attrName) {
1712: if (fAttributes != null) {
1713: updateQName((Node) fAttributes.getItem(attrIndex),
1714: attrName);
1715: }
1716: }
1717:
1718: public String getPrefix(int index) {
1719: if (fAttributes != null) {
1720: Node node = (Node) fAttributes.getItem(index);
1721: String prefix = node.getPrefix();
1722: prefix = (prefix != null && prefix.length() != 0) ? fSymbolTable
1723: .addSymbol(prefix)
1724: : null;
1725: return prefix;
1726: }
1727: return null;
1728: }
1729:
1730: public String getURI(int index) {
1731: if (fAttributes != null) {
1732: Node node = (Node) fAttributes.getItem(index);
1733: String namespace = node.getNamespaceURI();
1734: namespace = (namespace != null) ? fSymbolTable
1735: .addSymbol(namespace) : null;
1736: return namespace;
1737: }
1738: return null;
1739: }
1740:
1741: public String getLocalName(int index) {
1742: if (fAttributes != null) {
1743: Node node = (Node) fAttributes.getItem(index);
1744: String localName = node.getLocalName();
1745: localName = (localName != null) ? fSymbolTable
1746: .addSymbol(localName) : null;
1747: return localName;
1748: }
1749: return null;
1750: }
1751:
1752: public String getQName(int index) {
1753: if (fAttributes != null) {
1754: Node node = (Node) fAttributes.getItem(index);
1755: String rawname = fSymbolTable.addSymbol(node
1756: .getNodeName());
1757: return rawname;
1758: }
1759: return null;
1760: }
1761:
1762: public void setType(int attrIndex, String attrType) {
1763: fDTDTypes.setElementAt(attrType, attrIndex);
1764: }
1765:
1766: public String getType(int index) {
1767: String type = (String) fDTDTypes.elementAt(index);
1768: return (type != null) ? getReportableType(type) : "CDATA";
1769: }
1770:
1771: public String getType(String qName) {
1772: return "CDATA";
1773: }
1774:
1775: public String getType(String uri, String localName) {
1776: return "CDATA";
1777: }
1778:
1779: private String getReportableType(String type) {
1780: if (type.charAt(0) == '(') {
1781: return "NMTOKEN";
1782: }
1783: return type;
1784: }
1785:
1786: public void setValue(int attrIndex, String attrValue) {
1787: // REVISIT: is this desired behaviour?
1788: // The values are updated in the case datatype-normalization is turned on
1789: // in this case we need to make sure that specified attributes stay specified
1790:
1791: if (fAttributes != null) {
1792: AttrImpl attr = (AttrImpl) fAttributes
1793: .getItem(attrIndex);
1794: boolean specified = attr.getSpecified();
1795: attr.setValue(attrValue);
1796: attr.setSpecified(specified);
1797:
1798: }
1799: }
1800:
1801: public String getValue(int index) {
1802: return (fAttributes != null) ? fAttributes.item(index)
1803: .getNodeValue() : "";
1804:
1805: }
1806:
1807: public String getValue(String qName) {
1808: // REVISIT: implement
1809: return null;
1810: }
1811:
1812: public String getValue(String uri, String localName) {
1813: if (fAttributes != null) {
1814: Node node = fAttributes.getNamedItemNS(uri, localName);
1815: return (node != null) ? node.getNodeValue() : null;
1816: }
1817: return null;
1818: }
1819:
1820: public void setNonNormalizedValue(int attrIndex,
1821: String attrValue) {
1822: // REVISIT: implement
1823:
1824: }
1825:
1826: public String getNonNormalizedValue(int attrIndex) {
1827: // REVISIT: implement
1828: return null;
1829: }
1830:
1831: public void setSpecified(int attrIndex, boolean specified) {
1832: AttrImpl attr = (AttrImpl) fAttributes.getItem(attrIndex);
1833: attr.setSpecified(specified);
1834: }
1835:
1836: public boolean isSpecified(int attrIndex) {
1837: return ((Attr) fAttributes.getItem(attrIndex))
1838: .getSpecified();
1839: }
1840:
1841: public Augmentations getAugmentations(int attributeIndex) {
1842: return (Augmentations) fAugmentations
1843: .elementAt(attributeIndex);
1844: }
1845:
1846: public Augmentations getAugmentations(String uri,
1847: String localPart) {
1848: // REVISIT: implement
1849: return null;
1850: }
1851:
1852: public Augmentations getAugmentations(String qName) {
1853: // REVISIT: implement
1854: return null;
1855: }
1856:
1857: /**
1858: * Sets the augmentations of the attribute at the specified index.
1859: *
1860: * @param attrIndex The attribute index.
1861: * @param augs The augmentations.
1862: */
1863: public void setAugmentations(int attrIndex, Augmentations augs) {
1864: fAugmentations.setElementAt(augs, attrIndex);
1865: }
1866: }
1867:
1868: //
1869: // XMLDocumentHandler methods
1870: //
1871:
1872: /**
1873: * The start of the document.
1874: *
1875: * @param locator The document locator, or null if the document
1876: * location cannot be reported during the parsing
1877: * of this document. However, it is <em>strongly</em>
1878: * recommended that a locator be supplied that can
1879: * at least report the system identifier of the
1880: * document.
1881: * @param encoding The auto-detected IANA encoding name of the entity
1882: * stream. This value will be null in those situations
1883: * where the entity encoding is not auto-detected (e.g.
1884: * internal entities or a document entity that is
1885: * parsed from a java.io.Reader).
1886: * @param namespaceContext
1887: * The namespace context in effect at the
1888: * start of this document.
1889: * This object represents the current context.
1890: * Implementors of this class are responsible
1891: * for copying the namespace bindings from the
1892: * the current context (and its parent contexts)
1893: * if that information is important.
1894: *
1895: * @param augs Additional information that may include infoset augmentations
1896: * @exception XNIException
1897: * Thrown by handler to signal an error.
1898: */
1899: public void startDocument(XMLLocator locator, String encoding,
1900: NamespaceContext namespaceContext, Augmentations augs)
1901: throws XNIException {
1902: }
1903:
1904: /**
1905: * Notifies of the presence of an XMLDecl line in the document. If
1906: * present, this method will be called immediately following the
1907: * startDocument call.
1908: *
1909: * @param version The XML version.
1910: * @param encoding The IANA encoding name of the document, or null if
1911: * not specified.
1912: * @param standalone The standalone value, or null if not specified.
1913: * @param augs Additional information that may include infoset augmentations
1914: *
1915: * @exception XNIException
1916: * Thrown by handler to signal an error.
1917: */
1918: public void xmlDecl(String version, String encoding,
1919: String standalone, Augmentations augs) throws XNIException {
1920: }
1921:
1922: /**
1923: * Notifies of the presence of the DOCTYPE line in the document.
1924: *
1925: * @param rootElement
1926: * The name of the root element.
1927: * @param publicId The public identifier if an external DTD or null
1928: * if the external DTD is specified using SYSTEM.
1929: * @param systemId The system identifier if an external DTD, null
1930: * otherwise.
1931: * @param augs Additional information that may include infoset augmentations
1932: *
1933: * @exception XNIException
1934: * Thrown by handler to signal an error.
1935: */
1936: public void doctypeDecl(String rootElement, String publicId,
1937: String systemId, Augmentations augs) throws XNIException {
1938: }
1939:
1940: /**
1941: * A comment.
1942: *
1943: * @param text The text in the comment.
1944: * @param augs Additional information that may include infoset augmentations
1945: *
1946: * @exception XNIException
1947: * Thrown by application to signal an error.
1948: */
1949: public void comment(XMLString text, Augmentations augs)
1950: throws XNIException {
1951: }
1952:
1953: /**
1954: * A processing instruction. Processing instructions consist of a
1955: * target name and, optionally, text data. The data is only meaningful
1956: * to the application.
1957: * <p>
1958: * Typically, a processing instruction's data will contain a series
1959: * of pseudo-attributes. These pseudo-attributes follow the form of
1960: * element attributes but are <strong>not</strong> parsed or presented
1961: * to the application as anything other than text. The application is
1962: * responsible for parsing the data.
1963: *
1964: * @param target The target.
1965: * @param data The data or null if none specified.
1966: * @param augs Additional information that may include infoset augmentations
1967: *
1968: * @exception XNIException
1969: * Thrown by handler to signal an error.
1970: */
1971: public void processingInstruction(String target, XMLString data,
1972: Augmentations augs) throws XNIException {
1973: }
1974:
1975: /**
1976: * The start of an element.
1977: *
1978: * @param element The name of the element.
1979: * @param attributes The element attributes.
1980: * @param augs Additional information that may include infoset augmentations
1981: *
1982: * @exception XNIException
1983: * Thrown by handler to signal an error.
1984: */
1985: public void startElement(QName element, XMLAttributes attributes,
1986: Augmentations augs) throws XNIException {
1987: Element currentElement = (Element) fCurrentNode;
1988: int attrCount = attributes.getLength();
1989: if (DEBUG_EVENTS) {
1990: System.out.println("==>startElement: " + element
1991: + " attrs.length=" + attrCount);
1992: }
1993:
1994: for (int i = 0; i < attrCount; i++) {
1995: attributes.getName(i, fAttrQName);
1996: Attr attr = null;
1997:
1998: attr = currentElement.getAttributeNodeNS(fAttrQName.uri,
1999: fAttrQName.localpart);
2000: if (attr == null) {
2001: // Must be a non-namespace aware DOM Level 1 node.
2002: attr = currentElement
2003: .getAttributeNode(fAttrQName.rawname);
2004: }
2005: AttributePSVI attrPSVI = (AttributePSVI) attributes
2006: .getAugmentations(i).getItem(
2007: Constants.ATTRIBUTE_PSVI);
2008:
2009: if (attrPSVI != null) {
2010: //REVISIT: instead we should be using augmentations:
2011: // to set/retrieve Id attributes
2012: XSTypeDefinition decl = attrPSVI
2013: .getMemberTypeDefinition();
2014: boolean id = false;
2015: if (decl != null) {
2016: id = ((XSSimpleType) decl).isIDType();
2017: } else {
2018: decl = attrPSVI.getTypeDefinition();
2019: if (decl != null) {
2020: id = ((XSSimpleType) decl).isIDType();
2021: }
2022: }
2023: if (id) {
2024: ((ElementImpl) currentElement).setIdAttributeNode(
2025: attr, true);
2026: }
2027:
2028: if (fPSVI) {
2029: ((PSVIAttrNSImpl) attr).setPSVI(attrPSVI);
2030: }
2031:
2032: // Updating the TypeInfo for this attribute.
2033: ((AttrImpl) attr).setType(decl);
2034:
2035: if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
2036: // datatype-normalization
2037: // NOTE: The specified value MUST be set after we set
2038: // the node value because that turns the "specified"
2039: // flag to "true" which may overwrite a "false"
2040: // value from the attribute list.
2041: final String normalizedValue = attrPSVI
2042: .getSchemaNormalizedValue();
2043: if (normalizedValue != null) {
2044: boolean specified = attr.getSpecified();
2045: attr.setValue(normalizedValue);
2046: if (!specified) {
2047: ((AttrImpl) attr).setSpecified(specified);
2048: }
2049: }
2050: }
2051: } else { // DTD
2052: String type = null;
2053: boolean isDeclared = Boolean.TRUE.equals(attributes
2054: .getAugmentations(i).getItem(
2055: Constants.ATTRIBUTE_DECLARED));
2056: // For DOM Level 3 TypeInfo, the type name must
2057: // be null if this attribute has not been declared
2058: // in the DTD.
2059: if (isDeclared) {
2060: type = attributes.getType(i);
2061: if ("ID".equals(type)) {
2062: ((ElementImpl) currentElement)
2063: .setIdAttributeNode(attr, true);
2064: }
2065: }
2066: // Updating the TypeInfo for this attribute.
2067: ((AttrImpl) attr).setType(type);
2068: }
2069: }
2070: }
2071:
2072: /**
2073: * An empty element.
2074: *
2075: * @param element The name of the element.
2076: * @param attributes The element attributes.
2077: * @param augs Additional information that may include infoset augmentations
2078: *
2079: * @exception XNIException
2080: * Thrown by handler to signal an error.
2081: */
2082: public void emptyElement(QName element, XMLAttributes attributes,
2083: Augmentations augs) throws XNIException {
2084: if (DEBUG_EVENTS) {
2085: System.out.println("==>emptyElement: " + element);
2086: }
2087:
2088: startElement(element, attributes, augs);
2089: endElement(element, augs);
2090: }
2091:
2092: /**
2093: * This method notifies the start of a general entity.
2094: * <p>
2095: * <strong>Note:</strong> This method is not called for entity references
2096: * appearing as part of attribute values.
2097: *
2098: * @param name The name of the general entity.
2099: * @param identifier The resource identifier.
2100: * @param encoding The auto-detected IANA encoding name of the entity
2101: * stream. This value will be null in those situations
2102: * where the entity encoding is not auto-detected (e.g.
2103: * internal entities or a document entity that is
2104: * parsed from a java.io.Reader).
2105: * @param augs Additional information that may include infoset augmentations
2106: *
2107: * @exception XNIException Thrown by handler to signal an error.
2108: */
2109: public void startGeneralEntity(String name,
2110: XMLResourceIdentifier identifier, String encoding,
2111: Augmentations augs) throws XNIException {
2112: }
2113:
2114: /**
2115: * Notifies of the presence of a TextDecl line in an entity. If present,
2116: * this method will be called immediately following the startEntity call.
2117: * <p>
2118: * <strong>Note:</strong> This method will never be called for the
2119: * document entity; it is only called for external general entities
2120: * referenced in document content.
2121: * <p>
2122: * <strong>Note:</strong> This method is not called for entity references
2123: * appearing as part of attribute values.
2124: *
2125: * @param version The XML version, or null if not specified.
2126: * @param encoding The IANA encoding name of the entity.
2127: * @param augs Additional information that may include infoset augmentations
2128: *
2129: * @exception XNIException
2130: * Thrown by handler to signal an error.
2131: */
2132: public void textDecl(String version, String encoding,
2133: Augmentations augs) throws XNIException {
2134: }
2135:
2136: /**
2137: * This method notifies the end of a general entity.
2138: * <p>
2139: * <strong>Note:</strong> This method is not called for entity references
2140: * appearing as part of attribute values.
2141: *
2142: * @param name The name of the entity.
2143: * @param augs Additional information that may include infoset augmentations
2144: *
2145: * @exception XNIException
2146: * Thrown by handler to signal an error.
2147: */
2148: public void endGeneralEntity(String name, Augmentations augs)
2149: throws XNIException {
2150: }
2151:
2152: /**
2153: * Character content.
2154: *
2155: * @param text The content.
2156: * @param augs Additional information that may include infoset augmentations
2157: *
2158: * @exception XNIException
2159: * Thrown by handler to signal an error.
2160: */
2161: public void characters(XMLString text, Augmentations augs)
2162: throws XNIException {
2163: }
2164:
2165: /**
2166: * Ignorable whitespace. For this method to be called, the document
2167: * source must have some way of determining that the text containing
2168: * only whitespace characters should be considered ignorable. For
2169: * example, the validator can determine if a length of whitespace
2170: * characters in the document are ignorable based on the element
2171: * content model.
2172: *
2173: * @param text The ignorable whitespace.
2174: * @param augs Additional information that may include infoset augmentations
2175: *
2176: * @exception XNIException
2177: * Thrown by handler to signal an error.
2178: */
2179: public void ignorableWhitespace(XMLString text, Augmentations augs)
2180: throws XNIException {
2181: fAllWhitespace = true;
2182: }
2183:
2184: /**
2185: * The end of an element.
2186: *
2187: * @param element The name of the element.
2188: * @param augs Additional information that may include infoset augmentations
2189: *
2190: * @exception XNIException
2191: * Thrown by handler to signal an error.
2192: */
2193: public void endElement(QName element, Augmentations augs)
2194: throws XNIException {
2195: if (DEBUG_EVENTS) {
2196: System.out.println("==>endElement: " + element);
2197: }
2198:
2199: if (augs != null) {
2200: ElementPSVI elementPSVI = (ElementPSVI) augs
2201: .getItem(Constants.ELEMENT_PSVI);
2202: if (elementPSVI != null) {
2203: ElementImpl elementNode = (ElementImpl) fCurrentNode;
2204: if (fPSVI) {
2205: ((PSVIElementNSImpl) fCurrentNode)
2206: .setPSVI(elementPSVI);
2207: }
2208: // Updating the TypeInfo for this element.
2209: if (elementNode instanceof ElementNSImpl) {
2210: XSTypeDefinition type = elementPSVI
2211: .getMemberTypeDefinition();
2212: if (type == null) {
2213: type = elementPSVI.getTypeDefinition();
2214: }
2215: ((ElementNSImpl) elementNode).setType(type);
2216: }
2217: // include element default content (if one is available)
2218: String normalizedValue = elementPSVI
2219: .getSchemaNormalizedValue();
2220: if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) {
2221: if (normalizedValue != null)
2222: elementNode.setTextContent(normalizedValue);
2223: } else {
2224: // NOTE: this is a hack: it is possible that DOM had an empty element
2225: // and validator sent default value using characters(), which we don't
2226: // implement. Thus, here we attempt to add the default value.
2227: String text = elementNode.getTextContent();
2228: if (text.length() == 0) {
2229: // default content could be provided
2230: if (normalizedValue != null)
2231: elementNode.setTextContent(normalizedValue);
2232: }
2233: }
2234: return;
2235: }
2236: }
2237: // DTD; elements have no type.
2238: if (fCurrentNode instanceof ElementNSImpl) {
2239: ((ElementNSImpl) fCurrentNode).setType(null);
2240: }
2241: }
2242:
2243: /**
2244: * The start of a CDATA section.
2245: *
2246: * @param augs Additional information that may include infoset augmentations
2247: *
2248: * @exception XNIException
2249: * Thrown by handler to signal an error.
2250: */
2251: public void startCDATA(Augmentations augs) throws XNIException {
2252: }
2253:
2254: /**
2255: * The end of a CDATA section.
2256: *
2257: * @param augs Additional information that may include infoset augmentations
2258: *
2259: * @exception XNIException
2260: * Thrown by handler to signal an error.
2261: */
2262: public void endCDATA(Augmentations augs) throws XNIException {
2263: }
2264:
2265: /**
2266: * The end of the document.
2267: *
2268: * @param augs Additional information that may include infoset augmentations
2269: *
2270: * @exception XNIException
2271: * Thrown by handler to signal an error.
2272: */
2273: public void endDocument(Augmentations augs) throws XNIException {
2274: }
2275:
2276: /** Sets the document source. */
2277: public void setDocumentSource(XMLDocumentSource source) {
2278: }
2279:
2280: /** Returns the document source. */
2281: public XMLDocumentSource getDocumentSource() {
2282: return null;
2283: }
2284:
2285: } // DOMNormalizer class
|