1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xerces.internal.dom; 23 24 25 import java.io.IOException; 26 import java.util.ArrayList; 27 import java.io.StringReader; 28 import java.util.Vector; 29 30 import com.sun.org.apache.xerces.internal.dom.AbortException; 31 import com.sun.org.apache.xerces.internal.impl.Constants; 32 import com.sun.org.apache.xerces.internal.impl.RevalidationHandler; 33 import com.sun.org.apache.xerces.internal.impl.dtd.DTDGrammar; 34 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDDescription; 35 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator; 36 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; 37 import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator; 38 import com.sun.org.apache.xerces.internal.parsers.XMLGrammarPreparser; 39 import com.sun.org.apache.xerces.internal.util.AugmentationsImpl; 40 import com.sun.org.apache.xerces.internal.util.NamespaceSupport; 41 import com.sun.org.apache.xerces.internal.util.SymbolTable; 42 import com.sun.org.apache.xerces.internal.util.XML11Char; 43 import com.sun.org.apache.xerces.internal.util.XMLChar; 44 import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl; 45 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 46 import com.sun.org.apache.xerces.internal.xni.Augmentations; 47 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 48 import com.sun.org.apache.xerces.internal.xni.QName; 49 import com.sun.org.apache.xerces.internal.xni.XMLAttributes; 50 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; 51 import com.sun.org.apache.xerces.internal.xni.XMLLocator; 52 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; 53 import com.sun.org.apache.xerces.internal.xni.XMLString; 54 import com.sun.org.apache.xerces.internal.xni.XNIException; 55 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; 56 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; 57 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent; 58 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; 59 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; 60 import com.sun.org.apache.xerces.internal.xs.AttributePSVI; 61 import com.sun.org.apache.xerces.internal.xs.ElementPSVI; 62 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; 63 import org.w3c.dom.Attr; 64 import org.w3c.dom.Comment; 65 import org.w3c.dom.DOMError; 66 import org.w3c.dom.DOMErrorHandler; 67 import org.w3c.dom.Document; 68 import org.w3c.dom.DocumentType; 69 import org.w3c.dom.Element; 70 import org.w3c.dom.Entity; 71 import org.w3c.dom.NamedNodeMap; 72 import org.w3c.dom.Node; 73 import org.w3c.dom.NodeList; 74 import org.w3c.dom.ProcessingInstruction; 75 import org.w3c.dom.Text; 76 /** 77 * This class adds implementation for normalizeDocument method. 78 * It acts as if the document was going through a save and load cycle, putting 79 * the document in a "normal" form. The actual result depends on the features being set 80 * and governing what operations actually take place. See setNormalizationFeature for details. 81 * Noticeably this method normalizes Text nodes, makes the document "namespace wellformed", 82 * according to the algorithm described below in pseudo code, by adding missing namespace 83 * declaration attributes and adding or changing namespace prefixes, updates the replacement 84 * tree of EntityReference nodes, normalizes attribute values, etc. 85 * Mutation events, when supported, are generated to reflect the changes occuring on the 86 * document. 87 * See Namespace normalization for details on how namespace declaration attributes and prefixes 88 * are normalized. 89 * 90 * NOTE: There is an initial support for DOM revalidation with XML Schema as a grammar. 91 * The tree might not be validated correctly if entityReferences, CDATA sections are 92 * present in the tree. The PSVI information is not exposed, normalized data (including element 93 * default content is not available). 94 * 95 * @xerces.experimental 96 * 97 * @author Elena Litani, IBM 98 * @author Neeraj Bajaj, Sun Microsystems, inc. 99 * @version $Id: DOMNormalizer.java,v 1.9 2010-11-01 04:39:38 joehw Exp $ 100 */ 101 public class DOMNormalizer implements XMLDocumentHandler { 102 103 // 104 // constants 105 // 106 /** Debug normalize document*/ 107 protected final static boolean DEBUG_ND = false; 108 /** Debug namespace fix up algorithm*/ 109 protected final static boolean DEBUG = false; 110 /** Debug document handler events */ 111 protected final static boolean DEBUG_EVENTS = false; 112 113 /** prefix added by namespace fixup algorithm should follow a pattern "NS" + index*/ 114 protected final static String PREFIX = "NS"; 115 116 // 117 // Data 118 // 119 protected DOMConfigurationImpl fConfiguration = null; 120 protected CoreDocumentImpl fDocument = null; 121 protected final XMLAttributesProxy fAttrProxy = new XMLAttributesProxy(); 122 protected final QName fQName = new QName(); 123 124 /** Validation handler represents validator instance. */ 125 protected RevalidationHandler fValidationHandler; 126 127 /** symbol table */ 128 protected SymbolTable fSymbolTable; 129 /** error handler. may be null. */ 130 protected DOMErrorHandler fErrorHandler; 131 132 /** 133 * Cached {@link DOMError} impl. 134 * The same object is re-used to report multiple errors. 135 */ 136 private final DOMErrorImpl fError = new DOMErrorImpl(); 137 138 // Validation against namespace aware grammar 139 protected boolean fNamespaceValidation = false; 140 141 // Update PSVI information in the tree 142 protected boolean fPSVI = false; 143 144 /** The namespace context of this document: stores namespaces in scope */ 145 protected final NamespaceContext fNamespaceContext = new NamespaceSupport(); 146 147 /** Stores all namespace bindings on the current element */ 148 protected final NamespaceContext fLocalNSBinder = new NamespaceSupport(); 149 150 /** list of attributes */ 151 protected final ArrayList fAttributeList = new ArrayList(5); 152 153 /** DOM Locator - for namespace fixup algorithm */ 154 protected final DOMLocatorImpl fLocator = new DOMLocatorImpl(); 155 156 /** for setting the PSVI */ 157 protected Node fCurrentNode = null; 158 private QName fAttrQName = new QName(); 159 160 // attribute value normalization 161 final XMLString fNormalizedValue = new XMLString(new char[16], 0, 0); 162 163 //DTD validator 164 private XMLDTDValidator fDTDValidator; 165 166 //Check if element content is all "ignorable whitespace" 167 private boolean allWhitespace = false; 168 169 // Constructor 170 // 171 172 public DOMNormalizer(){} 173 174 175 176 /** 177 * Normalizes document. 178 * Note: reset() must be called before this method. 179 */ 180 protected void normalizeDocument(CoreDocumentImpl document, DOMConfigurationImpl config) { 181 182 fDocument = document; 183 fConfiguration = config; 184 185 // intialize and reset DOMNormalizer component 186 // 187 fSymbolTable = (SymbolTable) fConfiguration.getProperty(DOMConfigurationImpl.SYMBOL_TABLE); 188 // reset namespace context 189 fNamespaceContext.reset(); 190 fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); 191 192 if ((fConfiguration.features & DOMConfigurationImpl.VALIDATE) != 0) { 193 String schemaLang = (String)fConfiguration.getProperty(DOMConfigurationImpl.JAXP_SCHEMA_LANGUAGE); 194 195 if(schemaLang != null && schemaLang.equals(Constants.NS_XMLSCHEMA)) { 196 fValidationHandler = 197 CoreDOMImplementationImpl.singleton.getValidator(XMLGrammarDescription.XML_SCHEMA); 198 fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA, true); 199 fConfiguration.setFeature(DOMConfigurationImpl.SCHEMA_FULL_CHECKING, true); 200 // report fatal error on DOM Level 1 nodes 201 fNamespaceValidation = true; 202 203 // check if we need to fill in PSVI 204 fPSVI = ((fConfiguration.features & DOMConfigurationImpl.PSVI) !=0)?true:false; 205 } 206 207 fConfiguration.setFeature(DOMConfigurationImpl.XERCES_VALIDATION, true); 208 209 // reset ID table 210 fDocument.clearIdentifiers(); 211 212 if(fValidationHandler != null) 213 // reset schema validator 214 ((XMLComponent) fValidationHandler).reset(fConfiguration); 215 216 } 217 218 fErrorHandler = (DOMErrorHandler) fConfiguration.getParameter(Constants.DOM_ERROR_HANDLER); 219 if (fValidationHandler != null) { 220 fValidationHandler.setDocumentHandler(this); 221 fValidationHandler.startDocument( 222 new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI, 223 -1, -1 ), fDocument.encoding, fNamespaceContext, null); 224 225 } 226 try { 227 Node kid, next; 228 for (kid = fDocument.getFirstChild(); kid != null; kid = next) { 229 next = kid.getNextSibling(); 230 kid = normalizeNode(kid); 231 if (kid != null) { // don't advance 232 next = kid; 233 } 234 } 235 236 // release resources 237 if (fValidationHandler != null) { 238 fValidationHandler.endDocument(null); 239 CoreDOMImplementationImpl.singleton.releaseValidator( 240 XMLGrammarDescription.XML_SCHEMA, fValidationHandler); 241 fValidationHandler = null; 242 } 243 } catch (AbortException e) { 244 return; 245 } catch (RuntimeException e) { 246 throw e; // otherwise re-throw. 247 } 248 249 } 250 251 252 /** 253 * 254 * This method acts as if the document was going through a save 255 * and load cycle, putting the document in a "normal" form. The actual result 256 * depends on the features being set and governing what operations actually 257 * take place. See setNormalizationFeature for details. Noticeably this method 258 * normalizes Text nodes, makes the document "namespace wellformed", 259 * according to the algorithm described below in pseudo code, by adding missing 260 * namespace declaration attributes and adding or changing namespace prefixes, updates 261 * the replacement tree of EntityReference nodes,normalizes attribute values, etc. 262 * 263 * @param node Modified node or null. If node is returned, we need 264 * to normalize again starting on the node returned. 265 * @return the normalized Node 266 */ 267 protected Node normalizeNode (Node node){ 268 269 int type = node.getNodeType(); 270 boolean wellformed; 271 fLocator.fRelatedNode=node; 272 273 switch (type) { 274 case Node.DOCUMENT_TYPE_NODE: { 275 if (DEBUG_ND) { 276 System.out.println("==>normalizeNode:{doctype}"); 277 } 278 DocumentTypeImpl docType = (DocumentTypeImpl)node; 279 fDTDValidator = (XMLDTDValidator)CoreDOMImplementationImpl.singleton.getValidator(XMLGrammarDescription.XML_DTD); 280 fDTDValidator.setDocumentHandler(this); 281 fConfiguration.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY, createGrammarPool(docType)); 282 fDTDValidator.reset(fConfiguration); 283 fDTDValidator.startDocument( 284 new SimpleLocator(fDocument.fDocumentURI, fDocument.fDocumentURI, 285 -1, -1 ), fDocument.encoding, fNamespaceContext, null); 286 fDTDValidator.doctypeDecl(docType.getName(), docType.getPublicId(), docType.getSystemId(), null); 287 //REVISIT: well-formness encoding info 288 break; 289 } 290 291 case Node.ELEMENT_NODE: { 292 if (DEBUG_ND) { 293 System.out.println("==>normalizeNode:{element} "+node.getNodeName()); 294 } 295 296 //do the name check only when version of the document was changed & 297 //application has set the value of well-formed features to true 298 if (fDocument.errorChecking) { 299 if ( ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) && 300 fDocument.isXMLVersionChanged()){ 301 if (fNamespaceValidation){ 302 wellformed = CoreDocumentImpl.isValidQName(node.getPrefix() , node.getLocalName(), fDocument.isXML11Version()) ; 303 } 304 else { 305 wellformed = CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version()); 306 } 307 if (!wellformed){ 308 String msg = DOMMessageFormatter.formatMessage( 309 DOMMessageFormatter.DOM_DOMAIN, 310 "wf-invalid-character-in-node-name", 311 new Object[]{"Element", node.getNodeName()}); 312 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 313 "wf-invalid-character-in-node-name"); 314 } 315 } 316 } 317 // push namespace context 318 fNamespaceContext.pushContext(); 319 fLocalNSBinder.reset(); 320 321 ElementImpl elem = (ElementImpl)node; 322 if (elem.needsSyncChildren()) { 323 elem.synchronizeChildren(); 324 } 325 AttributeMap attributes = (elem.hasAttributes()) ? (AttributeMap) elem.getAttributes() : null; 326 327 // fix namespaces and remove default attributes 328 if ((fConfiguration.features & DOMConfigurationImpl.NAMESPACES) !=0) { 329 // fix namespaces 330 // normalize attribute values 331 // remove default attributes 332 namespaceFixUp(elem, attributes); 333 334 if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0 && attributes != null ) { 335 for (int i = 0; i < attributes.getLength(); ++i) { 336 Attr att = (Attr)attributes.getItem(i); 337 if (XMLSymbols.PREFIX_XMLNS.equals(att.getPrefix()) || 338 XMLSymbols.PREFIX_XMLNS.equals(att.getName())) { 339 elem.removeAttributeNode(att); 340 --i; 341 } 342 } 343 } 344 345 } else { 346 if ( attributes!=null ) { 347 for ( int i=0; i<attributes.getLength(); ++i ) { 348 Attr attr = (Attr)attributes.item(i); 349 //removeDefault(attr, attributes); 350 attr.normalize(); 351 if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){ 352 isAttrValueWF(fErrorHandler, fError, fLocator, attributes, (AttrImpl)attr, attr.getValue(), fDocument.isXML11Version()); 353 if (fDocument.isXMLVersionChanged()){ 354 wellformed=CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version()); 355 if (!wellformed){ 356 String msg = DOMMessageFormatter.formatMessage( 357 DOMMessageFormatter.DOM_DOMAIN, 358 "wf-invalid-character-in-node-name", 359 new Object[]{"Attr",node.getNodeName()}); 360 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 361 "wf-invalid-character-in-node-name"); 362 } 363 } 364 } 365 } 366 } 367 } 368 369 370 if (fValidationHandler != null) { 371 // REVISIT: possible solutions to discard default content are: 372 // either we pass some flag to XML Schema validator 373 // or rely on the PSVI information. 374 fAttrProxy.setAttributes(attributes, fDocument, elem); 375 updateQName(elem, fQName); // updates global qname 376 // set error node in the dom error wrapper 377 // so if error occurs we can report an error node 378 fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; 379 fCurrentNode = node; 380 // call re-validation handler 381 fValidationHandler.startElement(fQName, fAttrProxy, null); 382 } 383 384 if (fDTDValidator != null) { 385 // REVISIT: possible solutions to discard default content are: 386 // either we pass some flag to XML Schema validator 387 // or rely on the PSVI information. 388 fAttrProxy.setAttributes(attributes, fDocument, elem); 389 updateQName(elem, fQName); // updates global qname 390 // set error node in the dom error wrapper 391 // so if error occurs we can report an error node 392 fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; 393 fCurrentNode = node; 394 // call re-validation handler 395 fDTDValidator.startElement(fQName, fAttrProxy, null); 396 } 397 398 // normalize children 399 Node kid, next; 400 for (kid = elem.getFirstChild(); kid != null; kid = next) { 401 next = kid.getNextSibling(); 402 kid = normalizeNode(kid); 403 if (kid !=null) { 404 next = kid; // don't advance 405 } 406 } 407 if (DEBUG_ND) { 408 // normalized subtree 409 System.out.println("***The children of {"+node.getNodeName()+"} are normalized"); 410 for (kid = elem.getFirstChild(); kid != null; kid = next) { 411 next = kid.getNextSibling(); 412 System.out.println(kid.getNodeName() +"["+kid.getNodeValue()+"]"); 413 } 414 415 } 416 417 418 if (fValidationHandler != null) { 419 updateQName(elem, fQName); // updates global qname 420 // 421 // set error node in the dom error wrapper 422 // so if error occurs we can report an error node 423 fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; 424 fCurrentNode = node; 425 fValidationHandler.endElement(fQName, null); 426 } 427 428 if (fDTDValidator != null) { 429 updateQName(elem, fQName); // updates global qname 430 // 431 // set error node in the dom error wrapper 432 // so if error occurs we can report an error node 433 fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; 434 fCurrentNode = node; 435 fDTDValidator.endElement(fQName, null); 436 } 437 438 // pop namespace context 439 fNamespaceContext.popContext(); 440 441 break; 442 } 443 444 case Node.COMMENT_NODE: { 445 if (DEBUG_ND) { 446 System.out.println("==>normalizeNode:{comments}"); 447 } 448 449 if ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0) { 450 Node prevSibling = node.getPreviousSibling(); 451 Node parent = node.getParentNode(); 452 // remove the comment node 453 parent.removeChild(node); 454 if (prevSibling != null && prevSibling.getNodeType() == Node.TEXT_NODE) { 455 Node nextSibling = prevSibling.getNextSibling(); 456 if (nextSibling != null && nextSibling.getNodeType() == Node.TEXT_NODE) { 457 ((TextImpl)nextSibling).insertData(0, prevSibling.getNodeValue()); 458 parent.removeChild(prevSibling); 459 return nextSibling; 460 } 461 } 462 }//if comment node need not be removed 463 else { 464 if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)){ 465 String commentdata = ((Comment)node).getData(); 466 // check comments for invalid xml chracter as per the version 467 // of the document 468 isCommentWF(fErrorHandler, fError, fLocator, commentdata, fDocument.isXML11Version()); 469 } 470 }//end-else if comment node is not to be removed. 471 break; 472 } 473 case Node.ENTITY_REFERENCE_NODE: { 474 if (DEBUG_ND) { 475 System.out.println("==>normalizeNode:{entityRef} "+node.getNodeName()); 476 } 477 478 if ((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0) { 479 Node prevSibling = node.getPreviousSibling(); 480 Node parent = node.getParentNode(); 481 ((EntityReferenceImpl)node).setReadOnly(false, true); 482 expandEntityRef (parent, node); 483 parent.removeChild(node); 484 Node next = (prevSibling != null)?prevSibling.getNextSibling():parent.getFirstChild(); 485 // The list of children #text -> &ent; 486 // and entity has a first child as a text 487 // we should not advance 488 if (prevSibling != null && next != null && prevSibling.getNodeType() == Node.TEXT_NODE && 489 next.getNodeType() == Node.TEXT_NODE) { 490 return prevSibling; // Don't advance 491 } 492 return next; 493 } else { 494 if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) && 495 fDocument.isXMLVersionChanged()){ 496 CoreDocumentImpl.isXMLName(node.getNodeName() , fDocument.isXML11Version()); 497 } 498 // REVISIT: traverse entity reference and send appropriate calls to the validator 499 // (no normalization should be performed for the children). 500 } 501 break; 502 } 503 504 case Node.CDATA_SECTION_NODE: { 505 if (DEBUG_ND) { 506 System.out.println("==>normalizeNode:{cdata}"); 507 } 508 509 if ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) { 510 // convert CDATA to TEXT nodes 511 Node prevSibling = node.getPreviousSibling(); 512 if (prevSibling != null && prevSibling.getNodeType() == Node.TEXT_NODE){ 513 ((Text)prevSibling).appendData(node.getNodeValue()); 514 node.getParentNode().removeChild(node); 515 return prevSibling; //don't advance 516 } 517 else { 518 Text text = fDocument.createTextNode(node.getNodeValue()); 519 Node parent = node.getParentNode(); 520 node = parent.replaceChild(text, node); 521 return text; //don't advance 522 523 } 524 } 525 526 // send characters call for CDATA 527 if (fValidationHandler != null) { 528 // set error node in the dom error wrapper 529 // so if error occurs we can report an error node 530 fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; 531 fCurrentNode = node; 532 fValidationHandler.startCDATA(null); 533 fValidationHandler.characterData(node.getNodeValue(), null); 534 fValidationHandler.endCDATA(null); 535 } 536 537 if (fDTDValidator != null) { 538 // set error node in the dom error wrapper 539 // so if error occurs we can report an error node 540 fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; 541 fCurrentNode = node; 542 fDTDValidator.startCDATA(null); 543 fDTDValidator.characterData(node.getNodeValue(), null); 544 fDTDValidator.endCDATA(null); 545 } 546 String value = node.getNodeValue(); 547 548 if ((fConfiguration.features & DOMConfigurationImpl.SPLITCDATA) != 0) { 549 int index; 550 Node parent = node.getParentNode(); 551 if (fDocument.errorChecking) { 552 isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version()); 553 } 554 while ( (index=value.indexOf("]]>")) >= 0 ) { 555 node.setNodeValue(value.substring(0, index+2)); 556 value = value.substring(index +2); 557 558 Node firstSplitNode = node; 559 Node newChild = fDocument.createCDATASection(value); 560 parent.insertBefore(newChild, node.getNextSibling()); 561 node = newChild; 562 // issue warning 563 fLocator.fRelatedNode = firstSplitNode; 564 String msg = DOMMessageFormatter.formatMessage( 565 DOMMessageFormatter.DOM_DOMAIN, 566 "cdata-sections-splitted", 567 null); 568 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_WARNING, 569 "cdata-sections-splitted"); 570 } 571 572 } 573 else if (fDocument.errorChecking) { 574 // check well-formedness 575 isCDataWF(fErrorHandler, fError, fLocator, value, fDocument.isXML11Version()); 576 } 577 break; 578 } 579 580 case Node.TEXT_NODE: { 581 if (DEBUG_ND) { 582 System.out.println("==>normalizeNode(text):{"+node.getNodeValue()+"}"); 583 } 584 // If node is a text node, we need to check for one of two 585 // conditions: 586 // 1) There is an adjacent text node 587 // 2) There is no adjacent text node, but node is 588 // an empty text node. 589 Node next = node.getNextSibling(); 590 // If an adjacent text node, merge it with this node 591 if ( next!=null && next.getNodeType() == Node.TEXT_NODE ) { 592 ((Text)node).appendData(next.getNodeValue()); 593 node.getParentNode().removeChild( next ); 594 // We don't need to check well-formness here since we are not yet 595 // done with this node. 596 597 return node; // Don't advance; 598 } else if (node.getNodeValue().length()==0) { 599 // If kid is empty, remove it 600 node.getParentNode().removeChild( node ); 601 } else { 602 // validator.characters() call and well-formness 603 // Don't send characters or check well-formness in the following cases: 604 // 1. entities is false, next child is entity reference: expand tree first 605 // 2. comments is false, and next child is comment 606 // 3. cdata is false, and next child is cdata 607 608 short nextType = (next != null)?next.getNodeType():-1; 609 if (nextType == -1 || !(((fConfiguration.features & DOMConfigurationImpl.ENTITIES) == 0 && 610 nextType == Node.ENTITY_NODE) || 611 ((fConfiguration.features & DOMConfigurationImpl.COMMENTS) == 0 && 612 nextType == Node.COMMENT_NODE) || 613 ((fConfiguration.features & DOMConfigurationImpl.CDATA) == 0) && 614 nextType == Node.CDATA_SECTION_NODE)) { 615 if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) ){ 616 isXMLCharWF(fErrorHandler, fError, fLocator, node.getNodeValue(), fDocument.isXML11Version()); 617 } 618 if (fValidationHandler != null) { 619 fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; 620 fCurrentNode = node; 621 fValidationHandler.characterData(node.getNodeValue(), null); 622 if (DEBUG_ND) { 623 System.out.println("=====>characterData(),"+nextType); 624 625 } 626 } 627 if (fDTDValidator != null) { 628 fConfiguration.fErrorHandlerWrapper.fCurrentNode = node; 629 fCurrentNode = node; 630 fDTDValidator.characterData(node.getNodeValue(), null); 631 if (DEBUG_ND) { 632 System.out.println("=====>characterData(),"+nextType); 633 634 } 635 if(allWhitespace) { 636 allWhitespace = false; 637 ((TextImpl)node).setIgnorableWhitespace(true); 638 } 639 } 640 } 641 else { 642 if (DEBUG_ND) { 643 System.out.println("=====>don't send characters(),"+nextType); 644 645 } 646 } 647 } 648 break; 649 } 650 case Node.PROCESSING_INSTRUCTION_NODE: { 651 652 //do the well-formed valid PI target name , data check when application has set the value of well-formed feature to true 653 if (fDocument.errorChecking && (fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0 ) { 654 ProcessingInstruction pinode = (ProcessingInstruction)node ; 655 656 String target = pinode.getTarget(); 657 //1.check PI target name 658 if(fDocument.isXML11Version()){ 659 wellformed = XML11Char.isXML11ValidName(target); 660 } 661 else{ 662 wellformed = XMLChar.isValidName(target); 663 } 664 665 if (!wellformed) { 666 String msg = DOMMessageFormatter.formatMessage( 667 DOMMessageFormatter.DOM_DOMAIN, 668 "wf-invalid-character-in-node-name", 669 new Object[]{"Element", node.getNodeName()}); 670 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 671 "wf-invalid-character-in-node-name"); 672 } 673 674 //2. check PI data 675 //processing isntruction data may have certain characters 676 //which may not be valid XML character 677 isXMLCharWF(fErrorHandler, fError, fLocator, pinode.getData(), fDocument.isXML11Version()); 678 } 679 }//end case Node.PROCESSING_INSTRUCTION_NODE 680 681 }//end of switch 682 return null; 683 }//normalizeNode 684 685 private XMLGrammarPool createGrammarPool(DocumentTypeImpl docType) { 686 687 XMLGrammarPoolImpl pool = new XMLGrammarPoolImpl(); 688 689 XMLGrammarPreparser preParser = new XMLGrammarPreparser(fSymbolTable); 690 preParser.registerPreparser(XMLGrammarDescription.XML_DTD, null); 691 preParser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE, true); 692 preParser.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATION_FEATURE, true); 693 preParser.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY, pool); 694 695 String internalSubset = docType.getInternalSubset(); 696 XMLInputSource is = new XMLInputSource(docType.getPublicId(), docType.getSystemId(), null); 697 698 if(internalSubset != null) 699 is.setCharacterStream(new StringReader(internalSubset)); 700 try { 701 DTDGrammar g = (DTDGrammar)preParser.preparseGrammar(XMLGrammarDescription.XML_DTD, is); 702 ((XMLDTDDescription)g.getGrammarDescription()).setRootName(docType.getName()); 703 is.setCharacterStream(null); 704 g = (DTDGrammar)preParser.preparseGrammar(XMLGrammarDescription.XML_DTD, is); 705 ((XMLDTDDescription)g.getGrammarDescription()).setRootName(docType.getName()); 706 707 } catch (XNIException e) { 708 } catch (IOException e) { 709 } 710 711 return pool; 712 } 713 714 715 716 protected final void expandEntityRef (Node parent, Node reference){ 717 Node kid, next; 718 for (kid = reference.getFirstChild(); kid != null; kid = next) { 719 next = kid.getNextSibling(); 720 parent.insertBefore(kid, reference); 721 } 722 } 723 724 // fix namespaces 725 // normalize attribute values 726 // remove default attributes 727 // check attribute names if the version of the document changed. 728 729 protected final void namespaceFixUp (ElementImpl element, AttributeMap attributes){ 730 if (DEBUG) { 731 System.out.println("[ns-fixup] element:" +element.getNodeName()+ 732 " uri: "+element.getNamespaceURI()); 733 } 734 735 // ------------------------------------ 736 // pick up local namespace declarations 737 // <xsl:stylesheet xmlns:xsl="http://xslt"> 738 // <!-- add the following via DOM 739 // body is bound to http://xslt 740 // --> 741 // <xsl:body xmlns:xsl="http://bound"/> 742 // 743 // ------------------------------------ 744 745 String value, name, uri, prefix; 746 if (attributes != null) { 747 748 // Record all valid local declarations 749 for (int k = 0; k < attributes.getLength(); ++k) { 750 Attr attr = (Attr)attributes.getItem(k); 751 752 //do the name check only when version of the document was changed & 753 //application has set the value of well-formed features to true 754 if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0) && 755 fDocument.isXMLVersionChanged()) { 756 //checkQName does checking based on the version of the document 757 fDocument.checkQName(attr.getPrefix() , attr.getLocalName()) ; 758 } 759 760 uri = attr.getNamespaceURI(); 761 if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) { 762 // namespace attribute 763 764 // "namespace-declarations" == false; Discard all namespace declaration attributes 765 if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) { 766 continue; 767 } 768 769 value = attr.getNodeValue(); 770 if (value == null) { 771 value=XMLSymbols.EMPTY_STRING; 772 } 773 774 // Check for invalid namespace declaration: 775 if (fDocument.errorChecking && value.equals(NamespaceContext.XMLNS_URI)) { 776 //A null value for locale is passed to formatMessage, 777 //which means that the default locale will be used 778 fLocator.fRelatedNode = attr; 779 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN,"CantBindXMLNS",null ); 780 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, "CantBindXMLNS"); 781 } else { 782 // XML 1.0 Attribute value normalization 783 // value = normalizeAttributeValue(value, attr); 784 prefix = attr.getPrefix(); 785 prefix = (prefix == null || 786 prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix); 787 String localpart = fSymbolTable.addSymbol( attr.getLocalName()); 788 if (prefix == XMLSymbols.PREFIX_XMLNS) { //xmlns:prefix 789 790 value = fSymbolTable.addSymbol(value); 791 if (value.length() != 0) { 792 fNamespaceContext.declarePrefix(localpart, value); 793 } else { 794 // REVISIT: issue error on invalid declarations 795 // xmlns:foo = "" 796 797 } 798 //removeDefault (attr, attributes); 799 continue; 800 } else { // (localpart == fXmlnsSymbol && prefix == fEmptySymbol) -- xmlns 801 // empty prefix is always bound ("" or some string) 802 value = fSymbolTable.addSymbol(value); 803 fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value); 804 //removeDefault (attr, attributes); 805 continue; 806 } 807 } // end-else: valid declaration 808 } // end-if: namespace attribute 809 } 810 } 811 812 813 814 // --------------------------------------------------------- 815 // Fix up namespaces for element: per DOM L3 816 // Need to consider the following cases: 817 // 818 // case 1: <xsl:stylesheet xmlns:xsl="http://xsl"> 819 // We create another element body bound to the "http://xsl" namespace 820 // as well as namespace attribute rebounding xsl to another namespace. 821 // <xsl:body xmlns:xsl="http://another"> 822 // Need to make sure that the new namespace decl value is changed to 823 // "http://xsl" 824 // 825 // --------------------------------------------------------- 826 // check if prefix/namespace is correct for current element 827 // --------------------------------------------------------- 828 829 uri = element.getNamespaceURI(); 830 prefix = element.getPrefix(); 831 832 // "namespace-declarations" == false? Discard all namespace declaration attributes 833 if ((fConfiguration.features & DOMConfigurationImpl.NSDECL) == 0) { 834 // no namespace declaration == no namespace URI, semantics are to keep prefix 835 uri = null; 836 } else if (uri != null) { // Element has a namespace 837 uri = fSymbolTable.addSymbol(uri); 838 prefix = (prefix == null || 839 prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix); 840 if (fNamespaceContext.getURI(prefix) == uri) { 841 // The xmlns:prefix=namespace or xmlns="default" was declared at parent. 842 // The binder always stores mapping of empty prefix to "". 843 } else { 844 // the prefix is either undeclared 845 // or 846 // conflict: the prefix is bound to another URI 847 addNamespaceDecl(prefix, uri, element); 848 fLocalNSBinder.declarePrefix(prefix, uri); 849 fNamespaceContext.declarePrefix(prefix, uri); 850 } 851 } else { // Element has no namespace 852 if (element.getLocalName() == null) { 853 854 // Error: DOM Level 1 node! 855 if (fNamespaceValidation) { 856 String msg = DOMMessageFormatter.formatMessage( 857 DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName", 858 new Object[]{element.getNodeName()}); 859 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR, 860 "NullLocalElementName"); 861 } else { 862 String msg = DOMMessageFormatter.formatMessage( 863 DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName", 864 new Object[]{element.getNodeName()}); 865 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 866 "NullLocalElementName"); 867 } 868 869 } else { // uri=null and no colon (DOM L2 node) 870 uri = fNamespaceContext.getURI(XMLSymbols.EMPTY_STRING); 871 if (uri !=null && uri.length() > 0) { 872 // undeclare default namespace declaration (before that element 873 // bound to non-zero length uir), but adding xmlns="" decl 874 addNamespaceDecl (XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING, element); 875 fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); 876 fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); 877 } 878 } 879 } 880 881 // ----------------------------------------- 882 // Fix up namespaces for attributes: per DOM L3 883 // check if prefix/namespace is correct the attributes 884 // ----------------------------------------- 885 if (attributes != null) { 886 887 // clone content of the attributes 888 attributes.cloneMap(fAttributeList); 889 for (int i = 0; i < fAttributeList.size(); i++) { 890 Attr attr = (Attr) fAttributeList.get(i); 891 fLocator.fRelatedNode = attr; 892 893 if (DEBUG) { 894 System.out.println("==>[ns-fixup] process attribute: "+attr.getNodeName()); 895 } 896 // normalize attribute value 897 attr.normalize(); 898 value = attr.getValue(); 899 name = attr.getNodeName(); 900 uri = attr.getNamespaceURI(); 901 902 // make sure that value is never null. 903 if (value == null) { 904 value=XMLSymbols.EMPTY_STRING; 905 } 906 907 if (uri != null) { // attribute has namespace !=null 908 prefix = attr.getPrefix(); 909 prefix = (prefix == null || 910 prefix.length() == 0) ? XMLSymbols.EMPTY_STRING :fSymbolTable.addSymbol(prefix); 911 /*String localpart =*/ fSymbolTable.addSymbol( attr.getLocalName()); 912 913 // --------------------------------------- 914 // skip namespace declarations 915 // --------------------------------------- 916 // REVISIT: can we assume that "uri" is from some symbol 917 // table, and compare by reference? -SG 918 if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) { 919 continue; 920 } 921 //--------------------------------------- 922 // check if value of the attribute is namespace well-formed 923 //--------------------------------------- 924 if (fDocument.errorChecking && ((fConfiguration.features & DOMConfigurationImpl.WELLFORMED) != 0)) { 925 isAttrValueWF(fErrorHandler, fError, fLocator, attributes, (AttrImpl)attr, attr.getValue(), fDocument.isXML11Version()); 926 if (fDocument.isXMLVersionChanged()){ 927 boolean wellformed=CoreDocumentImpl.isXMLName(attr.getNodeName() , fDocument.isXML11Version()); 928 if (!wellformed){ 929 String msg = DOMMessageFormatter.formatMessage( 930 DOMMessageFormatter.DOM_DOMAIN, 931 "wf-invalid-character-in-node-name", 932 new Object[]{"Attribute", attr.getNodeName()}); 933 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 934 "wf-invalid-character-in-node-name"); 935 } 936 } 937 } 938 939 // --------------------------------------- 940 // remove default attributes 941 // --------------------------------------- 942 /* 943 if (removeDefault(attr, attributes)) { 944 continue; 945 } 946 */ 947 // XML 1.0 Attribute value normalization 948 //value = normalizeAttributeValue(value, attr); 949 950 // reset id-attributes 951 ((AttrImpl)attr).setIdAttribute(false); 952 953 954 uri = fSymbolTable.addSymbol(uri); 955 956 // find if for this prefix a URI was already declared 957 String declaredURI = fNamespaceContext.getURI(prefix); 958 959 if (prefix == XMLSymbols.EMPTY_STRING || declaredURI != uri) { 960 // attribute has no prefix (default namespace decl does not apply to attributes) 961 // OR 962 // attribute prefix is not declared 963 // OR 964 // conflict: attribute has a prefix that conficlicts with a binding 965 // already active in scope 966 967 name = attr.getNodeName(); 968 // Find if any prefix for attributes namespace URI is available 969 // in the scope 970 String declaredPrefix = fNamespaceContext.getPrefix(uri); 971 if (declaredPrefix !=null && declaredPrefix !=XMLSymbols.EMPTY_STRING) { 972 973 // use the prefix that was found (declared previously for this URI 974 prefix = declaredPrefix; 975 } else { 976 if (prefix != XMLSymbols.EMPTY_STRING && fLocalNSBinder.getURI(prefix) == null) { 977 // the current prefix is not null and it has no in scope declaration 978 979 // use this prefix 980 } else { 981 982 // find a prefix following the pattern "NS" +index (starting at 1) 983 // make sure this prefix is not declared in the current scope. 984 int counter = 1; 985 prefix = fSymbolTable.addSymbol(PREFIX +counter++); 986 while (fLocalNSBinder.getURI(prefix)!=null) { 987 prefix = fSymbolTable.addSymbol(PREFIX +counter++); 988 } 989 990 } 991 // add declaration for the new prefix 992 addNamespaceDecl(prefix, uri, element); 993 value = fSymbolTable.addSymbol(value); 994 fLocalNSBinder.declarePrefix(prefix, value); 995 fNamespaceContext.declarePrefix(prefix, uri); 996 } 997 998 // change prefix for this attribute 999 attr.setPrefix(prefix); 1000 } 1001 } else { // attribute uri == null 1002 1003 // XML 1.0 Attribute value normalization 1004 //value = normalizeAttributeValue(value, attr); 1005 1006 // reset id-attributes 1007 ((AttrImpl)attr).setIdAttribute(false); 1008 1009 if (attr.getLocalName() == null) { 1010 // It is an error if document has DOM L1 nodes. 1011 if (fNamespaceValidation) { 1012 String msg = DOMMessageFormatter.formatMessage( 1013 DOMMessageFormatter.DOM_DOMAIN, 1014 "NullLocalAttrName", new Object[]{attr.getNodeName()}); 1015 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_FATAL_ERROR, 1016 "NullLocalAttrName"); 1017 } else { 1018 String msg = DOMMessageFormatter.formatMessage( 1019 DOMMessageFormatter.DOM_DOMAIN, 1020 "NullLocalAttrName", new Object[]{attr.getNodeName()}); 1021 reportDOMError(fErrorHandler, fError, fLocator, msg, DOMError.SEVERITY_ERROR, 1022 "NullLocalAttrName"); 1023 } 1024 } else { 1025 // uri=null and no colon 1026 // no fix up is needed: default namespace decl does not 1027 1028 // --------------------------------------- 1029 // remove default attributes 1030 // --------------------------------------- 1031 // removeDefault(attr, attributes); 1032 } 1033 } 1034 } 1035 } // end loop for attributes 1036 } 1037 1038 /** 1039 * Adds a namespace attribute or replaces the value of existing namespace 1040 * attribute with the given prefix and value for URI. 1041 * In case prefix is empty will add/update default namespace declaration. 1042 * 1043 * @param prefix 1044 * @param uri 1045 * @exception IOException 1046 */ 1047 1048 protected final void addNamespaceDecl(String prefix, String uri, ElementImpl element){ 1049 if (DEBUG) { 1050 System.out.println("[ns-fixup] addNamespaceDecl ["+prefix+"]"); 1051 } 1052 if (prefix == XMLSymbols.EMPTY_STRING) { 1053 if (DEBUG) { 1054 System.out.println("=>add xmlns=\""+uri+"\" declaration"); 1055 } 1056 element.setAttributeNS(NamespaceContext.XMLNS_URI, XMLSymbols.PREFIX_XMLNS, uri); 1057 } else { 1058 if (DEBUG) { 1059 System.out.println("=>add xmlns:"+prefix+"=\""+uri+"\" declaration"); 1060 } 1061 element.setAttributeNS(NamespaceContext.XMLNS_URI, "xmlns:"+prefix, uri); 1062 } 1063 } 1064 1065 1066 // 1067 // Methods for well-formness checking 1068 // 1069 1070 1071 /** 1072 * Check if CDATA section is well-formed 1073 * @param datavalue 1074 * @param isXML11Version = true if XML 1.1 1075 */ 1076 public static final void isCDataWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, 1077 String datavalue, boolean isXML11Version) 1078 { 1079 if (datavalue == null || (datavalue.length() == 0) ) { 1080 return; 1081 } 1082 1083 char [] dataarray = datavalue.toCharArray(); 1084 int datalength = dataarray.length; 1085 1086 // version of the document is XML 1.1 1087 if (isXML11Version) { 1088 // we need to check all chracters as per production rules of XML11 1089 int i = 0; 1090 while(i < datalength){ 1091 char c = dataarray[i++]; 1092 if ( XML11Char.isXML11Invalid(c) ) { 1093 // check if this is a supplemental character 1094 if (XMLChar.isHighSurrogate(c) && i < datalength) { 1095 char c2 = dataarray[i++]; 1096 if (XMLChar.isLowSurrogate(c2) && 1097 XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) { 1098 continue; 1099 } 1100 } 1101 String msg = DOMMessageFormatter.formatMessage( 1102 DOMMessageFormatter.XML_DOMAIN, 1103 "InvalidCharInCDSect", 1104 new Object[] { Integer.toString(c, 16)}); 1105 reportDOMError( 1106 errorHandler, 1107 error, 1108 locator, 1109 msg, 1110 DOMError.SEVERITY_ERROR, 1111 "wf-invalid-character"); 1112 } 1113 else if (c == ']') { 1114 int count = i; 1115 if (count < datalength && dataarray[count] == ']') { 1116 while (++count < datalength && dataarray[count] == ']') { 1117 // do nothing 1118 } 1119 if (count < datalength && dataarray[count] == '>') { 1120 // CDEndInContent 1121 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, "CDEndInContent", null); 1122 reportDOMError(errorHandler, error, locator,msg, DOMError.SEVERITY_ERROR, "wf-invalid-character"); 1123 } 1124 } 1125 1126 } 1127 } 1128 } // version of the document is XML 1.0 1129 else { 1130 // we need to check all chracters as per production rules of XML 1.0 1131 int i = 0; 1132 while (i < datalength) { 1133 char c = dataarray[i++]; 1134 if( XMLChar.isInvalid(c) ) { 1135 // check if this is a supplemental character 1136 if (XMLChar.isHighSurrogate(c) && i < datalength) { 1137 char c2 = dataarray[i++]; 1138 if (XMLChar.isLowSurrogate(c2) && 1139 XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) { 1140 continue; 1141 } 1142 } 1143 // Note: The key InvalidCharInCDSect from XMLMessages.properties 1144 // is being used to obtain the message and DOM error type 1145 // "wf-invalid-character" is used. Also per DOM it is error but 1146 // as per XML spec. it is fatal error 1147 String msg = DOMMessageFormatter.formatMessage( 1148 DOMMessageFormatter.XML_DOMAIN, 1149 "InvalidCharInCDSect", 1150 new Object[]{Integer.toString(c, 16)}); 1151 reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character"); 1152 } 1153 else if (c==']') { 1154 int count = i; 1155 if ( count< datalength && dataarray[count]==']' ) { 1156 while (++count < datalength && dataarray[count]==']' ) { 1157 // do nothing 1158 } 1159 if ( count < datalength && dataarray[count]=='>' ) { 1160 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, "CDEndInContent", null); 1161 reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character"); 1162 } 1163 } 1164 1165 } 1166 } 1167 } // end-else fDocument.isXMLVersion() 1168 1169 } // isCDataWF 1170 1171 /** 1172 * NON-DOM: check for valid XML characters as per the XML version 1173 * @param datavalue 1174 * @param isXML11Version = true if XML 1.1 1175 */ 1176 public static final void isXMLCharWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, 1177 String datavalue, boolean isXML11Version) 1178 { 1179 if ( datavalue == null || (datavalue.length() == 0) ) { 1180 return; 1181 } 1182 1183 char [] dataarray = datavalue.toCharArray(); 1184 int datalength = dataarray.length; 1185 1186 // version of the document is XML 1.1 1187 if(isXML11Version){ 1188 //we need to check all characters as per production rules of XML11 1189 int i = 0 ; 1190 while (i < datalength) { 1191 if(XML11Char.isXML11Invalid(dataarray[i++])){ 1192 // check if this is a supplemental character 1193 char ch = dataarray[i-1]; 1194 if (XMLChar.isHighSurrogate(ch) && i < datalength) { 1195 char ch2 = dataarray[i++]; 1196 if (XMLChar.isLowSurrogate(ch2) && 1197 XMLChar.isSupplemental(XMLChar.supplemental(ch, ch2))) { 1198 continue; 1199 } 1200 } 1201 String msg = DOMMessageFormatter.formatMessage( 1202 DOMMessageFormatter.DOM_DOMAIN, "InvalidXMLCharInDOM", 1203 new Object[]{Integer.toString(dataarray[i-1], 16)}); 1204 reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, 1205 "wf-invalid-character"); 1206 } 1207 } 1208 } // version of the document is XML 1.0 1209 else{ 1210 // we need to check all characters as per production rules of XML 1.0 1211 int i = 0 ; 1212 while (i < datalength) { 1213 if( XMLChar.isInvalid(dataarray[i++]) ) { 1214 // check if this is a supplemental character 1215 char ch = dataarray[i-1]; 1216 if (XMLChar.isHighSurrogate(ch) && i < datalength) { 1217 char ch2 = dataarray[i++]; 1218 if (XMLChar.isLowSurrogate(ch2) && 1219 XMLChar.isSupplemental(XMLChar.supplemental(ch, ch2))) { 1220 continue; 1221 } 1222 } 1223 String msg = DOMMessageFormatter.formatMessage( 1224 DOMMessageFormatter.DOM_DOMAIN, "InvalidXMLCharInDOM", 1225 new Object[]{Integer.toString(dataarray[i-1], 16)}); 1226 reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, 1227 "wf-invalid-character"); 1228 } 1229 } 1230 } // end-else fDocument.isXMLVersion() 1231 1232 } // isXMLCharWF 1233 1234 /** 1235 * NON-DOM: check if value of the comment is well-formed 1236 * @param datavalue 1237 * @param isXML11Version = true if XML 1.1 1238 */ 1239 public static final void isCommentWF(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, 1240 String datavalue, boolean isXML11Version) 1241 { 1242 if ( datavalue == null || (datavalue.length() == 0) ) { 1243 return; 1244 } 1245 1246 char [] dataarray = datavalue.toCharArray(); 1247 int datalength = dataarray.length ; 1248 1249 // version of the document is XML 1.1 1250 if (isXML11Version) { 1251 // we need to check all chracters as per production rules of XML11 1252 int i = 0 ; 1253 while (i < datalength){ 1254 char c = dataarray[i++]; 1255 if ( XML11Char.isXML11Invalid(c) ) { 1256 // check if this is a supplemental character 1257 if (XMLChar.isHighSurrogate(c) && i < datalength) { 1258 char c2 = dataarray[i++]; 1259 if (XMLChar.isLowSurrogate(c2) && 1260 XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) { 1261 continue; 1262 } 1263 } 1264 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, 1265 "InvalidCharInComment", 1266 new Object [] {Integer.toString(dataarray[i-1], 16)}); 1267 reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character"); 1268 } 1269 else if (c == '-' && i < datalength && dataarray[i] == '-') { 1270 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, 1271 "DashDashInComment", null); 1272 // invalid: '--' in comment 1273 reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character"); 1274 } 1275 } 1276 } // version of the document is XML 1.0 1277 else { 1278 // we need to check all chracters as per production rules of XML 1.0 1279 int i = 0; 1280 while (i < datalength){ 1281 char c = dataarray[i++]; 1282 if( XMLChar.isInvalid(c) ){ 1283 // check if this is a supplemental character 1284 if (XMLChar.isHighSurrogate(c) && i < datalength) { 1285 char c2 = dataarray[i++]; 1286 if (XMLChar.isLowSurrogate(c2) && 1287 XMLChar.isSupplemental(XMLChar.supplemental(c, c2))) { 1288 continue; 1289 } 1290 } 1291 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, 1292 "InvalidCharInComment", new Object [] {Integer.toString(dataarray[i-1], 16)}); 1293 reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character"); 1294 } 1295 else if (c == '-' && i<datalength && dataarray[i]=='-'){ 1296 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.XML_DOMAIN, 1297 "DashDashInComment", null); 1298 // invalid: '--' in comment 1299 reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, "wf-invalid-character"); 1300 } 1301 } 1302 1303 } // end-else fDocument.isXMLVersion() 1304 1305 } // isCommentWF 1306 1307 /** NON-DOM: check if attribute value is well-formed 1308 * @param attributes 1309 * @param a 1310 * @param value 1311 */ 1312 public static final void isAttrValueWF(DOMErrorHandler errorHandler, DOMErrorImpl error, 1313 DOMLocatorImpl locator, NamedNodeMap attributes, Attr a, String value, boolean xml11Version) { 1314 if (a instanceof AttrImpl && ((AttrImpl)a).hasStringValue()) { 1315 isXMLCharWF(errorHandler, error, locator, value, xml11Version); 1316 } else { 1317 NodeList children = a.getChildNodes(); 1318 //check each child node of the attribute's value 1319 for (int j = 0; j < children.getLength(); j++) { 1320 Node child = children.item(j); 1321 //If the attribute's child is an entity refernce 1322 if (child.getNodeType() == Node.ENTITY_REFERENCE_NODE) { 1323 Document owner = a.getOwnerDocument(); 1324 Entity ent = null; 1325 //search for the entity in the docType 1326 //of the attribute's ownerDocument 1327 if (owner != null) { 1328 DocumentType docType = owner.getDoctype(); 1329 if (docType != null) { 1330 NamedNodeMap entities = docType.getEntities(); 1331 ent = (Entity) entities.getNamedItemNS( 1332 "*", 1333 child.getNodeName()); 1334 } 1335 } 1336 //If the entity was not found issue a fatal error 1337 if (ent == null) { 1338 String msg = DOMMessageFormatter.formatMessage( 1339 DOMMessageFormatter.DOM_DOMAIN, "UndeclaredEntRefInAttrValue", 1340 new Object[]{a.getNodeName()}); 1341 reportDOMError(errorHandler, error, locator, msg, DOMError.SEVERITY_ERROR, 1342 "UndeclaredEntRefInAttrValue"); 1343 } 1344 } 1345 else { 1346 // Text node 1347 isXMLCharWF(errorHandler, error, locator, child.getNodeValue(), xml11Version); 1348 } 1349 } 1350 } 1351 } 1352 1353 1354 1355 /** 1356 * Reports a DOM error to the user handler. 1357 * 1358 * If the error is fatal, the processing will be always aborted. 1359 */ 1360 public static final void reportDOMError(DOMErrorHandler errorHandler, DOMErrorImpl error, DOMLocatorImpl locator, 1361 String message, short severity, String type ) { 1362 if( errorHandler!=null ) { 1363 error.reset(); 1364 error.fMessage = message; 1365 error.fSeverity = severity; 1366 error.fLocator = locator; 1367 error.fType = type; 1368 error.fRelatedData = locator.fRelatedNode; 1369 1370 if(!errorHandler.handleError(error)) 1371 throw new AbortException(); 1372 } 1373 if( severity==DOMError.SEVERITY_FATAL_ERROR ) 1374 throw new AbortException(); 1375 } 1376 1377 protected final void updateQName (Node node, QName qname){ 1378 1379 String prefix = node.getPrefix(); 1380 String namespace = node.getNamespaceURI(); 1381 String localName = node.getLocalName(); 1382 // REVISIT: the symbols are added too often: start/endElement 1383 // and in the namespaceFixup. Should reduce number of calls to symbol table. 1384 qname.prefix = (prefix!=null && prefix.length()!=0)?fSymbolTable.addSymbol(prefix):null; 1385 qname.localpart = (localName != null)?fSymbolTable.addSymbol(localName):null; 1386 qname.rawname = fSymbolTable.addSymbol(node.getNodeName()); 1387 qname.uri = (namespace != null)?fSymbolTable.addSymbol(namespace):null; 1388 } 1389 1390 1391 1392 /* REVISIT: remove this method if DOM does not change spec. 1393 * Performs partial XML 1.0 attribute value normalization and replaces 1394 * attribute value if the value is changed after the normalization. 1395 * DOM defines that normalizeDocument acts as if the document was going 1396 * through a save and load cycle, given that serializer will not escape 1397 * any '\n' or '\r' characters on load those will be normalized. 1398 * Thus during normalize document we need to do the following: 1399 * - perform "2.11 End-of-Line Handling" 1400 * - replace #xD, #xA, #x9 with #x20 (white space). 1401 * Note: This alg. won't attempt to resolve entity references or character entity 1402 * references, since '&' will be escaped during serialization and during loading 1403 * this won't be recognized as entity reference, i.e. attribute value "&foo;" will 1404 * be serialized as "&foo;" and thus after loading will be "&foo;" again. 1405 * @param value current attribute value 1406 * @param attr current attribute 1407 * @return String the value (could be original if normalization did not change 1408 * the string) 1409 */ 1410 final String normalizeAttributeValue(String value, Attr attr) { 1411 if (!attr.getSpecified()){ 1412 // specified attributes should already have a normalized form 1413 // since those were added by validator 1414 return value; 1415 } 1416 int end = value.length(); 1417 // ensure capacity 1418 if (fNormalizedValue.ch.length < end) { 1419 fNormalizedValue.ch = new char[end]; 1420 } 1421 fNormalizedValue.length = 0; 1422 boolean normalized = false; 1423 for (int i = 0; i < end; i++) { 1424 char c = value.charAt(i); 1425 if (c==0x0009 || c==0x000A) { 1426 fNormalizedValue.ch[fNormalizedValue.length++] = ' '; 1427 normalized = true; 1428 } 1429 else if(c==0x000D){ 1430 normalized = true; 1431 fNormalizedValue.ch[fNormalizedValue.length++] = ' '; 1432 int next = i+1; 1433 if (next < end && value.charAt(next)==0x000A) i=next; // skip following xA 1434 } 1435 else { 1436 fNormalizedValue.ch[fNormalizedValue.length++] = c; 1437 } 1438 } 1439 if (normalized){ 1440 value = fNormalizedValue.toString(); 1441 attr.setValue(value); 1442 } 1443 return value; 1444 } 1445 1446 protected final class XMLAttributesProxy 1447 implements XMLAttributes { 1448 protected AttributeMap fAttributes; 1449 protected CoreDocumentImpl fDocument; 1450 protected ElementImpl fElement; 1451 1452 protected final Vector fAugmentations = new Vector(5); 1453 1454 1455 public void setAttributes(AttributeMap attributes, CoreDocumentImpl doc, ElementImpl elem) { 1456 fDocument = doc; 1457 fAttributes = attributes; 1458 fElement = elem; 1459 if (attributes != null) { 1460 int length = attributes.getLength(); 1461 1462 fAugmentations.setSize(length); 1463 // REVISIT: this implementation does not store any value in augmentations 1464 // and basically not keeping augs in parallel to attributes map 1465 // untill all attributes are added (default attributes) 1466 for (int i = 0; i < length; i++) { 1467 fAugmentations.setElementAt(new AugmentationsImpl(), i); 1468 } 1469 } else { 1470 fAugmentations.setSize(0); 1471 } 1472 } 1473 1474 1475 /** 1476 * This method adds default declarations 1477 * @see com.sun.org.apache.xerces.internal.xni.XMLAttributes#addAttribute(QName, String, String) 1478 */ 1479 public int addAttribute(QName qname, String attrType, String attrValue) { 1480 int index = fElement.getXercesAttribute(qname.uri, qname.localpart); 1481 // add defaults to the tree 1482 if (index < 0) { 1483 // the default attribute was removed by a user and needed to 1484 // be added back 1485 AttrImpl attr = (AttrImpl) 1486 ((CoreDocumentImpl) fElement.getOwnerDocument()).createAttributeNS( 1487 qname.uri, 1488 qname.rawname, 1489 qname.localpart); 1490 // REVISIT: the following should also update ID table 1491 attr.setNodeValue(attrValue); 1492 index = fElement.setXercesAttributeNode(attr); 1493 fAugmentations.insertElementAt(new AugmentationsImpl(), index); 1494 attr.setSpecified(false); 1495 } 1496 else { 1497 // default attribute is in the tree 1498 // we don't need to do anything since prefix was already fixed 1499 // at the namespace fixup time and value must be same value, otherwise 1500 // attribute will be treated as specified and we will never reach 1501 // this method. 1502 1503 } 1504 return index; 1505 } 1506 1507 1508 public void removeAllAttributes(){ 1509 // REVISIT: implement 1510 } 1511 1512 1513 public void removeAttributeAt(int attrIndex){ 1514 // REVISIT: implement 1515 } 1516 1517 1518 public int getLength(){ 1519 return(fAttributes != null)?fAttributes.getLength():0; 1520 } 1521 1522 1523 public int getIndex(String qName){ 1524 // REVISIT: implement 1525 return -1; 1526 } 1527 1528 public int getIndex(String uri, String localPart){ 1529 // REVISIT: implement 1530 return -1; 1531 } 1532 1533 public void setName(int attrIndex, QName attrName){ 1534 // REVISIT: implement 1535 } 1536 1537 public void getName(int attrIndex, QName attrName){ 1538 if (fAttributes !=null) { 1539 updateQName((Node)fAttributes.getItem(attrIndex), attrName); 1540 } 1541 } 1542 1543 public String getPrefix(int index){ 1544 // REVISIT: implement 1545 return null; 1546 } 1547 1548 1549 public String getURI(int index){ 1550 // REVISIT: implement 1551 return null; 1552 } 1553 1554 1555 public String getLocalName(int index){ 1556 // REVISIT: implement 1557 return null; 1558 } 1559 1560 1561 public String getQName(int index){ 1562 // REVISIT: implement 1563 return null; 1564 } 1565 1566 public QName getQualifiedName(int index){ 1567 //return fAttributes.item(index).ge); 1568 return null; 1569 } 1570 1571 public void setType(int attrIndex, String attrType){ 1572 // REVISIT: implement 1573 } 1574 1575 1576 public String getType(int index){ 1577 return "CDATA"; 1578 } 1579 1580 1581 public String getType(String qName){ 1582 return "CDATA"; 1583 } 1584 1585 1586 public String getType(String uri, String localName){ 1587 return "CDATA"; 1588 } 1589 1590 1591 public void setValue(int attrIndex, String attrValue){ 1592 // REVISIT: is this desired behaviour? 1593 // The values are updated in the case datatype-normalization is turned on 1594 // in this case we need to make sure that specified attributes stay specified 1595 1596 if (fAttributes != null){ 1597 AttrImpl attr = (AttrImpl)fAttributes.getItem(attrIndex); 1598 boolean specified = attr.getSpecified(); 1599 attr.setValue(attrValue); 1600 attr.setSpecified(specified); 1601 1602 } 1603 } 1604 1605 public void setValue(int attrIndex, String attrValue, XMLString value){ 1606 setValue(attrIndex, value.toString()); 1607 } 1608 1609 public String getValue(int index){ 1610 return (fAttributes !=null)?fAttributes.item(index).getNodeValue():""; 1611 1612 } 1613 1614 1615 public String getValue(String qName){ 1616 // REVISIT: implement 1617 return null; 1618 } 1619 1620 1621 public String getValue(String uri, String localName){ 1622 if (fAttributes != null) { 1623 Node node = fAttributes.getNamedItemNS(uri, localName); 1624 return(node != null)? node.getNodeValue():null; 1625 } 1626 return null; 1627 } 1628 1629 1630 public void setNonNormalizedValue(int attrIndex, String attrValue){ 1631 // REVISIT: implement 1632 1633 } 1634 1635 1636 public String getNonNormalizedValue(int attrIndex){ 1637 // REVISIT: implement 1638 return null; 1639 } 1640 1641 1642 public void setSpecified(int attrIndex, boolean specified){ 1643 AttrImpl attr = (AttrImpl)fAttributes.getItem(attrIndex); 1644 attr.setSpecified(specified); 1645 } 1646 1647 public boolean isSpecified(int attrIndex){ 1648 return((Attr)fAttributes.getItem(attrIndex)).getSpecified(); 1649 } 1650 1651 public Augmentations getAugmentations (int attributeIndex){ 1652 return(Augmentations)fAugmentations.elementAt(attributeIndex); 1653 } 1654 1655 public Augmentations getAugmentations (String uri, String localPart){ 1656 // REVISIT: implement 1657 return null; 1658 } 1659 1660 public Augmentations getAugmentations(String qName){ 1661 // REVISIT: implement 1662 return null; 1663 } 1664 1665 /** 1666 * Sets the augmentations of the attribute at the specified index. 1667 * 1668 * @param attrIndex The attribute index. 1669 * @param augs The augmentations. 1670 */ 1671 public void setAugmentations(int attrIndex, Augmentations augs) { 1672 fAugmentations.setElementAt(augs, attrIndex); 1673 } 1674 } 1675 1676 // 1677 // XMLDocumentHandler methods 1678 // 1679 1680 /** 1681 * The start of the document. 1682 * 1683 * @param locator The document locator, or null if the document 1684 * location cannot be reported during the parsing 1685 * of this document. However, it is <em>strongly</em> 1686 * recommended that a locator be supplied that can 1687 * at least report the system identifier of the 1688 * document. 1689 * @param encoding The auto-detected IANA encoding name of the entity 1690 * stream. This value will be null in those situations 1691 * where the entity encoding is not auto-detected (e.g. 1692 * internal entities or a document entity that is 1693 * parsed from a java.io.Reader). 1694 * @param namespaceContext 1695 * The namespace context in effect at the 1696 * start of this document. 1697 * This object represents the current context. 1698 * Implementors of this class are responsible 1699 * for copying the namespace bindings from the 1700 * the current context (and its parent contexts) 1701 * if that information is important. 1702 * 1703 * @param augs Additional information that may include infoset augmentations 1704 * @exception XNIException 1705 * Thrown by handler to signal an error. 1706 */ 1707 public void startDocument(XMLLocator locator, String encoding, 1708 NamespaceContext namespaceContext, 1709 Augmentations augs) 1710 throws XNIException{ 1711 } 1712 1713 /** 1714 * Notifies of the presence of an XMLDecl line in the document. If 1715 * present, this method will be called immediately following the 1716 * startDocument call. 1717 * 1718 * @param version The XML version. 1719 * @param encoding The IANA encoding name of the document, or null if 1720 * not specified. 1721 * @param standalone The standalone value, or null if not specified. 1722 * @param augs Additional information that may include infoset augmentations 1723 * 1724 * @exception XNIException 1725 * Thrown by handler to signal an error. 1726 */ 1727 public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) 1728 throws XNIException{ 1729 } 1730 1731 /** 1732 * Notifies of the presence of the DOCTYPE line in the document. 1733 * 1734 * @param rootElement 1735 * The name of the root element. 1736 * @param publicId The public identifier if an external DTD or null 1737 * if the external DTD is specified using SYSTEM. 1738 * @param systemId The system identifier if an external DTD, null 1739 * otherwise. 1740 * @param augs Additional information that may include infoset augmentations 1741 * 1742 * @exception XNIException 1743 * Thrown by handler to signal an error. 1744 */ 1745 public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) 1746 throws XNIException{ 1747 } 1748 1749 /** 1750 * A comment. 1751 * 1752 * @param text The text in the comment. 1753 * @param augs Additional information that may include infoset augmentations 1754 * 1755 * @exception XNIException 1756 * Thrown by application to signal an error. 1757 */ 1758 public void comment(XMLString text, Augmentations augs) throws XNIException{ 1759 } 1760 1761 /** 1762 * A processing instruction. Processing instructions consist of a 1763 * target name and, optionally, text data. The data is only meaningful 1764 * to the application. 1765 * <p> 1766 * Typically, a processing instruction's data will contain a series 1767 * of pseudo-attributes. These pseudo-attributes follow the form of 1768 * element attributes but are <strong>not</strong> parsed or presented 1769 * to the application as anything other than text. The application is 1770 * responsible for parsing the data. 1771 * 1772 * @param target The target. 1773 * @param data The data or null if none specified. 1774 * @param augs Additional information that may include infoset augmentations 1775 * 1776 * @exception XNIException 1777 * Thrown by handler to signal an error. 1778 */ 1779 public void processingInstruction(String target, XMLString data, Augmentations augs) 1780 throws XNIException{ 1781 } 1782 1783 /** 1784 * The start of an element. 1785 * 1786 * @param element The name of the element. 1787 * @param attributes The element attributes. 1788 * @param augs Additional information that may include infoset augmentations 1789 * 1790 * @exception XNIException 1791 * Thrown by handler to signal an error. 1792 */ 1793 public void startElement(QName element, XMLAttributes attributes, Augmentations augs) 1794 throws XNIException { 1795 Element currentElement = (Element) fCurrentNode; 1796 int attrCount = attributes.getLength(); 1797 if (DEBUG_EVENTS) { 1798 System.out.println("==>startElement: " +element+ 1799 " attrs.length="+attrCount); 1800 } 1801 1802 for (int i = 0; i < attrCount; i++) { 1803 attributes.getName(i, fAttrQName); 1804 Attr attr = null; 1805 1806 attr = currentElement.getAttributeNodeNS(fAttrQName.uri, fAttrQName.localpart); 1807 AttributePSVI attrPSVI = 1808 (AttributePSVI) attributes.getAugmentations(i).getItem(Constants.ATTRIBUTE_PSVI); 1809 1810 if (attrPSVI != null) { 1811 //REVISIT: instead we should be using augmentations: 1812 // to set/retrieve Id attributes 1813 XSTypeDefinition decl = attrPSVI.getMemberTypeDefinition(); 1814 boolean id = false; 1815 if (decl != null){ 1816 id = ((XSSimpleType)decl).isIDType(); 1817 } else{ 1818 decl = attrPSVI.getTypeDefinition(); 1819 if (decl !=null){ 1820 id = ((XSSimpleType)decl).isIDType(); 1821 } 1822 } 1823 if (id){ 1824 ((ElementImpl)currentElement).setIdAttributeNode(attr, true); 1825 } 1826 1827 if (fPSVI) { 1828 ((PSVIAttrNSImpl) attr).setPSVI(attrPSVI); 1829 } 1830 if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) { 1831 // datatype-normalization 1832 // NOTE: The specified value MUST be set after we set 1833 // the node value because that turns the "specified" 1834 // flag to "true" which may overwrite a "false" 1835 // value from the attribute list. 1836 boolean specified = attr.getSpecified(); 1837 attr.setValue(attrPSVI.getSchemaNormalizedValue()); 1838 if (!specified) { 1839 ((AttrImpl) attr).setSpecified(specified); 1840 } 1841 } 1842 } 1843 } 1844 } 1845 1846 1847 /** 1848 * An empty element. 1849 * 1850 * @param element The name of the element. 1851 * @param attributes The element attributes. 1852 * @param augs Additional information that may include infoset augmentations 1853 * 1854 * @exception XNIException 1855 * Thrown by handler to signal an error. 1856 */ 1857 public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) 1858 throws XNIException { 1859 if (DEBUG_EVENTS) { 1860 System.out.println("==>emptyElement: " +element); 1861 } 1862 1863 startElement(element, attributes, augs); 1864 endElement(element, augs); 1865 } 1866 1867 /** 1868 * This method notifies the start of a general entity. 1869 * <p> 1870 * <strong>Note:</strong> This method is not called for entity references 1871 * appearing as part of attribute values. 1872 * 1873 * @param name The name of the general entity. 1874 * @param identifier The resource identifier. 1875 * @param encoding The auto-detected IANA encoding name of the entity 1876 * stream. This value will be null in those situations 1877 * where the entity encoding is not auto-detected (e.g. 1878 * internal entities or a document entity that is 1879 * parsed from a java.io.Reader). 1880 * @param augs Additional information that may include infoset augmentations 1881 * 1882 * @exception XNIException Thrown by handler to signal an error. 1883 */ 1884 public void startGeneralEntity(String name, 1885 XMLResourceIdentifier identifier, 1886 String encoding, 1887 Augmentations augs) throws XNIException{ 1888 } 1889 1890 /** 1891 * Notifies of the presence of a TextDecl line in an entity. If present, 1892 * this method will be called immediately following the startEntity call. 1893 * <p> 1894 * <strong>Note:</strong> This method will never be called for the 1895 * document entity; it is only called for external general entities 1896 * referenced in document content. 1897 * <p> 1898 * <strong>Note:</strong> This method is not called for entity references 1899 * appearing as part of attribute values. 1900 * 1901 * @param version The XML version, or null if not specified. 1902 * @param encoding The IANA encoding name of the entity. 1903 * @param augs Additional information that may include infoset augmentations 1904 * 1905 * @exception XNIException 1906 * Thrown by handler to signal an error. 1907 */ 1908 public void textDecl(String version, String encoding, Augmentations augs) throws XNIException{ 1909 } 1910 1911 /** 1912 * This method notifies the end of a general entity. 1913 * <p> 1914 * <strong>Note:</strong> This method is not called for entity references 1915 * appearing as part of attribute values. 1916 * 1917 * @param name The name of the entity. 1918 * @param augs Additional information that may include infoset augmentations 1919 * 1920 * @exception XNIException 1921 * Thrown by handler to signal an error. 1922 */ 1923 public void endGeneralEntity(String name, Augmentations augs) throws XNIException{ 1924 } 1925 1926 /** 1927 * Character content. 1928 * 1929 * @param text The content. 1930 * @param augs Additional information that may include infoset augmentations 1931 * 1932 * @exception XNIException 1933 * Thrown by handler to signal an error. 1934 */ 1935 public void characters(XMLString text, Augmentations augs) throws XNIException{ 1936 } 1937 1938 /** 1939 * Ignorable whitespace. For this method to be called, the document 1940 * source must have some way of determining that the text containing 1941 * only whitespace characters should be considered ignorable. For 1942 * example, the validator can determine if a length of whitespace 1943 * characters in the document are ignorable based on the element 1944 * content model. 1945 * 1946 * @param text The ignorable whitespace. 1947 * @param augs Additional information that may include infoset augmentations 1948 * 1949 * @exception XNIException 1950 * Thrown by handler to signal an error. 1951 */ 1952 public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException{ 1953 allWhitespace = true; 1954 } 1955 1956 /** 1957 * The end of an element. 1958 * 1959 * @param element The name of the element. 1960 * @param augs Additional information that may include infoset augmentations 1961 * 1962 * @exception XNIException 1963 * Thrown by handler to signal an error. 1964 */ 1965 public void endElement(QName element, Augmentations augs) throws XNIException { 1966 if (DEBUG_EVENTS) { 1967 System.out.println("==>endElement: " + element); 1968 } 1969 1970 if(augs != null) { 1971 ElementPSVI elementPSVI = (ElementPSVI) augs.getItem(Constants.ELEMENT_PSVI); 1972 if (elementPSVI != null) { 1973 ElementImpl elementNode = (ElementImpl) fCurrentNode; 1974 if (fPSVI) { 1975 ((PSVIElementNSImpl) fCurrentNode).setPSVI(elementPSVI); 1976 } 1977 // include element default content (if one is available) 1978 String normalizedValue = elementPSVI.getSchemaNormalizedValue(); 1979 if ((fConfiguration.features & DOMConfigurationImpl.DTNORMALIZATION) != 0) { 1980 if (normalizedValue !=null) 1981 elementNode.setTextContent(normalizedValue); 1982 } 1983 else { 1984 // NOTE: this is a hack: it is possible that DOM had an empty element 1985 // and validator sent default value using characters(), which we don't 1986 // implement. Thus, here we attempt to add the default value. 1987 String text = elementNode.getTextContent(); 1988 if (text.length() == 0) { 1989 // default content could be provided 1990 if (normalizedValue !=null) 1991 elementNode.setTextContent(normalizedValue); 1992 } 1993 } 1994 } 1995 } 1996 } 1997 1998 1999 /** 2000 * The start of a CDATA section. 2001 * 2002 * @param augs Additional information that may include infoset augmentations 2003 * 2004 * @exception XNIException 2005 * Thrown by handler to signal an error. 2006 */ 2007 public void startCDATA(Augmentations augs) throws XNIException{ 2008 } 2009 2010 /** 2011 * The end of a CDATA section. 2012 * 2013 * @param augs Additional information that may include infoset augmentations 2014 * 2015 * @exception XNIException 2016 * Thrown by handler to signal an error. 2017 */ 2018 public void endCDATA(Augmentations augs) throws XNIException{ 2019 } 2020 2021 /** 2022 * The end of the document. 2023 * 2024 * @param augs Additional information that may include infoset augmentations 2025 * 2026 * @exception XNIException 2027 * Thrown by handler to signal an error. 2028 */ 2029 public void endDocument(Augmentations augs) throws XNIException{ 2030 } 2031 2032 2033 /** Sets the document source. */ 2034 public void setDocumentSource(XMLDocumentSource source){ 2035 } 2036 2037 2038 /** Returns the document source. */ 2039 public XMLDocumentSource getDocumentSource(){ 2040 return null; 2041 } 2042 2043 } // DOMNormalizer class