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