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