⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmltokenizerqt.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2000 Peter Kelly (pmk@post.com) * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) * Copyright (C) 2007 Samuel Weinig (sam@webkit.org) * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008 Holger Hans Peter Freyther * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */#include "config.h"#include "XMLTokenizer.h"#include "CDATASection.h"#include "CString.h"#include "CachedScript.h"#include "Comment.h"#include "DocLoader.h"#include "Document.h"#include "DocumentFragment.h"#include "DocumentType.h"#include "Frame.h"#include "FrameLoader.h"#include "FrameView.h"#include "HTMLLinkElement.h"#include "HTMLStyleElement.h"#include "HTMLTokenizer.h"#include "ProcessingInstruction.h"#include "ResourceError.h"#include "ResourceHandle.h"#include "ResourceRequest.h"#include "ResourceResponse.h"#include "ScriptController.h"#include "ScriptElement.h"#include "ScriptSourceCode.h"#include "ScriptValue.h"#include "TextResourceDecoder.h"#include <QDebug>#include <wtf/Platform.h>#include <wtf/StringExtras.h>#include <wtf/Threading.h>#include <wtf/Vector.h>using namespace std;namespace WebCore {#if QT_VERSION >= 0x040400class EntityResolver : public QXmlStreamEntityResolver{    virtual QString resolveUndeclaredEntity(const QString &name);};QString EntityResolver::resolveUndeclaredEntity(const QString &name){    UChar c = decodeNamedEntity(name.toUtf8().constData());    return QString(c);}#endif// --------------------------------XMLTokenizer::XMLTokenizer(Document* _doc, FrameView* _view)    : m_doc(_doc)    , m_view(_view)    , m_wroteText(false)    , m_currentNode(_doc)    , m_currentNodeIsReferenced(false)    , m_sawError(false)    , m_sawXSLTransform(false)    , m_sawFirstElement(false)    , m_isXHTMLDocument(false)    , m_parserPaused(false)    , m_requestingScript(false)    , m_finishCalled(false)    , m_errorCount(0)    , m_lastErrorLine(0)    , m_lastErrorColumn(0)    , m_pendingScript(0)    , m_scriptStartLine(0)    , m_parsingFragment(false){#if QT_VERSION >= 0x040400    m_stream.setEntityResolver(new EntityResolver);#endif}XMLTokenizer::XMLTokenizer(DocumentFragment* fragment, Element* parentElement)    : m_doc(fragment->document())    , m_view(0)    , m_wroteText(false)    , m_currentNode(fragment)    , m_currentNodeIsReferenced(fragment)    , m_sawError(false)    , m_sawXSLTransform(false)    , m_sawFirstElement(false)    , m_isXHTMLDocument(false)    , m_parserPaused(false)    , m_requestingScript(false)    , m_finishCalled(false)    , m_errorCount(0)    , m_lastErrorLine(0)    , m_lastErrorColumn(0)    , m_pendingScript(0)    , m_scriptStartLine(0)    , m_parsingFragment(true){    if (fragment)        fragment->ref();    if (m_doc)        m_doc->ref();              // Add namespaces based on the parent node    Vector<Element*> elemStack;    while (parentElement) {        elemStack.append(parentElement);                Node* n = parentElement->parentNode();        if (!n || !n->isElementNode())            break;        parentElement = static_cast<Element*>(n);    }        if (elemStack.isEmpty())        return;    #if QT_VERSION < 0x040400    for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) {        if (NamedAttrMap* attrs = element->attributes()) {            for (unsigned i = 0; i < attrs->length(); i++) {                Attribute* attr = attrs->attributeItem(i);                if (attr->localName() == "xmlns")                    m_defaultNamespaceURI = attr->value();                else if (attr->prefix() == "xmlns")                    m_prefixToNamespaceMap.set(attr->localName(), attr->value());            }        }    }#else    QXmlStreamNamespaceDeclarations namespaces;    for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) {        if (NamedAttrMap* attrs = element->attributes()) {            for (unsigned i = 0; i < attrs->length(); i++) {                Attribute* attr = attrs->attributeItem(i);                if (attr->localName() == "xmlns")                    m_defaultNamespaceURI = attr->value();                else if (attr->prefix() == "xmlns")                    namespaces.append(QXmlStreamNamespaceDeclaration(attr->localName(), attr->value()));            }        }    }    m_stream.addExtraNamespaceDeclarations(namespaces);    m_stream.setEntityResolver(new EntityResolver);#endif    // If the parent element is not in document tree, there may be no xmlns attribute; just default to the parent's namespace.    if (m_defaultNamespaceURI.isNull() && !parentElement->inDocument())        m_defaultNamespaceURI = parentElement->namespaceURI();}XMLTokenizer::~XMLTokenizer(){    setCurrentNode(0);    if (m_parsingFragment && m_doc)        m_doc->deref();    if (m_pendingScript)        m_pendingScript->removeClient(this);#if QT_VERSION >= 0x040400    delete m_stream.entityResolver();#endif}void XMLTokenizer::doWrite(const String& parseString){    m_wroteText = true;    if (m_doc->decoder() && m_doc->decoder()->sawError()) {        // If the decoder saw an error, report it as fatal (stops parsing)        handleError(fatal, "Encoding error", lineNumber(), columnNumber());        return;    }    QString data(parseString);    if (!data.isEmpty()) {#if QT_VERSION < 0x040400        if (!m_sawFirstElement) {            int idx = data.indexOf(QLatin1String("<?xml"));            if (idx != -1) {                int start = idx + 5;                int end = data.indexOf(QLatin1String("?>"), start);                QString content = data.mid(start, end-start);                bool ok = true;                HashMap<String, String> attrs = parseAttributes(content, ok);                String version = attrs.get("version");                String encoding = attrs.get("encoding");                ExceptionCode ec = 0;                if (!m_parsingFragment) {                    if (!version.isEmpty())                        m_doc->setXMLVersion(version, ec);                    if (!encoding.isEmpty())                        m_doc->setXMLEncoding(encoding);                }            }        }#endif        m_stream.addData(data);        parse();    }    return;}void XMLTokenizer::initializeParserContext(const char* chunk){    m_parserStopped = false;    m_sawError = false;    m_sawXSLTransform = false;    m_sawFirstElement = false;}void XMLTokenizer::doEnd(){#if ENABLE(XSLT)    #warning Look at XMLTokenizerLibXml.cpp#endif    if (m_stream.error() == QXmlStreamReader::PrematureEndOfDocumentError || (m_wroteText && !m_sawFirstElement)) {        handleError(fatal, qPrintable(m_stream.errorString()), lineNumber(),                    columnNumber());    }}#if ENABLE(XSLT)void* xmlDocPtrForString(DocLoader* docLoader, const String& source, const String& url){    if (source.isEmpty())        return 0;    // Parse in a single chunk into an xmlDocPtr    // FIXME: Hook up error handlers so that a failure to parse the main document results in    // good error messages.    const UChar BOM = 0xFEFF;    const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);    xmlGenericErrorFunc oldErrorFunc = xmlGenericError;    void* oldErrorContext = xmlGenericErrorContext;        setLoaderForLibXMLCallbacks(docLoader);            xmlSetGenericErrorFunc(0, errorFunc);        xmlDocPtr sourceDoc = xmlReadMemory(reinterpret_cast<const char*>(source.characters()),                                        source.length() * sizeof(UChar),                                        url.latin1().data(),                                        BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE",                                         XSLT_PARSE_OPTIONS);        setLoaderForLibXMLCallbacks(0);    xmlSetGenericErrorFunc(oldErrorContext, oldErrorFunc);        return sourceDoc;}#endifint XMLTokenizer::lineNumber() const{    return m_stream.lineNumber();}int XMLTokenizer::columnNumber() const{    return m_stream.columnNumber();}void XMLTokenizer::stopParsing(){    Tokenizer::stopParsing();}void XMLTokenizer::resumeParsing(){    ASSERT(m_parserPaused);        m_parserPaused = false;    // First, execute any pending callbacks    parse();    if (m_parserPaused)        return;    // Then, write any pending data    SegmentedString rest = m_pendingSrc;    m_pendingSrc.clear();    write(rest, false);    // Finally, if finish() has been called and write() didn't result    // in any further callbacks being queued, call end()    if (m_finishCalled && !m_parserPaused && !m_pendingScript)        end();}bool parseXMLDocumentFragment(const String& chunk, DocumentFragment* fragment, Element* parent){    if (!chunk.length())        return true;    XMLTokenizer tokenizer(fragment, parent);        tokenizer.write(String("<qxmlstreamdummyelement>"), false);    tokenizer.write(chunk, false);    tokenizer.write(String("</qxmlstreamdummyelement>"), false);    tokenizer.finish();    return !tokenizer.hasError();}// --------------------------------struct AttributeParseState {    HashMap<String, String> attributes;    bool gotAttributes;};static void attributesStartElementNsHandler(AttributeParseState* state, const QXmlStreamAttributes& attrs){    if (attrs.count() <= 0)        return;    state->gotAttributes = true;    for(int i = 0; i < attrs.count(); i++) {        const QXmlStreamAttribute& attr = attrs[i];        String attrLocalName = attr.name();        String attrValue     = attr.value();        String attrURI       = attr.namespaceUri();        String attrQName     = attr.qualifiedName();        state->attributes.set(attrQName, attrValue);    }}HashMap<String, String> parseAttributes(const String& string, bool& attrsOK){    AttributeParseState state;    state.gotAttributes = false;    QXmlStreamReader stream;    QString dummy = QString(QLatin1String("<?xml version=\"1.0\"?><attrs %1 />")).arg(string);    stream.addData(dummy);    while (!stream.atEnd()) {        stream.readNext();        if (stream.isStartElement()) {            attributesStartElementNsHandler(&state, stream.attributes());        }    }    attrsOK = state.gotAttributes;    return state.attributes;}static inline String prefixFromQName(const QString& qName){    const int offset = qName.indexOf(QLatin1Char(':'));    if (offset <= 0)        return String();    else        return qName.left(offset);}static inline void handleElementNamespaces(Element* newElement, const QXmlStreamNamespaceDeclarations &ns,                                           ExceptionCode& ec){    for (int i = 0; i < ns.count(); ++i) {        const QXmlStreamNamespaceDeclaration &decl = ns[i];        String namespaceURI = decl.namespaceUri();        String namespaceQName = decl.prefix().isEmpty() ? String("xmlns") : String("xmlns:") + decl.prefix();        newElement->setAttributeNS("http://www.w3.org/2000/xmlns/", namespaceQName, namespaceURI, ec);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -