00001
00023 #include "xml_tokenizer.h"
00024 #include "xml/dom_docimpl.h"
00025 #include "xml/dom_textimpl.h"
00026 #include "xml/dom_xmlimpl.h"
00027 #include "html/html_headimpl.h"
00028 #include "rendering/render_object.h"
00029 #include "misc/htmltags.h"
00030 #include "misc/htmlattrs.h"
00031 #include "misc/loader.h"
00032
00033 #include "khtmlview.h"
00034 #include "khtml_part.h"
00035 #include <qvariant.h>
00036 #include <kdebug.h>
00037 #include <klocale.h>
00038
00039 using namespace DOM;
00040 using namespace khtml;
00041
00042 XMLHandler::XMLHandler(DocumentPtr *_doc, KHTMLView *_view)
00043 {
00044 m_doc = _doc;
00045 if ( m_doc ) m_doc->ref();
00046 m_view = _view;
00047 m_currentNode = _doc->document();
00048 }
00049
00050
00051 XMLHandler::~XMLHandler()
00052 {
00053 if ( m_doc ) m_doc->deref();
00054 }
00055
00056
00057 QString XMLHandler::errorProtocol()
00058 {
00059 return errorProt;
00060 }
00061
00062
00063 bool XMLHandler::startDocument()
00064 {
00065
00066 errorProt = "";
00067 state = StateInit;
00068
00069 return true;
00070 }
00071
00072
00073 bool XMLHandler::startElement( const QString& namespaceURI, const QString& , const QString& qName, const QXmlAttributes& atts )
00074 {
00075 if (m_currentNode->nodeType() == Node::TEXT_NODE)
00076 exitText();
00077
00078 ElementImpl *newElement;
00079 newElement = m_doc->document()->createElementNS(namespaceURI,qName);
00080
00081 int i;
00082 for (i = 0; i < atts.length(); i++) {
00083 int exceptioncode = 0;
00084 DOMString uri(atts.uri(i));
00085 DOMString ln(atts.localName(i));
00086 DOMString val(atts.value(i));
00087 NodeImpl::Id id = m_doc->document()->attrId(uri.implementation(),
00088 ln.implementation(),
00089 false );
00090 newElement->setAttribute(id, val.implementation(), exceptioncode);
00091 if (exceptioncode)
00092 return false;
00093 }
00094 if (m_currentNode->addChild(newElement)) {
00095 if (m_view && !newElement->attached())
00096 newElement->attach();
00097 m_currentNode = newElement;
00098 return true;
00099 }
00100 else {
00101 delete newElement;
00102 return false;
00103 }
00104
00105
00106
00107
00108 }
00109
00110
00111 bool XMLHandler::endElement( const QString& , const QString& , const QString& )
00112 {
00113 if (m_currentNode->nodeType() == Node::TEXT_NODE)
00114 exitText();
00115 if (m_currentNode->parentNode() != 0) {
00116 if (m_currentNode->renderer())
00117 m_currentNode->renderer()->close();
00118 m_currentNode = m_currentNode->parentNode();
00119 }
00120
00121
00122 return true;
00123 }
00124
00125
00126 bool XMLHandler::startCDATA()
00127 {
00128 if (m_currentNode->nodeType() == Node::TEXT_NODE)
00129 exitText();
00130
00131 NodeImpl *newNode = m_doc->document()->createCDATASection(new DOMStringImpl(""));
00132 if (m_currentNode->addChild(newNode)) {
00133 if (m_view && !newNode->attached())
00134 newNode->attach();
00135 m_currentNode = newNode;
00136 return true;
00137 }
00138 else {
00139 delete newNode;
00140 return false;
00141 }
00142
00143 }
00144
00145 bool XMLHandler::endCDATA()
00146 {
00147 if (m_currentNode->parentNode() != 0)
00148 m_currentNode = m_currentNode->parentNode();
00149 return true;
00150 }
00151
00152 bool XMLHandler::characters( const QString& ch )
00153 {
00154 if (ch.stripWhiteSpace().isEmpty())
00155 return true;
00156
00157 if (m_currentNode->nodeType() == Node::TEXT_NODE ||
00158 m_currentNode->nodeType() == Node::CDATA_SECTION_NODE ||
00159 enterText()) {
00160
00161 unsigned short parentId = m_currentNode->parentNode() ? m_currentNode->parentNode()->id() : 0;
00162 if (parentId == ID_SCRIPT || parentId == ID_STYLE || parentId == ID_XMP || parentId == ID_TEXTAREA) {
00163
00164
00165 int exceptioncode = 0;
00166 static_cast<TextImpl*>(m_currentNode)->appendData(ch,exceptioncode);
00167 if (exceptioncode)
00168 return false;
00169 }
00170 else {
00171
00172 int exceptioncode = 0;
00173 static_cast<TextImpl*>(m_currentNode)->appendData(ch.simplifyWhiteSpace(),exceptioncode);
00174 if (exceptioncode)
00175 return false;
00176 }
00177 return true;
00178 }
00179 else
00180 return false;
00181 }
00182
00183 bool XMLHandler::comment(const QString & ch)
00184 {
00185 if (m_currentNode->nodeType() == Node::TEXT_NODE)
00186 exitText();
00187
00188 m_currentNode->addChild(m_doc->document()->createComment(new DOMStringImpl(ch.unicode(), ch.length())));
00189 return true;
00190 }
00191
00192 bool XMLHandler::processingInstruction(const QString &target, const QString &data)
00193 {
00194 if (m_currentNode->nodeType() == Node::TEXT_NODE)
00195 exitText();
00196
00197 ProcessingInstructionImpl *pi =
00198 m_doc->document()->createProcessingInstruction(target, new DOMStringImpl(data.unicode(), data.length()));
00199 m_currentNode->addChild(pi);
00200 pi->checkStyleSheet();
00201 return true;
00202 }
00203
00204
00205 QString XMLHandler::errorString()
00206 {
00207 return i18n("the document is not in the correct file format");
00208 }
00209
00210
00211 bool XMLHandler::fatalError( const QXmlParseException& exception )
00212 {
00213 errorProt += i18n( "fatal parsing error: %1 in line %2, column %3" )
00214 .arg( exception.message() )
00215 .arg( exception.lineNumber() )
00216 .arg( exception.columnNumber() );
00217
00218 errorLine = exception.lineNumber();
00219 errorCol = exception.columnNumber();
00220
00221 return false;
00222 }
00223
00224 bool XMLHandler::enterText()
00225 {
00226 NodeImpl *newNode = m_doc->document()->createTextNode("");
00227 if (m_currentNode->addChild(newNode)) {
00228 if (m_view && !newNode->attached())
00229 newNode->attach();
00230 m_currentNode = newNode;
00231 return true;
00232 }
00233 else {
00234 delete newNode;
00235 return false;
00236 }
00237 }
00238
00239 void XMLHandler::exitText()
00240 {
00241 NodeImpl* par = m_currentNode->parentNode();
00242 if (par != 0)
00243 m_currentNode = par;
00244 }
00245
00246 bool XMLHandler::attributeDecl(const QString &, const QString &, const QString &,
00247 const QString &, const QString &)
00248 {
00249
00250
00251 return true;
00252 }
00253
00254 bool XMLHandler::externalEntityDecl(const QString &, const QString &, const QString &)
00255 {
00256
00257 return true;
00258 }
00259
00260 bool XMLHandler::internalEntityDecl(const QString &name, const QString &value)
00261 {
00262 EntityImpl *e = new EntityImpl(m_doc,name);
00263
00264 e->addChild(m_doc->document()->createTextNode(new DOMStringImpl(value.unicode(), value.length())));
00265
00266
00267
00268 return true;
00269 }
00270
00271 bool XMLHandler::notationDecl(const QString &, const QString &, const QString &)
00272 {
00273
00274
00275
00276
00277
00278 return true;
00279 }
00280
00281 bool XMLHandler::unparsedEntityDecl(const QString &, const QString &,
00282 const QString &, const QString &)
00283 {
00284
00285 return true;
00286 }
00287
00288
00289
00290
00291 XMLTokenizer::XMLTokenizer(DOM::DocumentPtr *_doc, KHTMLView *_view)
00292 {
00293 m_doc = _doc;
00294 if ( m_doc ) m_doc->ref();
00295 m_view = _view;
00296 m_xmlCode = "";
00297 m_scriptsIt = 0;
00298 m_cachedScript = 0;
00299 }
00300
00301 XMLTokenizer::~XMLTokenizer()
00302 {
00303 if ( m_doc ) m_doc->deref();
00304 if (m_scriptsIt)
00305 delete m_scriptsIt;
00306 if (m_cachedScript)
00307 m_cachedScript->deref(this);
00308 }
00309
00310
00311 void XMLTokenizer::begin()
00312 {
00313 }
00314
00315 void XMLTokenizer::write( const QString &str, bool )
00316 {
00317 m_xmlCode += str;
00318 }
00319
00320 void XMLTokenizer::end()
00321 {
00322 emit finishedParsing();
00323 }
00324
00325 void XMLTokenizer::finish()
00326 {
00327
00328 XMLHandler handler(m_doc,m_view);
00329 QXmlInputSource source;
00330 source.setData(m_xmlCode);
00331 QXmlSimpleReader reader;
00332 reader.setContentHandler( &handler );
00333 reader.setLexicalHandler( &handler );
00334 reader.setErrorHandler( &handler );
00335 reader.setDeclHandler( &handler );
00336 reader.setDTDHandler( &handler );
00337 bool ok = reader.parse( source );
00338
00339 if (!ok) {
00340
00341
00342
00343
00344
00345
00346 int exceptioncode = 0;
00347 while (m_doc->document()->hasChildNodes())
00348 static_cast<NodeImpl*>(m_doc->document())->removeChild(m_doc->document()->firstChild(),exceptioncode);
00349
00350 QTextIStream stream(&m_xmlCode);
00351 unsigned long lineno;
00352 for (lineno = 0; lineno < handler.errorLine-1; lineno++)
00353 stream.readLine();
00354 QString line = stream.readLine();
00355
00356 unsigned long colno;
00357 QString errorLocPtr = "";
00358 for (colno = 0; colno < handler.errorCol-1; colno++)
00359 errorLocPtr += " ";
00360 errorLocPtr += "^";
00361
00362
00363 DocumentImpl *doc = m_doc->document();
00364 NodeImpl *html = doc->createElementNS(XHTML_NAMESPACE,"html");
00365 NodeImpl *body = doc->createElementNS(XHTML_NAMESPACE,"body");
00366 NodeImpl *h1 = doc->createElementNS(XHTML_NAMESPACE,"h1");
00367 NodeImpl *headingText = doc->createTextNode(i18n("XML parsing error"));
00368 NodeImpl *errorText = doc->createTextNode(handler.errorProtocol());
00369 NodeImpl *hr = doc->createElementNS(XHTML_NAMESPACE,"hr");
00370 NodeImpl *pre = doc->createElementNS(XHTML_NAMESPACE,"pre");
00371 NodeImpl *lineText = doc->createTextNode(line+"\n");
00372 NodeImpl *errorLocText = doc->createTextNode(errorLocPtr);
00373
00374
00375
00376 doc->appendChild(html,exceptioncode);
00377 html->appendChild(body,exceptioncode);
00378 body->appendChild(h1,exceptioncode);
00379 h1->appendChild(headingText,exceptioncode);
00380 body->appendChild(errorText,exceptioncode);
00381 body->appendChild(hr,exceptioncode);
00382 body->appendChild(pre,exceptioncode);
00383 pre->appendChild(lineText,exceptioncode);
00384 pre->appendChild(errorLocText,exceptioncode);
00385
00386
00387
00388 h1->renderer()->close();
00389 pre->renderer()->close();
00390 body->renderer()->close();
00391
00392 m_doc->document()->recalcStyle( NodeImpl::Inherit );
00393 m_doc->document()->updateRendering();
00394
00395 end();
00396 }
00397 else {
00398
00399
00400 addScripts(m_doc->document());
00401 m_scriptsIt = new QPtrListIterator<HTMLScriptElementImpl>(m_scripts);
00402 executeScripts();
00403 }
00404
00405 }
00406
00407 void XMLTokenizer::addScripts(NodeImpl *n)
00408 {
00409
00410
00411
00412 if (n->id() == ID_SCRIPT) {
00413 m_scripts.append(static_cast<HTMLScriptElementImpl*>(n));
00414 }
00415
00416 NodeImpl *child;
00417 for (child = n->firstChild(); child; child = child->nextSibling())
00418 addScripts(child);
00419 }
00420
00421 void XMLTokenizer::executeScripts()
00422 {
00423
00424
00425
00426
00427 while (m_scriptsIt->current()) {
00428 DOMString scriptSrc = m_scriptsIt->current()->getAttribute(ATTR_SRC);
00429 QString charset = m_scriptsIt->current()->getAttribute(ATTR_CHARSET).string();
00430
00431 if (scriptSrc != "") {
00432
00433 m_cachedScript = m_doc->document()->docLoader()->requestScript(scriptSrc, charset);
00434 ++(*m_scriptsIt);
00435 m_cachedScript->ref(this);
00436 return;
00437 }
00438 else {
00439
00440 QString scriptCode = "";
00441 NodeImpl *child;
00442 for (child = m_scriptsIt->current()->firstChild(); child; child = child->nextSibling()) {
00443 if ( ( child->nodeType() == Node::TEXT_NODE || child->nodeType() == Node::CDATA_SECTION_NODE) &&
00444 static_cast<TextImpl*>(child)->string() )
00445 scriptCode += QConstString(static_cast<TextImpl*>(child)->string()->s,
00446 static_cast<TextImpl*>(child)->string()->l).string();
00447 }
00448
00449
00450
00451
00452 if (m_view) {
00453 m_view->part()->executeScript(scriptCode);
00454 }
00455 ++(*m_scriptsIt);
00456 }
00457 }
00458
00459
00460
00461 m_doc->document()->updateStyleSelector();
00462
00463
00464 end();
00465 }
00466
00467 void XMLTokenizer::notifyFinished(CachedObject *finishedObj)
00468 {
00469
00470
00471
00472 if (finishedObj == m_cachedScript) {
00473 DOMString scriptSource = m_cachedScript->script();
00474 m_cachedScript->deref(this);
00475 m_cachedScript = 0;
00476 m_view->part()->executeScript(scriptSource.string());
00477 executeScripts();
00478 }
00479 }
00480
00481 #include "xml_tokenizer.moc"
00482