Esempio n. 1
0
bool XMLHandler::startElement(const QString &namespaceURI, const QString & /*localName*/, const QString &qName, const QXmlAttributes &atts)
{
    if(currentNode()->nodeType() == Node::TEXT_NODE)
        exitText();

    DOMString nsURI;
    if(!namespaceURI.isNull())
        nsURI = DOMString(namespaceURI);
    else
        // No namespace declared, default to the no namespace
        nsURI = DOMString("");
    ElementImpl *newElement = m_doc->createElementNS(nsURI, qName);
    if(!newElement)
        return false;
    int i;
    for(i = 0; i < atts.length(); i++)
    {
        int exceptioncode = 0;
        QString uriString = atts.uri(i);
        QString qnString = atts.qName(i);
        fixUpNSURI(uriString, qnString);
        DOMString uri(uriString);
        DOMString qn(qnString);
        DOMString val(atts.value(i));
        newElement->setAttributeNS(uri, qn, val, exceptioncode);
        if(exceptioncode) // exception setting attributes
            return false;
    }

    if(newElement->id() == ID_SCRIPT || newElement->id() == makeId(xhtmlNamespace, ID_SCRIPT))
        static_cast< HTMLScriptElementImpl * >(newElement)->setCreatedByParser(true);

    // this is tricky. in general the node doesn't have to attach to the one it's in. as far
    // as standards go this is wrong, but there's literally thousands of documents where
    // we see <p><ul>...</ul></p>. the following code is there for those cases.
    // when we can't attach to the currently holding us node we try to attach to its parent
    bool attached = false;
    for(NodeImpl *current = currentNode(); current; current = current->parent())
    {
        attached = current->addChild(newElement);
        if(attached)
            break;
    }
    if(attached)
    {
        if(m_view && !newElement->attached() && !m_doc->hasPendingSheets())
            newElement->attach();
        pushNode(newElement);
        return true;
    }
    else
    {
        delete newElement;
        return false;
    }

    // ### DOM spec states: "if there is no markup inside an element's content, the text is contained in a
    // single object implementing the Text interface that is the only child of the element."... do we
    // need to ensure that empty elements always have an empty text child?
}
void KHTMLParser::parseToken(Token *t)
{
    if (t->id > 2*ID_CLOSE_TAG)
    {
        kdDebug( 6035 ) << "Unknown tag!! tagID = " << t->id << endl;
        return;
    }
    if(discard_until) {
        if(t->id == discard_until)
            discard_until = 0;

        // do not skip </iframe>
        if ( discard_until || current->id() + ID_CLOSE_TAG != t->id )
            return;
    }

#ifdef PARSER_DEBUG
    kdDebug( 6035 ) << "\n\n==> parser: processing token " << getTagName(t->id).string() << "(" << t->id << ")"
                    << " current = " << getTagName(current->id()).string() << "(" << current->id() << ")" << endl;
    kdDebug(6035) << " inBody=" << inBody << " haveFrameSet=" << haveFrameSet << endl;
#endif

    // holy shit. apparently some sites use </br> instead of <br>
    // be compatible with IE and NS
    if(t->id == ID_BR+ID_CLOSE_TAG && document->document()->inCompatMode())
        t->id -= ID_CLOSE_TAG;

    if(t->id > ID_CLOSE_TAG)
    {
        processCloseTag(t);
        return;
    }

    // ignore spaces, if we're not inside a paragraph or other inline code
    if( t->id == ID_TEXT && t->text ) {
        if(inBody && !skipMode() && current->id() != ID_STYLE
                && current->id() != ID_TITLE && current->id() != ID_SCRIPT &&
                !t->text->containsOnlyWhitespace())
            haveContent = true;
#ifdef PARSER_DEBUG
        kdDebug(6035) << "length="<< t->text->l << " text='" << QConstString(t->text->s, t->text->l).string() << "'" << endl;
#endif
    }

    NodeImpl *n = getElement(t);
    // just to be sure, and to catch currently unimplemented stuff
    if(!n)
        return;

    // set attributes
    if(n->isElementNode())
    {
        ElementImpl *e = static_cast<ElementImpl *>(n);
        e->setAttributeMap(t->attrs);

        // take care of optional close tags
        if(endTag[e->id()] == DOM::OPTIONAL)
            popBlock(t->id);
    }

    // if this tag is forbidden inside the current context, pop
    // blocks until we are allowed to add it...
    while(forbiddenTag[t->id]) {
#ifdef PARSER_DEBUG
        kdDebug( 6035 ) << "t->id: " << t->id << " is forbidden :-( " << endl;
#endif
        popOneBlock();
    }

    if (!insertNode(n, t->flat))
    {
        // we couldn't insert the node...

        if(n->isElementNode())
        {
            ElementImpl *e = static_cast<ElementImpl *>(n);
            e->setAttributeMap(0);
        }

#ifdef PARSER_DEBUG
        kdDebug( 6035 ) << "insertNode failed current=" << current->id() << ", new=" << n->id() << "!" << endl;
#endif
        if (map == n)
        {
#ifdef PARSER_DEBUG
            kdDebug( 6035 ) << "  --> resetting map!" << endl;
#endif
            map = 0;
        }
        if (form == n)
        {
#ifdef PARSER_DEBUG
            kdDebug( 6035 ) << "   --> resetting form!" << endl;
#endif
            form = 0;
        }
        delete n;
    }
}