void AbstractDOMParser::startElement()

in src/xercesc/parsers/AbstractDOMParser.cpp [975:1205]


void AbstractDOMParser::startElement(const XMLElementDecl&   elemDecl
                             , const unsigned int            urlId
                             , const XMLCh* const            elemPrefix
                             , const RefVectorOf<XMLAttr>&   attrList
                             , const XMLSize_t               attrCount
                             , const bool                    isEmpty
                             , const bool                    isRoot)
{
    DOMElement     *elem;
    DOMElementImpl *elemImpl;
    const XMLCh* namespaceURI = 0;
    bool doNamespaces = fScanner->getDoNamespaces();

    // Create the element name. Here we are going to bypass the
    // DOMDocument::createElement() interface and instantiate the
    // required types directly in order to avoid name checking
    // overhead.
    //
    if (doNamespaces)
    {
        //DOM Level 2, doNamespaces on
        //
        const XMLCh* localName = elemDecl.getBaseName();

        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(localName);

                elem = createElementNS (
                  namespaceURI, elemPrefix, localName, elemQName.getRawBuffer());
            }
            else
              elem = createElementNS (namespaceURI, 0, localName, localName);
        }
        else
          elem = createElementNS (namespaceURI, 0, localName, localName);
    }
    else
    {   //DOM Level 1
        elem = createElement (elemDecl.getFullName());
    }

    elemImpl = (DOMElementImpl *) elem;

    if (attrCount)
    {
      unsigned int xmlnsNSId = fScanner->getXMLNSNamespaceId();
      unsigned int emptyNSId = fScanner->getEmptyNamespaceId();

      DOMAttrMapImpl* map = elemImpl->fAttributes;
      map->reserve (attrCount);

      for (XMLSize_t index = 0; index < attrCount; ++index)
      {
        const XMLAttr* oneAttrib = attrList.elementAt(index);
        DOMAttrImpl *attr = 0;

        if (doNamespaces)
        {
            //DOM Level 2, doNamespaces on
            //
            unsigned int attrURIId = oneAttrib->getURIId();
            const XMLCh* localName = oneAttrib->getName();
            const XMLCh* prefix = oneAttrib->getPrefix();
            namespaceURI = 0;

            if ((prefix==0 || *prefix==0) && XMLString::equals(localName, XMLUni::fgXMLNSString))
            {
                // xmlns=...
                attrURIId = xmlnsNSId;
            }
            if (attrURIId != emptyNSId)
            {
                //TagName has a prefix
                namespaceURI = fScanner->getURIText(attrURIId);
            }

            attr = (DOMAttrImpl*) createAttrNS (namespaceURI,
                                                prefix,
                                                localName,
                                                oneAttrib->getQName());

            map->setNamedItemNSFast(attr);
        }
        else
        {
            attr = (DOMAttrImpl*) createAttr (oneAttrib->getName());
            map->setNamedItemFast(attr);
        }

        attr->setValueFast(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());

        // store DTD validation information
        if(fCreateSchemaInfo)
        {
            switch(oneAttrib->getType())
            {
            case XMLAttDef::CData:          attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedCDATAAttribute); break;
            case XMLAttDef::ID:             attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDAttribute); break;
            case XMLAttDef::IDRef:          attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDREFAttribute); break;
            case XMLAttDef::IDRefs:         attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDREFSAttribute); break;
            case XMLAttDef::Entity:         attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENTITYAttribute); break;
            case XMLAttDef::Entities:       attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENTITIESAttribute); break;
            case XMLAttDef::NmToken:        attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNMTOKENAttribute); break;
            case XMLAttDef::NmTokens:       attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNMTOKENSAttribute); break;
            case XMLAttDef::Notation:       attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNOTATIONAttribute); break;
            case XMLAttDef::Enumeration:    attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENUMERATIONAttribute); break;
            default:                        attr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdNotValidatedAttribute); break;
            }
        }
      }
    }

    //Set up the default attributes if any.
    //
    if (elemDecl.hasAttDefs())
    {
        XMLAttDefList* defAttrs = &elemDecl.getAttDefList();
        XMLAttDef* attr = 0;
        DOMAttrImpl * insertAttr = 0;

        for(XMLSize_t i=0; i<defAttrs->getAttDefCount(); i++)
        {
            attr = &defAttrs->getAttDef(i);

            const XMLAttDef::DefAttTypes defType = attr->getDefaultType();
            if ((defType == XMLAttDef::Default)
            ||  (defType == XMLAttDef::Fixed))
            {

                if (doNamespaces)
                {
                    // 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
                    // be 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, XMLUni::fgXMLNSString))    //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();
                }
                else
                {
                    // 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->setValueFast(attr->getValue());
                    insertAttr->setSpecified(false);
                }

                // store DTD validation information
                if(fCreateSchemaInfo)
                {
                    switch(attr->getType())
                    {
                    case XMLAttDef::CData:          insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedCDATAAttribute); break;
                    case XMLAttDef::ID:             insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDAttribute); break;
                    case XMLAttDef::IDRef:          insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDREFAttribute); break;
                    case XMLAttDef::IDRefs:         insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedIDREFSAttribute); break;
                    case XMLAttDef::Entity:         insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENTITYAttribute); break;
                    case XMLAttDef::Entities:       insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENTITIESAttribute); break;
                    case XMLAttDef::NmToken:        insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNMTOKENAttribute); break;
                    case XMLAttDef::NmTokens:       insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNMTOKENSAttribute); break;
                    case XMLAttDef::Notation:       insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedNOTATIONAttribute); break;
                    case XMLAttDef::Enumeration:    insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdValidatedENUMERATIONAttribute); break;
                    default:                        insertAttr->setSchemaTypeInfo(&DOMTypeInfoImpl::g_DtdNotValidatedAttribute); break;
                    }
                }
            }

            insertAttr = 0;
            attr->reset();
        }
    }

    if (fCurrentParent != fDocument)
      castToParentImpl (fCurrentParent)->appendChildFast (elem);
    else
      fCurrentParent->appendChild (elem);

    fCurrentParent = elem;
    fCurrentNode = elem;
    fWithinElement = true;

    // If an empty element, do end right now (no endElement() will be called)
    if (isEmpty)
        endElement(elemDecl, urlId, isRoot, elemPrefix);
}