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

📄 xml_tokenizer.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    }

    if (m_currentNode->addChild(newElement)) {
        if (m_view && !newElement->attached())
            newElement->attach();
        m_currentNode = newElement;
        return;
    }
    else {
        delete newElement;
        return;
    }

    // ### 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 XMLTokenizer::endElement()
{
    if (m_parserStopped) return;

    popNamespaces();

    if (m_currentNode->nodeType() == Node::TEXT_NODE)
        exitText();
    if (m_currentNode->parentNode() != 0) {
        do {
            m_currentNode = m_currentNode->parentNode();
        } while (m_currentNode && m_currentNode->implicitNode());
    }
// ###  else error
}

void XMLTokenizer::characters(const xmlChar *s, int len)
{
    if (m_parserStopped) return;

    if (m_currentNode->nodeType() == Node::TEXT_NODE ||
        m_currentNode->nodeType() == Node::CDATA_SECTION_NODE ||
        enterText()) {

        int exceptioncode = 0;
        static_cast<TextImpl*>(m_currentNode)->appendData(QString::fromUtf8(reinterpret_cast<const char *>(s), len),
            exceptioncode);
    }
}

bool XMLTokenizer::enterText()
{
    NodeImpl *newNode = m_doc->document()->createTextNode("");
    if (m_currentNode->addChild(newNode)) {
        m_currentNode = newNode;
        return true;
    }
    else {
        delete newNode;
        return false;
    }
}

void XMLTokenizer::exitText()
{
    if (m_view && m_currentNode && !m_currentNode->attached())
        m_currentNode->attach();

    NodeImpl* par = m_currentNode->parentNode();
    if (par != 0)
        m_currentNode = par;
}

void XMLTokenizer::error(ErrorType type, const char *message, va_list args)
{
    if (m_parserStopped) {
        return;
    }

    if (type == fatal || (m_errorCount < maxErrors && m_lastErrorLine != lineNumber() && m_lastErrorColumn != columnNumber())) {

        QString format;
        switch (type) {
            case warning:
#if APPLE_CHANGES
                format = QString("warning on line %2 at column %3: %1");
#else
                format = i18n( "warning: %1 in line %2, column %3\n" );
#endif
                break;
            case fatal:
#if APPLE_CHANGES
                // fall through
#else
                format = i18n( "fatal error: %1 in line %2, column %3\n" );
                break;
#endif
            default:
#if APPLE_CHANGES
                format = QString("error on line %2 at column %3: %1");
#else
                format = i18n( "error: %1 in line %2, column %3\n" );
#endif
        }
#if !NOKIA_CHANGES
        char *m;
        vasprintf(&m, message, args);
        m_errorMessages += format.arg(m).arg(lineNumber()).arg(columnNumber());
        free(m);
#endif
        m_lastErrorLine = lineNumber();
        m_lastErrorColumn = columnNumber();
        ++m_errorCount;
    }

    if (type != warning)
        m_sawError = true;

    if (type == fatal)
        stopParsing();
}

void XMLTokenizer::processingInstruction(const xmlChar *target, const xmlChar *data)
{
    if (m_parserStopped) {
        return;
    }

    if (m_currentNode->nodeType() == Node::TEXT_NODE)
        exitText();
    // ### handle exceptions
    ProcessingInstructionImpl *pi = m_doc->document()->createProcessingInstruction(
        QString::fromUtf8(reinterpret_cast<const char *>(target)),
        QString::fromUtf8(reinterpret_cast<const char *>(data)));
    m_currentNode->addChild(pi);
    // don't load stylesheets for standalone documents
    if (m_doc->document()->part()) {
	m_sawXSLTransform = !pi->checkStyleSheet();
        if (m_sawXSLTransform)
            // Stop the SAX parser.
            stopParsing();
    }
}

void XMLTokenizer::cdataBlock(const xmlChar *s, int len)
{
    if (m_parserStopped) {
        return;
    }

    if (m_currentNode->nodeType() == Node::TEXT_NODE)
        exitText();

    NodeImpl *newNode = m_doc->document()->createCDATASection("");
    if (m_currentNode->addChild(newNode)) {
        if (m_view && !newNode->attached())
            newNode->attach();
        m_currentNode = newNode;
    }
    else {
        delete newNode;
        return;
    }

    characters(s, len);

    if (m_currentNode->parentNode() != 0)
        m_currentNode = m_currentNode->parentNode();
}

void XMLTokenizer::comment(const xmlChar *s)
{
    if (m_parserStopped) return;

    if (m_currentNode->nodeType() == Node::TEXT_NODE)
        exitText();
    // ### handle exceptions
    m_currentNode->addChild(m_doc->document()->createComment(QString::fromUtf8(reinterpret_cast<const char *>(s))));
}

static void startElementHandler(void *userData, const xmlChar *name, const xmlChar **libxmlAttributes)
{
    static_cast<XMLTokenizer *>(userData)->startElement(name, libxmlAttributes);
}

static void endElementHandler(void *userData, const xmlChar *name)
{
    static_cast<XMLTokenizer *>(userData)->endElement();
}

static void charactersHandler(void *userData, const xmlChar *s, int len)
{
    static_cast<XMLTokenizer *>(userData)->characters(s, len);
}

static void processingInstructionHandler(void *userData, const xmlChar *target, const xmlChar *data)
{
    static_cast<XMLTokenizer *>(userData)->processingInstruction(target, data);
}

static void cdataBlockHandler(void *userData, const xmlChar *s, int len)
{
    static_cast<XMLTokenizer *>(userData)->cdataBlock(s, len);
}

static void commentHandler(void *userData, const xmlChar *comment)
{
    static_cast<XMLTokenizer *>(userData)->comment(comment);
}

static void warningHandler(void *userData, const char *message, ...)
{
    va_list args;
    va_start(args, message);
    static_cast<XMLTokenizer *>(userData)->error(XMLTokenizer::warning, message, args);
    va_end(args);
}

static void fatalErrorHandler(void *userData, const char *message, ...)
{
    va_list args;
    va_start(args, message);
    static_cast<XMLTokenizer *>(userData)->error(XMLTokenizer::fatal, message, args);
    va_end(args);
}

static void normalErrorHandler(void *userData, const char *message, ...)
{
    va_list args;
    va_start(args, message);
    static_cast<XMLTokenizer *>(userData)->error(XMLTokenizer::nonFatal, message, args);
    va_end(args);
}


void XMLTokenizer::finish()
{
    xmlSAXHandler sax;
    memset(&sax, 0, sizeof(sax));
    sax.error = normalErrorHandler;
    sax.fatalError = fatalErrorHandler;
    sax.characters = charactersHandler;
    sax.endElement = endElementHandler;
    sax.processingInstruction = processingInstructionHandler;
    sax.startElement = startElementHandler;
    sax.cdataBlock = cdataBlockHandler;
    sax.comment = commentHandler;
    sax.warning = warningHandler;
    m_parserStopped = false;
    m_sawError = false;
    m_sawXSLTransform = false;
    m_context = createQStringParser(&sax, this, m_doc->document()->URL().ascii());
    parseQString(m_context, m_xmlCode);
    xmlFreeParserCtxt(m_context);
    m_context = NULL;

    if (m_sawError) {
        insertErrorMessageBlock();
    } else {
        // Parsing was successful. Now locate all html <script> tags in the document and execute them
        // one by one.
        addScripts(m_doc->document());
        m_scriptsIt = new QPtrListIterator<HTMLScriptElementImpl>(m_scripts);
        executeScripts();
    }
    emit finishedParsing();
}

void XMLTokenizer::insertErrorMessageBlock()
{
    // One or more errors occurred during parsing of the code. Display an error block to the user above
    // the normal content (the DOM tree is created manually and includes line/col info regarding
    // where the errors are located)

    // Create elements for display
    int exceptioncode = 0;
    DocumentImpl *doc = m_doc->document();
    NodeImpl* root = doc->documentElement();
    if (!root) {
        root = doc->createElementNS(XHTML_NAMESPACE, "html", exceptioncode);
        NodeImpl* body = doc->createElementNS(XHTML_NAMESPACE, "body", exceptioncode);
        root->appendChild(body, exceptioncode);
        doc->appendChild(root, exceptioncode);
        root = body;
    }

    ElementImpl* reportElement = doc->createElementNS(XHTML_NAMESPACE, "parsererror", exceptioncode);
    reportElement->setAttribute(ATTR_STYLE, "white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black");
    ElementImpl* h3 = doc->createElementNS(XHTML_NAMESPACE, "h3", exceptioncode);
    h3->appendChild(doc->createTextNode("This page contains the following errors:"), exceptioncode);
    reportElement->appendChild(h3, exceptioncode);
    ElementImpl* fixed = doc->createElementNS(XHTML_NAMESPACE, "div", exceptioncode);
    fixed->setAttribute(ATTR_STYLE, "font-family:monospace;font-size:12px");
    NodeImpl* textNode = doc->createTextNode(m_errorMessages);
    fixed->appendChild(textNode, exceptioncode);
    reportElement->appendChild(fixed, exceptioncode);
    h3 = doc->createElementNS(XHTML_NAMESPACE, "h3", exceptioncode);
    reportElement->appendChild(h3, exceptioncode);

    h3->appendChild(doc->createTextNode("Below is a rendering of the page up to the first error."), exceptioncode);
#ifdef KHTML_XSLT
    if (doc->transformSourceDocument()) {
        ElementImpl* par = doc->createElementNS(XHTML_NAMESPACE, "p", exceptioncode);
        reportElement->appendChild(par, exceptioncode);
        par->setAttribute(ATTR_STYLE, "white-space: normal");
        par->appendChild(doc->createTextNode("This document was created as the result of an XSL transformation. The line and column numbers given are from the transformed result."), exceptioncode);
    }
#endif
    root->insertBefore(reportElement, root->firstChild(), exceptioncode);

    doc->updateRendering();
}

void XMLTokenizer::addScripts(NodeImpl *n)
{
    // Recursively go through the entire document tree, looking for html <script> tags. For each of these
    // that is found, add it to the m_scripts list from which they will be executed

    if (n->id() == ID_SCRIPT) {
        m_scripts.append(static_cast<HTMLScriptElementImpl*>(n));
    }

    NodeImpl *child;
    for (child = n->firstChild(); child; child = child->nextSibling())
        addScripts(child);
}

void XMLTokenizer::executeScripts()
{
    // Iterate through all of the html <script> tags in the document. For those that have a src attribute,
    // start loading the script and return (executeScripts() will be called again once the script is loaded
    // and continue where it left off). For scripts that don't have a src attribute, execute the code
    // inside the tag
    while (m_scriptsIt->current()) {
        DOMString scriptSrc = m_scriptsIt->current()->getAttribute(ATTR_SRC);
        QString charset = m_scriptsIt->current()->getAttribute(ATTR_CHARSET).string();

	// don't load external scripts for standalone documents (for now)
        if (scriptSrc != "" && m_doc->document()->part()) {
            // we have a src attribute

⌨️ 快捷键说明

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