void XMLTreeBuilder::processStartTag(const AtomicXMLToken& token) { exitText(); bool isFirstElement = !m_sawFirstElement; m_sawFirstElement = true; NodeStackItem top = m_currentNodeStack.last(); processNamespaces(token, top); QualifiedName qName(token.prefix(), token.name(), top.namespaceForPrefix(token.prefix(), top.namespaceURI())); RefPtr<Element> newElement = m_document->createElement(qName, true); processAttributes(token, top, newElement); newElement->beginParsingChildren(); m_currentNodeStack.last().node()->parserAddChild(newElement.get()); top.setNode(newElement); pushCurrentNode(top); if (!newElement->attached()) newElement->attach(); if (isFirstElement && m_document->frame()) m_document->frame()->loader()->dispatchDocumentElementAvailable(); if (token.selfClosing()) closeElement(newElement); }
void XMLTreeBuilder::processXMLEntity(const AtomicXMLToken& token) { DEFINE_STATIC_LOCAL(AtomicString, amp, ("amp")); DEFINE_STATIC_LOCAL(AtomicString, apos, ("apos")); DEFINE_STATIC_LOCAL(AtomicString, gt, ("gt")); DEFINE_STATIC_LOCAL(AtomicString, lt, ("lt")); DEFINE_STATIC_LOCAL(AtomicString, quot, ("quot")); DEFINE_STATIC_LOCAL(String, ampS, ("&")); DEFINE_STATIC_LOCAL(String, aposS, ("'")); DEFINE_STATIC_LOCAL(String, gtS, (">")); DEFINE_STATIC_LOCAL(String, ltS, ("<")); DEFINE_STATIC_LOCAL(String, quotS, ("\"")); if (token.name() == amp) appendToText(ampS.characters(), 1); else if (token.name() == apos) appendToText(aposS.characters(), 1); else if (token.name() == gt) appendToText(gtS.characters(), 1); else if (token.name() == lt) appendToText(ltS.characters(), 1); else if (token.name() == quot) appendToText(quotS.characters(), 1); else m_parser->stopParsing(); }
void XMLTreeBuilder::processDOCTYPE(const AtomicXMLToken& token) { DEFINE_STATIC_LOCAL(AtomicString, xhtmlTransitional, ("-//W3C//DTD XHTML 1.0 Transitional//EN")); DEFINE_STATIC_LOCAL(AtomicString, xhtml11, ("-//W3C//DTD XHTML 1.1//EN")); DEFINE_STATIC_LOCAL(AtomicString, xhtmlStrict, ("-//W3C//DTD XHTML 1.0 Strict//EN")); DEFINE_STATIC_LOCAL(AtomicString, xhtmlFrameset, ("-//W3C//DTD XHTML 1.0 Frameset//EN")); DEFINE_STATIC_LOCAL(AtomicString, xhtmlBasic, ("-//W3C//DTD XHTML Basic 1.0//EN")); DEFINE_STATIC_LOCAL(AtomicString, xhtmlMathML, ("-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN")); DEFINE_STATIC_LOCAL(AtomicString, xhtmlMathMLSVG, ("-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN")); DEFINE_STATIC_LOCAL(AtomicString, xhtmlMobile, ("-//WAPFORUM//DTD XHTML Mobile 1.0//EN")); if (!failOnText()) return; AtomicString publicIdentifier(token.publicIdentifier().data(), token.publicIdentifier().size()); AtomicString systemIdentifier(token.systemIdentifier().data(), token.systemIdentifier().size()); RefPtr<DocumentType> doctype = DocumentType::create(m_document, token.name(), publicIdentifier, systemIdentifier); m_document->setDocType(doctype); m_document->parserAddChild(doctype); if ((publicIdentifier == xhtmlTransitional) || (publicIdentifier == xhtml11) || (publicIdentifier == xhtmlStrict) || (publicIdentifier == xhtmlFrameset) || (publicIdentifier == xhtmlBasic) || (publicIdentifier == xhtmlMathML) || (publicIdentifier == xhtmlMathMLSVG) || (publicIdentifier == xhtmlMobile)) m_isXHTML = true; }
void XMLTreeBuilder::processProcessingInstruction(const AtomicXMLToken& token) { if (!failOnText()) return; // FIXME: fall back if we can't handle the PI ourself. add(ProcessingInstruction::create(m_document, token.target(), token.data())); }
void XMLTreeBuilder::processNamespaces(const AtomicXMLToken& token, NodeStackItem& stackItem) { for (unsigned i = 0; i < token.attributes().size(); ++i) { const Attribute& tokenAttribute = token.attributes().at(i); if (tokenAttribute.name().prefix() == xmlnsAtom) stackItem.setNamespaceURI(tokenAttribute.name().localName(), tokenAttribute.value()); else if (tokenAttribute.name() == xmlnsAtom) stackItem.setNamespaceURI(tokenAttribute.value()); } }
void XMLTreeBuilder::processEndTag(const AtomicXMLToken& token) { exitText(); RefPtr<ContainerNode> node = m_currentNodeStack.last().node(); if (!node->hasTagName(QualifiedName(token.prefix(), token.name(), m_currentNodeStack.last().namespaceForPrefix(token.prefix(), m_currentNodeStack.last().namespaceURI())))) m_parser->stopParsing(); closeElement(toElement(node.get())); }
void XMLTreeBuilder::processNamespaces(const AtomicXMLToken& token, NodeStackItem& stackItem) { if (!token.attributes()) return; for (size_t i = 0; i < token.attributes()->size(); ++i) { Attribute* attribute = token.attributes()->attributeItem(i); if (attribute->name().prefix() == xmlnsAtom) stackItem.setNamespaceURI(attribute->name().localName(), attribute->value()); else if (attribute->name() == xmlnsAtom) stackItem.setNamespaceURI(attribute->value()); } }
void XMLTreeBuilder::processHTMLEntity(const AtomicXMLToken& token) { HTMLEntitySearch search; const AtomicString& name = token.name(); for (size_t i = 0; i < name.length(); ++i) { search.advance(name[i]); if (!search.isEntityPrefix()) { m_parser->stopParsing(); return; } } search.advance(';'); if (!search.isEntityPrefix()) { m_parser->stopParsing(); return; } UChar32 entityValue = search.mostRecentMatch()->firstValue; // FIXME: We need to account for secondValue if any XML entities are longer // than one unicode character. ASSERT_NOT_REACHED(); // Darin Adler writes: // You can see given the code above that this else is dead code. This code is in a strange state. // And the reinterpret_cast to UChar* makes the code little-endian-specific. That is not good! if (entityValue <= 0xFFFF) appendToText(reinterpret_cast<UChar*>(&entityValue), 1); else { UChar utf16Pair[2] = { U16_LEAD(entityValue), U16_TRAIL(entityValue) }; appendToText(utf16Pair, 2); } }
void XMLTreeBuilder::processXMLDeclaration(const AtomicXMLToken& token) { if (!failOnText()) return; ExceptionCode ec = 0; m_document->setXMLVersion(String(token.xmlVersion()), ec); if (ec) m_parser->stopParsing(); m_document->setXMLStandalone(token.xmlStandalone(), ec); if (ec) m_parser->stopParsing(); // FIXME: how should this behave if standalone is not specified? // FIXME: set encoding. }
void XMLTreeBuilder::processAttributes(const AtomicXMLToken& token, NodeStackItem& stackItem, PassRefPtr<Element> newElement) { for (unsigned i = 0; i < token.attributes().size(); ++i) { const Attribute& tokenAttribute = token.attributes().at(i); ExceptionCode ec = 0; if (tokenAttribute.name().prefix() == xmlnsAtom) newElement->setAttributeNS(XMLNSNames::xmlnsNamespaceURI, "xmlns:" + tokenAttribute.name().localName(), tokenAttribute.value(), ec); else if (tokenAttribute.name() == xmlnsAtom) newElement->setAttributeNS(XMLNSNames::xmlnsNamespaceURI, xmlnsAtom, tokenAttribute.value(), ec); else { QualifiedName qName(tokenAttribute.prefix(), tokenAttribute.localName(), stackItem.namespaceForPrefix(tokenAttribute.prefix(), nullAtom)); newElement->setAttribute(qName, tokenAttribute.value()); } if (ec) { m_parser->stopParsing(); return; } } }
void XMLTreeBuilder::processAttributes(const AtomicXMLToken& token, NodeStackItem& stackItem, PassRefPtr<Element> newElement) { if (!token.attributes()) return; for (size_t i = 0; i < token.attributes()->size(); ++i) { Attribute* attribute = token.attributes()->attributeItem(i); ExceptionCode ec = 0; if (attribute->name().prefix() == xmlnsAtom) newElement->setAttributeNS(XMLNSNames::xmlnsNamespaceURI, "xmlns:" + attribute->name().localName(), attribute->value(), ec); else if (attribute->name() == xmlnsAtom) newElement->setAttributeNS(XMLNSNames::xmlnsNamespaceURI, xmlnsAtom, attribute->value(), ec); else { QualifiedName qName(attribute->prefix(), attribute->localName(), stackItem.namespaceForPrefix(attribute->prefix(), nullAtom)); newElement->setAttribute(qName, attribute->value()); } if (ec) { m_parser->stopParsing(); return; } } }
void XMLTreeBuilder::processHTMLEntity(const AtomicXMLToken& token) { HTMLEntitySearch search; const AtomicString& name = token.name(); for (size_t i = 0; i < name.length(); ++i) { search.advance(name[i]); if (!search.isEntityPrefix()) { m_parser->stopParsing(); return; } } search.advance(';'); UChar32 entityValue = search.currentValue(); if (entityValue <= 0xFFFF) appendToText(reinterpret_cast<UChar*>(&entityValue), 1); else { UChar utf16Pair[2] = { U16_LEAD(entityValue), U16_TRAIL(entityValue) }; appendToText(utf16Pair, 2); } }
void XMLTreeBuilder::processToken(const AtomicXMLToken& token) { switch (token.type()) { case XMLTokenTypes::Uninitialized: ASSERT_NOT_REACHED(); break; case XMLTokenTypes::ProcessingInstruction: processProcessingInstruction(token); break; case XMLTokenTypes::XMLDeclaration: processXMLDeclaration(token); break; case XMLTokenTypes::DOCTYPE: processDOCTYPE(token); break; case XMLTokenTypes::StartTag: processStartTag(token); break; case XMLTokenTypes::EndTag: processEndTag(token); break; case XMLTokenTypes::CDATA: processCDATA(token); break; case XMLTokenTypes::Character: processCharacter(token); break; case XMLTokenTypes::Comment: processComment(token); break; case XMLTokenTypes::Entity: processEntity(token); break; case XMLTokenTypes::EndOfFile: exitText(); return; } }
void XMLTreeBuilder::processComment(const AtomicXMLToken& token) { exitText(); add(Comment::create(m_document, token.comment())); }
void XMLTreeBuilder::processCDATA(const AtomicXMLToken& token) { exitText(); add(CDATASection::create(m_document, token.data())); }
void XMLTreeBuilder::processCharacter(const AtomicXMLToken& token) { appendToText(token.characters().data(), token.characters().size()); }