📄 xml_tokenizer.cpp
字号:
/** * This file is part of the DOM implementation for KDE. * * Copyright (C) 2000 Peter Kelly (pmk@post.com) * Copyright (C) 2003 Apple Computer, Inc. * * 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 "xml_tokenizer.h"#include "xml/dom_docimpl.h"#include "xml/dom_textimpl.h"#include "xml/dom_xmlimpl.h"#include "html/html_tableimpl.h"#include "html/html_headimpl.h"#include "rendering/render_object.h"#include "misc/htmltags.h"#include "misc/htmlattrs.h"#include "misc/loader.h"#include "khtmlview.h"#include "khtml_part.h"#include <qvariant.h>#include <kdebug.h>#include <klocale.h>using namespace DOM;using namespace khtml;XMLIncrementalSource::XMLIncrementalSource() : QXmlInputSource(), m_pos( 0 ), m_unicode( 0 ), m_finished( false ){}void XMLIncrementalSource::fetchData(){ //just a dummy to overwrite default behavior}QChar XMLIncrementalSource::next(){ if ( m_finished ) return QXmlInputSource::EndOfDocument; else if ( m_data.length() <= m_pos ) return QXmlInputSource::EndOfData; else return m_unicode[m_pos++];}void XMLIncrementalSource::setData( const QString& str ){ m_data = str; m_unicode = m_data.unicode(); m_pos = 0; if ( !str.isEmpty() ) m_finished = false;}void XMLIncrementalSource::setData( const QByteArray& data ){ setData( fromRawData( data, true ) );}void XMLIncrementalSource::appendXML( const QString& str ){ m_data += str; m_unicode = m_data.unicode();}QString XMLIncrementalSource::data(){ return m_data;}void XMLIncrementalSource::setFinished( bool finished ){ m_finished = finished;}XMLHandler::XMLHandler(DocumentPtr *_doc, KHTMLView *_view) : errorLine(0){ m_doc = _doc; if ( m_doc ) m_doc->ref(); m_view = _view; pushNode( _doc->document() );}XMLHandler::~XMLHandler(){ if ( m_doc ) m_doc->deref();}void XMLHandler::pushNode( NodeImpl *node ){ m_nodes.push( node );}NodeImpl *XMLHandler::popNode(){ return m_nodes.pop();}NodeImpl *XMLHandler::currentNode() const{ return m_nodes.current();}QString XMLHandler::errorProtocol(){ return errorProt;}bool XMLHandler::startDocument(){ // at the beginning of parsing: do some initialization errorProt = ""; state = StateInit; return true;}bool XMLHandler::startElement( const QString& namespaceURI, const QString& /*localName*/, const QString& qName, const QXmlAttributes& atts ){ if (currentNode()->nodeType() == Node::TEXT_NODE) exitText(); ElementImpl *newElement = m_doc->document()->createElementNS(namespaceURI,qName); if (!newElement) return false; int i; for (i = 0; i < atts.length(); i++) { int exceptioncode = 0; DOMString uri(atts.uri(i)); DOMString qn(atts.qName(i)); DOMString val(atts.value(i)); newElement->setAttributeNS(uri, qn, val, exceptioncode); if (exceptioncode) // exception setting attributes return false; } if (newElement->id() == 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->document()->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?}bool XMLHandler::endElement( const QString& /*namespaceURI*/, const QString& /*localName*/, const QString& /*qName*/ ){ if (currentNode()->nodeType() == Node::TEXT_NODE) exitText(); NodeImpl *node = popNode(); if ( node ) { node->close(); while ( currentNode() && currentNode()->implicitNode() ) //for the implicit HTMLTableSectionElementImpl popNode()->close(); } else return false; return true;}bool XMLHandler::startCDATA(){ if (currentNode()->nodeType() == Node::TEXT_NODE) exitText(); NodeImpl *newNode = m_doc->document()->createCDATASection(new DOMStringImpl("")); if (currentNode()->addChild(newNode)) { if (m_view && !newNode->attached() && !m_doc->document()->hasPendingSheets()) newNode->attach(); pushNode( newNode ); return true; } else { delete newNode; return false; }}bool XMLHandler::endCDATA(){ popNode(); Q_ASSERT( currentNode() ); return currentNode();}bool XMLHandler::characters( const QString& ch ){ //this is needed for xhtml parsing. otherwise we try to attach //"\n\t" to html, head and other nodes which don't accept textchildren if ( ch.stripWhiteSpace().isEmpty() ) return true; if (currentNode()->nodeType() == Node::TEXT_NODE || currentNode()->nodeType() == Node::CDATA_SECTION_NODE || enterText()) { int exceptioncode = 0; static_cast<TextImpl*>(currentNode())->appendData(ch,exceptioncode); if (exceptioncode) return false; return true; } else return false;}bool XMLHandler::comment(const QString & ch){ if (currentNode()->nodeType() == Node::TEXT_NODE) exitText(); // ### handle exceptions currentNode()->addChild(m_doc->document()->createComment(new DOMStringImpl(ch.unicode(), ch.length()))); return true;}bool XMLHandler::processingInstruction(const QString &target, const QString &data){ if (currentNode()->nodeType() == Node::TEXT_NODE) exitText(); // ### handle exceptions ProcessingInstructionImpl *pi = m_doc->document()->createProcessingInstruction(target, new DOMStringImpl(data.unicode(), data.length())); currentNode()->addChild(pi); pi->checkStyleSheet(); return true;}QString XMLHandler::errorString(){ return i18n("the document is not in the correct file format");}bool XMLHandler::fatalError( const QXmlParseException& exception ){ errorProt += i18n( "fatal parsing error: %1 in line %2, column %3" ) .arg( exception.message() ) .arg( exception.lineNumber() ) .arg( exception.columnNumber() );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -