Newer
Older
* Copyright (c) 2002,2003 The Apache Software Foundation. All rights
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 2001, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/**
* This file contains code to build the DOM tree. It registers a document
* handler with the scanner. In these handler methods, appropriate DOM nodes
* are created and added to the DOM tree.
*
* $Id$
*
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/parsers/AbstractDOMParser.hpp>
#include <xercesc/internal/XMLScannerResolver.hpp>
#include <xercesc/internal/ElemStack.hpp>
#include <xercesc/sax/EntityResolver.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/framework/XMLNotationDecl.hpp>
#include <xercesc/util/IOException.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/impl/DOMAttrImpl.hpp>
#include <xercesc/dom/DOMCDATASection.hpp>
#include <xercesc/dom/DOMComment.hpp>
#include <xercesc/dom/impl/DOMTextImpl.hpp>
#include <xercesc/dom/impl/DOMDocumentImpl.hpp>
#include <xercesc/dom/impl/DOMDocumentTypeImpl.hpp>
#include <xercesc/dom/DOMDocumentType.hpp>
#include <xercesc/dom/impl/DOMElementImpl.hpp>
#include <xercesc/dom/impl/DOMEntityImpl.hpp>
#include <xercesc/dom/impl/DOMEntityReferenceImpl.hpp>
#include <xercesc/dom/impl/DOMNotationImpl.hpp>
#include <xercesc/dom/DOMNamedNodeMap.hpp>
#include <xercesc/dom/DOMProcessingInstruction.hpp>
#include <xercesc/dom/impl/DOMProcessingInstructionImpl.hpp>
#include <xercesc/dom/impl/DOMNodeIDMap.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/common/GrammarResolver.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
// ---------------------------------------------------------------------------
// AbstractDOMParser: Constructors and Destructor
// ---------------------------------------------------------------------------
AbstractDOMParser::AbstractDOMParser( XMLValidator* const valToAdopt
, MemoryManager* const manager) :
fCreateEntityReferenceNodes(true)
, fIncludeIgnorableWhitespace(true)
, fWithinElement(false)
, fParseInProgress(false)
, fCreateCommentNodes(true)
, fDocumentAdoptedByUser(false)
, fScanner(0)
, fCurrentParent(0)
, fCurrentNode(0)
, fDocument(0)
, fNodeStack(0)
, fDocumentType(0)
, fDocumentVector(0)
, fGrammarResolver(0)
, fURIStringPool(0)
, fValidator(valToAdopt)
, fMemoryManager(manager)
, fBufMgr(manager)
try
{
initialize();
}
catch(...)
{
cleanUp();
throw;
}
}
AbstractDOMParser::~AbstractDOMParser()
{
cleanUp();
}
// ---------------------------------------------------------------------------
// AbstractDOMParser: Initialize/CleanUp methods
// ---------------------------------------------------------------------------
void AbstractDOMParser::initialize()
{
// Create grammar resolver and string pool to pass to the scanner
fGrammarResolver = new (fMemoryManager) GrammarResolver(fMemoryManager);
fURIStringPool = new (fMemoryManager) XMLStringPool(109, fMemoryManager);
// Create a scanner and tell it what validator to use. Then set us
// as the document event handler so we can fill the DOM document.
fScanner = XMLScannerResolver::getDefaultScanner(fValidator, fMemoryManager);
fScanner->setDocHandler(this);
fScanner->setDocTypeHandler(this);
fScanner->setGrammarResolver(fGrammarResolver);
fScanner->setURIStringPool(fURIStringPool);
fNodeStack = new (fMemoryManager) ValueStackOf<DOMNode*>(64, fMemoryManager);
{
if (fDocumentVector)
delete fDocumentVector;
if (!fDocumentAdoptedByUser && fDocument)
fDocument->release();
delete fGrammarResolver;
delete fURIStringPool;
// ---------------------------------------------------------------------------
// AbstractDOMParser: Utilities
// ---------------------------------------------------------------------------
void AbstractDOMParser::reset()
{
// if fDocument exists already, store the old pointer in the vector for deletion later
if (!fDocumentVector) {
// allocate the vector if not exists yet
fDocumentVector = new (fMemoryManager) RefVectorOf<DOMDocumentImpl>(10, true, fMemoryManager) ;
}
fDocumentVector->addElement(fDocument);
}
fDocument = 0;
resetDocType();
fCurrentParent = 0;
fCurrentNode = 0;
fParseInProgress = false;
fWithinElement = false;
void AbstractDOMParser::resetPool()
{
// We cannot enter here while a regular parse is in progress.
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
if (fDocumentVector)
fDocumentVector->removeAllElements();
if (!fDocumentAdoptedByUser)
delete fDocument;
bool AbstractDOMParser::isDocumentAdopted() const
{
return fDocumentAdoptedByUser;
}
DOMDocument* AbstractDOMParser::adoptDocument()
{
fDocumentAdoptedByUser = true;
return fDocument;
}
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
// ---------------------------------------------------------------------------
// AbstractDOMParser: Getter methods
// ---------------------------------------------------------------------------
DOMDocument* AbstractDOMParser::getDocument()
{
return fDocument;
}
const XMLValidator& AbstractDOMParser::getValidator() const
{
return *fScanner->getValidator();
}
bool AbstractDOMParser::getDoNamespaces() const
{
return fScanner->getDoNamespaces();
}
bool AbstractDOMParser::getExitOnFirstFatalError() const
{
return fScanner->getExitOnFirstFatal();
}
bool AbstractDOMParser::getValidationConstraintFatal() const
{
return fScanner->getValidationConstraintFatal();
}
AbstractDOMParser::ValSchemes AbstractDOMParser::getValidationScheme() const
{
const XMLScanner::ValSchemes scheme = fScanner->getValidationScheme();
if (scheme == XMLScanner::Val_Always)
return Val_Always;
else if (scheme == XMLScanner::Val_Never)
return Val_Never;
return Val_Auto;
}
bool AbstractDOMParser::getDoSchema() const
{
return fScanner->getDoSchema();
}
bool AbstractDOMParser::getValidationSchemaFullChecking() const
{
return fScanner->getValidationSchemaFullChecking();
}
int AbstractDOMParser::getErrorCount() const
{
return fScanner->getErrorCount();
}
XMLCh* AbstractDOMParser::getExternalSchemaLocation() const
{
return fScanner->getExternalSchemaLocation();
}
XMLCh* AbstractDOMParser::getExternalNoNamespaceSchemaLocation() const
{
return fScanner->getExternalNoNamespaceSchemaLocation();
}
SecurityManager* AbstractDOMParser::getSecurityManager() const
{
return fScanner->getSecurityManager();
}
bool AbstractDOMParser::getLoadExternalDTD() const
{
return fScanner->getLoadExternalDTD();
}
bool AbstractDOMParser::getCalculateSrcOfs() const
{
return fScanner->getCalculateSrcOfs();
}
bool AbstractDOMParser::getStandardUriConformant() const
{
return fScanner->getStandardUriConformant();
}
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
// ---------------------------------------------------------------------------
// AbstractDOMParser: Setter methods
// ---------------------------------------------------------------------------
void AbstractDOMParser::setDoNamespaces(const bool newState)
{
fScanner->setDoNamespaces(newState);
}
void AbstractDOMParser::setExitOnFirstFatalError(const bool newState)
{
fScanner->setExitOnFirstFatal(newState);
}
void AbstractDOMParser::setValidationConstraintFatal(const bool newState)
{
fScanner->setValidationConstraintFatal(newState);
}
void AbstractDOMParser::setValidationScheme(const ValSchemes newScheme)
{
if (newScheme == Val_Never)
fScanner->setValidationScheme(XMLScanner::Val_Never);
else if (newScheme == Val_Always)
fScanner->setValidationScheme(XMLScanner::Val_Always);
else
fScanner->setValidationScheme(XMLScanner::Val_Auto);
}
void AbstractDOMParser::setDoSchema(const bool newState)
{
fScanner->setDoSchema(newState);
}
void AbstractDOMParser::setValidationSchemaFullChecking(const bool schemaFullChecking)
{
fScanner->setValidationSchemaFullChecking(schemaFullChecking);
}
void AbstractDOMParser::setExternalSchemaLocation(const XMLCh* const schemaLocation)
{
fScanner->setExternalSchemaLocation(schemaLocation);
}
void AbstractDOMParser::setExternalNoNamespaceSchemaLocation(const XMLCh* const noNamespaceSchemaLocation)
{
fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation);
}
void AbstractDOMParser::setExternalSchemaLocation(const char* const schemaLocation)
{
fScanner->setExternalSchemaLocation(schemaLocation);
}
void AbstractDOMParser::setExternalNoNamespaceSchemaLocation(const char* const noNamespaceSchemaLocation)
{
fScanner->setExternalNoNamespaceSchemaLocation(noNamespaceSchemaLocation);
}
void AbstractDOMParser::setSecurityManager(SecurityManager* const securityManager)
{
// since this could impact various components, don't permit it to change
// during a parse
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
fScanner->setSecurityManager(securityManager);
}
void AbstractDOMParser::setLoadExternalDTD(const bool newState)
{
fScanner->setLoadExternalDTD(newState);
}
void AbstractDOMParser::setCalculateSrcOfs(const bool newState)
{
fScanner->setCalculateSrcOfs(newState);
}
void AbstractDOMParser::setStandardUriConformant(const bool newState)
{
fScanner->setStandardUriConformant(newState);
}
void AbstractDOMParser::useScanner(const XMLCh* const scannerName)
{
XMLScanner* tempScanner = XMLScannerResolver::resolveScanner
(
scannerName
, fValidator
, fMemoryManager
);
tempScanner->setParseSettings(fScanner);
tempScanner->setGrammarResolver(fGrammarResolver);
tempScanner->setURIStringPool(fURIStringPool);
delete fScanner;
fScanner = tempScanner;
}
}
// ---------------------------------------------------------------------------
// AbstractDOMParser: Parsing methods
// ---------------------------------------------------------------------------
void AbstractDOMParser::parse(const InputSource& source)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
try
{
fParseInProgress = true;
fScanner->scanDocument(source);
fParseInProgress = false;
}
catch(...)
{
fParseInProgress = false;
throw;
}
}
void AbstractDOMParser::parse(const XMLCh* const systemId)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
try
{
fParseInProgress = true;
fScanner->scanDocument(systemId);
fParseInProgress = false;
}
catch(...)
{
fParseInProgress = false;
throw;
}
}
void AbstractDOMParser::parse(const char* const systemId)
{
// Avoid multiple entrance
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
try
{
fParseInProgress = true;
fScanner->scanDocument(systemId);
fParseInProgress = false;
}
catch(...)
{
fParseInProgress = false;
throw;
}
}
// ---------------------------------------------------------------------------
// AbstractDOMParser: Progressive parse methods
// ---------------------------------------------------------------------------
bool AbstractDOMParser::parseFirst( const XMLCh* const systemId
, XMLPScanToken& toFill)
{
//
// Avoid multiple entrance. We cannot enter here while a regular parse
// is in progress.
//
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
return fScanner->scanFirst(systemId, toFill);
}
bool AbstractDOMParser::parseFirst( const char* const systemId
, XMLPScanToken& toFill)
{
//
// Avoid multiple entrance. We cannot enter here while a regular parse
// is in progress.
//
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
return fScanner->scanFirst(systemId, toFill);
}
bool AbstractDOMParser::parseFirst( const InputSource& source
, XMLPScanToken& toFill)
{
//
// Avoid multiple entrance. We cannot enter here while a regular parse
// is in progress.
//
if (fParseInProgress)
ThrowXML(IOException, XMLExcepts::Gen_ParseInProgress);
return fScanner->scanFirst(source, toFill);
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
}
bool AbstractDOMParser::parseNext(XMLPScanToken& token)
{
return fScanner->scanNext(token);
}
void AbstractDOMParser::parseReset(XMLPScanToken& token)
{
// Reset the scanner, and then reset the parser
fScanner->scanReset(token);
reset();
}
// ---------------------------------------------------------------------------
// AbstractDOMParser: Implementation of XMLDocumentHandler interface
// ---------------------------------------------------------------------------
void AbstractDOMParser::docCharacters( const XMLCh* const chars
, const unsigned int length
, const bool cdataSection)
{
// Ignore chars outside of content
if (!fWithinElement)
return;
// revisit. Is it really safe to null-terminate here?
// Does the scanner do it already?
// If scanner goes up to the very end of an unterminated
// buffer, we may be stepping on something bad here.
// Probably best to modify the scanner to null terminate.
XMLCh savedChar = chars[length];
XMLCh *ncChars = (XMLCh *)chars; // cast off const
ncChars[length] = 0;
if (cdataSection == true)
{
DOMCDATASection *node = fDocument->createCDATASection(chars);
fCurrentParent->appendChild(node);
fCurrentNode = node;
}
else
{
if (fCurrentNode->getNodeType() == DOMNode::TEXT_NODE)
{
DOMText *node = (DOMText *)fCurrentNode;
node->appendData(chars);
}
else
{
DOMText *node = fDocument->createTextNode(chars);
fCurrentParent->appendChild(node);
fCurrentNode = node;
}
}
ncChars[length] = savedChar;
return;
}
void AbstractDOMParser::docComment(const XMLCh* const comment)
{
if (fCreateCommentNodes) {
DOMComment *dcom = fDocument->createComment(comment);
fCurrentParent->appendChild(dcom);
fCurrentNode = dcom;
}
}
void AbstractDOMParser::docPI( const XMLCh* const target
, const XMLCh* const data)
{
DOMProcessingInstruction *pi = fDocument->createProcessingInstruction
(
target
, data
);
fCurrentParent->appendChild(pi);
fCurrentNode = pi;
}
void AbstractDOMParser::endEntityReference(const XMLEntityDecl& entDecl)
{
Tinny Ng
committed
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
DOMEntityReferenceImpl *erImpl = 0;
DOMNode* firstChild = 0;
if (fCurrentParent->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE) {
erImpl = (DOMEntityReferenceImpl *) fCurrentParent;
firstChild = erImpl->getFirstChild();
}
fCurrentParent = fNodeStack->pop();
if (!fCreateEntityReferenceNodes && erImpl && firstChild) {
DOMNode *kid, *next;
fCurrentNode = fCurrentParent->getLastChild();
for (kid = firstChild; kid != 0; kid = next)
{
// If kid and fCurrentNode are both Text nodes (but _not_ CDATASection,
// which is a subclass of Text), they can be merged.
if (kid->getNodeType() == DOMNode::TEXT_NODE &&
fCurrentNode &&
fCurrentNode->getNodeType() == DOMNode::TEXT_NODE )
{
((DOMTextImpl *) fCurrentNode)->appendData(((DOMTextImpl *) kid)->getData());
}
else {
// append the child of erImpl to currentParent
fCurrentNode = kid->cloneNode(true);
fCurrentParent->appendChild(fCurrentNode);
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
if (erImpl->getBaseURI()) {
/**
* Record baseURI information for the Element (by adding xml:base attribute)
* or for the ProcessingInstruction (by setting a baseURI field)
*/
if (fCurrentNode->getNodeType() == DOMNode::ELEMENT_NODE) {
// if an element already has xml:base attribute
// do nothing
const XMLCh baseString[] =
{
chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
};
const XMLCh xmlBaseString[] =
{
chLatin_x, chLatin_m, chLatin_l, chColon, chLatin_b, chLatin_a, chLatin_s, chLatin_e, chNull
};
if (fScanner -> getDoNamespaces() && (((DOMElement*)fCurrentNode)->getAttributeNodeNS(DOMNodeImpl::getXmlURIString(), baseString) != 0)) {
return;
} else if (((DOMElement*)fCurrentNode)->getAttributeNode(xmlBaseString) != 0) {
return;
}
// retrive the baseURI from the entity decl
const XMLCh* baseURI = erImpl->getBaseURI();
if (baseURI != 0 && !XMLString::equals(baseURI,fDocument->getDocumentURI())) {
if (fScanner -> getDoNamespaces()) {
((DOMElement*)fCurrentNode)->setAttributeNS(DOMNodeImpl::getXmlURIString(), baseString, baseURI);
} else {
((DOMElement*)fCurrentNode)->setAttribute(xmlBaseString, baseURI);
}
}
}
else if (fCurrentNode->getNodeType() == DOMNode::PROCESSING_INSTRUCTION_NODE) {
((DOMProcessingInstructionImpl*)fCurrentNode)->setBaseURI(erImpl->getBaseURI());
}
}
Tinny Ng
committed
}
next = kid->getNextSibling();
Tinny Ng
committed
else
fCurrentNode = fCurrentParent;
if (erImpl)
erImpl->setReadOnly(true, true);
}
void AbstractDOMParser::endElement( const XMLElementDecl& elemDecl
, const unsigned int urlId
, const bool isRoot
, const XMLCh* const elemPrefix)
{
fCurrentNode = fCurrentParent;
fCurrentParent = fNodeStack->pop();
//validation is performed after the startElement event so we have to associate the info here
((DOMElementImpl *)(fCurrentNode))->setTypeInfo(elemDecl.getDOMTypeInfoName(), elemDecl.getDOMTypeInfoUri());
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
// If we've hit the end of content, clear the flag
if (fNodeStack->empty())
fWithinElement = false;
}
void AbstractDOMParser::ignorableWhitespace(const XMLCh* const chars
, const unsigned int length
, const bool cdataSection)
{
// Ignore chars before the root element
if (!fWithinElement || !fIncludeIgnorableWhitespace)
return;
// revisit. Not safe to slam in a null like this.
XMLCh savedChar = chars[length];
XMLCh *ncChars = (XMLCh *)chars; // cast off const
ncChars[length] = chNull;
if (fCurrentNode->getNodeType() == DOMNode::TEXT_NODE)
{
DOMText *node = (DOMText *)fCurrentNode;
node->appendData(chars);
}
else
{
DOMTextImpl *node = (DOMTextImpl *)fDocument->createTextNode(chars);
node->setIgnorableWhitespace(true);
fCurrentParent->appendChild(node);
fCurrentNode = node;
}
ncChars[length] = savedChar;
}
void AbstractDOMParser::resetDocument()
{
//
// The reset methods are called before a new parse event occurs.
// Reset this parsers state to clear out anything that may be left
// from a previous use, in particular the DOM document itself.
//
this->reset();
}
void AbstractDOMParser::startDocument()
{
fDocument = (DOMDocumentImpl *)DOMImplementation::getImplementation()->createDocument();
// Just set the document as the current parent and current node
fCurrentParent = fDocument;
fCurrentNode = fDocument;
// set DOM error checking off
fDocument->setErrorChecking(false);
fDocument->setDocumentURI(fScanner->getLocator()->getSystemId());
fDocument->setActualEncoding(fScanner->getReaderMgr()->getCurrentEncodingStr());
}
void AbstractDOMParser::endDocument()
{
// set DOM error checking back on
fDocument->setErrorChecking(true);
// DOM L2 does not support editing DocumentType nodes
if (fDocumentType && fScanner -> getDoNamespaces())
fDocumentType->setReadOnly(true, true);
}
void AbstractDOMParser::startElement(const XMLElementDecl& elemDecl
, const unsigned int urlId
, const XMLCh* const elemPrefix
, const RefVectorOf<XMLAttr>& attrList
, const unsigned int attrCount
, const bool isEmpty
, const bool isRoot)
{
DOMElement *elem;
DOMElementImpl *elemImpl;
static const XMLCh XMLNS[] = {
chLatin_x, chLatin_m, chLatin_l, chLatin_n, chLatin_s, chNull
};
static const XMLCh XSI[] = {
chLatin_x, chLatin_s, chLatin_i, chNull
};
Khaled Noaman
committed
//get the list for use in the loop
XMLAttDefList* defAttrs = 0;
if(elemDecl.hasAttDefs()) {
defAttrs = &elemDecl.getAttDefList();
}
if (fScanner -> getDoNamespaces()) { //DOM Level 2, doNamespaces on
const XMLCh* namespaceURI = 0;
if (urlId != fScanner->getEmptyNamespaceId()) { //TagName has a prefix
namespaceURI = fScanner->getURIText(urlId); //get namespaceURI
if (elemPrefix && *elemPrefix) {
XMLBufBid elemQName(&fBufMgr);
elemQName.set(elemPrefix);
elemQName.append(chColon);
elemQName.append(elemDecl.getBaseName());
elem = createElementNSNode(namespaceURI, elemQName.getRawBuffer());
}
else {
elem = createElementNSNode(namespaceURI, elemDecl.getBaseName());
}
else {
elem = createElementNSNode(namespaceURI, elemDecl.getBaseName());
elemImpl = (DOMElementImpl *) elem;
for (unsigned int index = 0; index < attrCount; ++index) {
const XMLAttr* oneAttrib = attrList.elementAt(index);
unsigned int attrURIId = oneAttrib -> getURIId();
namespaceURI = 0;
if (XMLString::equals(oneAttrib -> getName(), XMLNS)) //for xmlns=...
attrURIId = fScanner->getXMLNSNamespaceId();
if (attrURIId != fScanner->getEmptyNamespaceId()) { //TagName has a prefix
namespaceURI = fScanner->getURIText(attrURIId); //get namespaceURI
}
// revisit. Optimize to init the named node map to the
// right size up front.
DOMAttrImpl *attr = (DOMAttrImpl *)
fDocument->createAttributeNS(namespaceURI, oneAttrib->getQName());
attr->setValue(oneAttrib -> getValue());
DOMNode* remAttr = elemImpl->setAttributeNodeNS(attr);
//DOMAttrImpl *attr = elemImpl->setAttributeNS(namespaceURI, oneAttrib -> getQName(),
// oneAttrib -> getValue());
// Attributes of type ID. If this is one, add it to the hashtable of IDs
// that is constructed for use by GetElementByID().
//
if (oneAttrib->getType()==XMLAttDef::ID)
{
if (fDocument->fNodeIDMap == 0)
fDocument->fNodeIDMap = new (fDocument) DOMNodeIDMap(500, fDocument);
fDocument->fNodeIDMap->add(attr);
attr->fNode.isIdAttr(true);
}
attr->setSpecified(oneAttrib->getSpecified());
XMLAttDef *attDef = 0;
if(defAttrs != 0)
attDef = defAttrs->findAttDef(attrURIId, oneAttrib->getQName());
if(attDef != 0) {
attr->setTypeInfo(attDef->getDOMTypeInfoName(), attDef->getDOMTypeInfoUri());
attDef->reset();
}
else {
const XMLCh *name = oneAttrib->getName();
if (XMLString::equals(oneAttrib->getPrefix(), XSI)) {
if(XMLString::equals(name, SchemaSymbols::fgXSI_TYPE)) {
attr->setTypeInfo(SchemaSymbols::fgDT_QNAME, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
}
else if(XMLString::equals(name, SchemaSymbols::fgATT_NILL)) {
attr->setTypeInfo(SchemaSymbols::fgDT_BOOLEAN, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
}
else if(XMLString::equals(name, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCACTION)) {
attr->setTypeInfo(SchemaSymbols::fgDT_ANYURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
}
}
else {
//for normal ns attrs
attr->setTypeInfo(SchemaSymbols::fgDT_ANYURI, SchemaSymbols::fgURI_SCHEMAFORSCHEMA);
}
}
}
}
else { //DOM Level 1
elem = fDocument->createElement(elemDecl.getFullName());
elemImpl = (DOMElementImpl *) elem;
for (unsigned int index = 0; index < attrCount; ++index) {
const XMLAttr* oneAttrib = attrList.elementAt(index);
//AttrImpl *attr = elemImpl->setAttribute(oneAttrib->getName(), oneAttrib->getValue());
DOMAttrImpl *attr = (DOMAttrImpl *)
fDocument->createAttribute(oneAttrib->getName());
attr->setValue(oneAttrib -> getValue());
DOMNode* rem = elemImpl->setAttributeNode(attr);
if (rem)
rem->release();
attr->setSpecified(oneAttrib->getSpecified());
// Attributes of type ID. If this is one, add it to the hashtable of IDs
// that is constructed for use by GetElementByID().
//
if (oneAttrib->getType()==XMLAttDef::ID)
{
if (fDocument->fNodeIDMap == 0)
fDocument->fNodeIDMap = new (fDocument) DOMNodeIDMap(500, fDocument);
fDocument->fNodeIDMap->add(attr);
attr->fNode.isIdAttr(true);
}
XMLAttDef *attDef = 0;
if(defAttrs != 0)
attDef = defAttrs->findAttDef(oneAttrib -> getURIId(), oneAttrib->getQName());
if(attDef != 0) {
attr->setTypeInfo(attDef->getDOMTypeInfoName(), attDef->getDOMTypeInfoUri());
attDef->reset();
}
// set up the default attributes
{
XMLAttDef* attr = 0;
DOMAttrImpl * insertAttr = 0;
while (defAttrs->hasMoreElements())
{
attr = &defAttrs->nextElement();
const XMLAttDef::DefAttTypes defType = attr->getDefaultType();
if ((defType == XMLAttDef::Default)
|| (defType == XMLAttDef::Fixed))
{
{
// DOM Level 2 wants all namespace declaration attributes
// to be bound to "http://www.w3.org/2000/xmlns/"
// So as long as the XML parser doesn't do it, it needs to
// done here.
const XMLCh* qualifiedName = attr->getFullName();
XMLBufBid bbPrefixQName(&fBufMgr);
XMLBuffer& prefixBuf = bbPrefixQName.getBuffer();
int colonPos = -1;
unsigned int uriId = fScanner->resolveQName(qualifiedName, prefixBuf, ElemStack::Mode_Attribute, colonPos);
const XMLCh* namespaceURI = 0;
if (XMLString::equals(qualifiedName, XMLNS)) //for xmlns=...
uriId = fScanner->getXMLNSNamespaceId();
if (uriId != fScanner->getEmptyNamespaceId()) { //TagName has a prefix
namespaceURI = fScanner->getURIText(uriId);
}
insertAttr = (DOMAttrImpl *) fDocument->createAttributeNS(
namespaceURI, // NameSpaceURI
qualifiedName); // qualified name
DOMAttr* remAttr = elemImpl->setDefaultAttributeNodeNS(insertAttr);
if (remAttr)
remAttr->release();
if (attr->getValue() != 0)
{
insertAttr->setValue(attr->getValue());
insertAttr->setSpecified(false);
}
{
// Namespaces is turned off...
insertAttr = (DOMAttrImpl *) fDocument->createAttribute(attr->getFullName());
DOMNode* remAttr = elemImpl->setDefaultAttributeNode(insertAttr);
if (remAttr)
remAttr->release();
//need to do this before the get as otherwise we overwrite any value in the attr
if (attr->getValue() != 0)
{
insertAttr->setValue(attr->getValue());
insertAttr->setSpecified(false);
}
insertAttr->setTypeInfo(attr->getDOMTypeInfoName(), attr->getDOMTypeInfoUri());
}