📄 dom_xmlimpl.cpp
字号:
/**
* This file is part of the DOM implementation for KDE.
*
* Copyright (C) 2000 Peter Kelly (pmk@post.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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "dom/dom_exception.h"
#include "xml/dom_xmlimpl.h"
#include "xml/dom_docimpl.h"
#include "xml/dom_stringimpl.h"
#include "css/css_stylesheetimpl.h"
#ifdef KHTML_XSLT
#include "xsl_stylesheetimpl.h"
#endif
#include "misc/loader.h"
#include "xml/xml_tokenizer.h"
using khtml::parseAttributes;
namespace DOM {
EntityImpl::EntityImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
{
m_publicId = 0;
m_systemId = 0;
m_notationName = 0;
m_name = 0;
}
EntityImpl::EntityImpl(DocumentPtr *doc, DOMString _name) : NodeBaseImpl(doc)
{
m_publicId = 0;
m_systemId = 0;
m_notationName = 0;
m_name = _name.implementation();
if (m_name)
m_name->ref();
}
EntityImpl::EntityImpl(DocumentPtr *doc, DOMString _publicId, DOMString _systemId, DOMString _notationName) : NodeBaseImpl(doc)
{
m_publicId = _publicId.implementation();
if (m_publicId)
m_publicId->ref();
m_systemId = _systemId.implementation();
if (m_systemId)
m_systemId->ref();
m_notationName = _notationName.implementation();
if (m_notationName)
m_notationName->ref();
m_name = 0;
}
EntityImpl::~EntityImpl()
{
if (m_publicId)
m_publicId->deref();
if (m_systemId)
m_systemId->deref();
if (m_notationName)
m_notationName->deref();
if (m_name)
m_name->deref();
}
DOMString EntityImpl::publicId() const
{
return m_publicId;
}
DOMString EntityImpl::systemId() const
{
return m_systemId;
}
DOMString EntityImpl::notationName() const
{
return m_notationName;
}
DOMString EntityImpl::nodeName() const
{
return m_name;
}
unsigned short EntityImpl::nodeType() const
{
return Node::ENTITY_NODE;
}
NodeImpl *EntityImpl::cloneNode ( bool /*deep*/)
{
// Spec says cloning Document nodes is "implementation dependent"
// so we do not support it...
return 0;
}
// DOM Section 1.1.1
bool EntityImpl::childTypeAllowed( unsigned short type )
{
switch (type) {
case Node::ELEMENT_NODE:
case Node::PROCESSING_INSTRUCTION_NODE:
case Node::COMMENT_NODE:
case Node::TEXT_NODE:
case Node::CDATA_SECTION_NODE:
case Node::ENTITY_REFERENCE_NODE:
return true;
break;
default:
return false;
}
}
DOMString EntityImpl::toString() const
{
DOMString result = "<!ENTITY' ";
if (m_name && m_name->l != 0) {
result += " ";
result += m_name;
}
if (m_publicId && m_publicId->l != 0) {
result += " PUBLIC \"";
result += m_publicId;
result += "\" \"";
result += m_systemId;
result += "\"";
} else if (m_systemId && m_systemId->l != 0) {
result += " SYSTEM \"";
result += m_systemId;
result += "\"";
}
if (m_notationName && m_notationName->l != 0) {
result += " NDATA ";
result += m_notationName;
}
result += ">";
return result;
}
// -------------------------------------------------------------------------
EntityReferenceImpl::EntityReferenceImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
{
m_entityName = 0;
}
EntityReferenceImpl::EntityReferenceImpl(DocumentPtr *doc, DOMStringImpl *_entityName) : NodeBaseImpl(doc)
{
m_entityName = _entityName;
if (m_entityName)
m_entityName->ref();
}
EntityReferenceImpl::~EntityReferenceImpl()
{
if (m_entityName)
m_entityName->deref();
}
DOMString EntityReferenceImpl::nodeName() const
{
return m_entityName;
}
unsigned short EntityReferenceImpl::nodeType() const
{
return Node::ENTITY_REFERENCE_NODE;
}
NodeImpl *EntityReferenceImpl::cloneNode ( bool deep )
{
EntityReferenceImpl *clone = new EntityReferenceImpl(docPtr(),m_entityName);
// ### make sure children are readonly
// ### since we are a reference, should we clone children anyway (even if not deep?)
if (deep)
cloneChildNodes(clone);
return clone;
}
// DOM Section 1.1.1
bool EntityReferenceImpl::childTypeAllowed( unsigned short type )
{
switch (type) {
case Node::ELEMENT_NODE:
case Node::PROCESSING_INSTRUCTION_NODE:
case Node::COMMENT_NODE:
case Node::TEXT_NODE:
case Node::CDATA_SECTION_NODE:
case Node::ENTITY_REFERENCE_NODE:
return true;
break;
default:
return false;
}
}
DOMString EntityReferenceImpl::toString() const
{
DOMString result = "&";
result += m_entityName;
result += ";";
return result;
}
// -------------------------------------------------------------------------
NotationImpl::NotationImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
{
m_publicId = 0;
m_systemId = 0;
m_name = 0;
}
NotationImpl::NotationImpl(DocumentPtr *doc, DOMString _name, DOMString _publicId, DOMString _systemId) : NodeBaseImpl(doc)
{
m_name = _name.implementation();
if (m_name)
m_name->ref();
m_publicId = _publicId.implementation();
if (m_publicId)
m_publicId->ref();
m_systemId = _systemId.implementation();
if (m_systemId)
m_systemId->ref();
}
NotationImpl::~NotationImpl()
{
if (m_name)
m_name->deref();
if (m_publicId)
m_publicId->deref();
if (m_systemId)
m_systemId->deref();
}
DOMString NotationImpl::publicId() const
{
return m_publicId;
}
DOMString NotationImpl::systemId() const
{
return m_systemId;
}
DOMString NotationImpl::nodeName() const
{
return m_name;
}
unsigned short NotationImpl::nodeType() const
{
return Node::NOTATION_NODE;
}
NodeImpl *NotationImpl::cloneNode ( bool /*deep*/)
{
// Spec says cloning Document nodes is "implementation dependent"
// so we do not support it...
return 0;
}
// DOM Section 1.1.1
bool NotationImpl::childTypeAllowed( unsigned short /*type*/ )
{
return false;
}
// -------------------------------------------------------------------------
// ### need a way of updating these properly whenever child nodes of the processing instruction
// change or are added/removed
ProcessingInstructionImpl::ProcessingInstructionImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
{
m_target = 0;
m_data = 0;
m_localHref = 0;
m_sheet = 0;
m_cachedSheet = 0;
m_loading = false;
#ifdef KHTML_XSLT
m_isXSL = false;
#endif
}
ProcessingInstructionImpl::ProcessingInstructionImpl(DocumentPtr *doc, DOMString _target, DOMString _data) : NodeBaseImpl(doc)
{
m_target = _target.implementation();
if (m_target)
m_target->ref();
m_data = _data.implementation();
if (m_data)
m_data->ref();
m_sheet = 0;
m_cachedSheet = 0;
m_localHref = 0;
#ifdef KHTML_XSLT
m_isXSL = false;
#endif
}
ProcessingInstructionImpl::~ProcessingInstructionImpl()
{
if (m_target)
m_target->deref();
if (m_data)
m_data->deref();
if (m_cachedSheet)
m_cachedSheet->deref(this);
if (m_sheet)
m_sheet->deref();
}
DOMString ProcessingInstructionImpl::target() const
{
return m_target;
}
DOMString ProcessingInstructionImpl::data() const
{
return m_data;
}
void ProcessingInstructionImpl::setData( const DOMString &_data, int &exceptioncode )
{
// NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
if (isReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return;
}
if (m_data)
m_data->deref();
m_data = _data.implementation();
if (m_data)
m_data->ref();
}
DOMString ProcessingInstructionImpl::nodeName() const
{
return m_target;
}
unsigned short ProcessingInstructionImpl::nodeType() const
{
return Node::PROCESSING_INSTRUCTION_NODE;
}
DOMString ProcessingInstructionImpl::nodeValue() const
{
return m_data;
}
void ProcessingInstructionImpl::setNodeValue( const DOMString &_nodeValue, int &exceptioncode )
{
// NO_MODIFICATION_ALLOWED_ERR: taken care of by setData()
setData(_nodeValue, exceptioncode);
}
NodeImpl *ProcessingInstructionImpl::cloneNode ( bool /*deep*/)
{
// ### copy m_localHref
return new ProcessingInstructionImpl(docPtr(),m_target,m_data);
}
DOMString ProcessingInstructionImpl::localHref() const
{
return m_localHref;
}
// DOM Section 1.1.1
bool ProcessingInstructionImpl::childTypeAllowed( unsigned short /*type*/ )
{
return false;
}
bool ProcessingInstructionImpl::checkStyleSheet()
{
if (m_target && DOMString(m_target) == "xml-stylesheet") {
// see http://www.w3.org/TR/xml-stylesheet/
// ### check that this occurs only in the prolog
// ### support stylesheet included in a fragment of this (or another) document
// ### make sure this gets called when adding from javascript
bool attrsOk;
const QMap<QString, QString> attrs = parseAttributes(m_data, attrsOk);
if (!attrsOk)
return true;
QMap<QString, QString>::ConstIterator i = attrs.find("type");
QString type;
if (i != attrs.end())
type = *i;
bool isCSS = type.isEmpty() || type == "text/css";
#ifdef KHTML_XSLT
m_isXSL = (type == "text/xml" || type == "text/xsl" || type == "application/xml" ||
type == "application/xhtml+xml" || type == "application/rss+xml" || type == "application/atom=xml");
if (!isCSS && !m_isXSL)
#else
if (!isCSS)
#endif
return true;
#ifdef KHTML_XSLT
if (m_isXSL)
getDocument()->tokenizer()->setTransformSource(getDocument());
#endif
i = attrs.find("href");
QString href;
if (i != attrs.end())
href = *i;
if (href.length()>1)
{
if (href[0]=='#')
{
DOMString newLocalHref = href.mid(1);
if (m_localHref)
m_localHref->deref();
m_localHref = newLocalHref.implementation();
if (m_localHref)
m_localHref->ref();
#ifdef KHTML_XSLT
// We need to make a synthetic XSLStyleSheetImpl that is embedded. It needs to be able
// to kick off import/include loads that can hang off some parent sheet.
if (m_isXSL) {
if (m_sheet)
m_sheet->deref();
XSLStyleSheetImpl* localSheet = new XSLStyleSheetImpl(this, m_localHref, true);
localSheet->setDocument((xmlDocPtr)getDocument()->transformSource());
localSheet->ref();
localSheet->loadChildSheets();
m_sheet = localSheet;
m_loading = false;
}
return !m_isXSL;
#endif
}
else
{
// ### some validation on the URL?
// ### FIXME charset
if (getDocument()->part()) {
m_loading = true;
if (m_cachedSheet) m_cachedSheet->deref(this);
#ifdef KHTML_XSLT
if (m_isXSL)
m_cachedSheet = getDocument()->docLoader()->requestXSLStyleSheet(getDocument()->completeURL(href));
else
#endif
m_cachedSheet = getDocument()->docLoader()->requestStyleSheet(getDocument()->completeURL(href), QString::null);
if (m_cachedSheet) {
getDocument()->addPendingSheet();
m_cachedSheet->ref( this );
}
else
m_loading = false;
#ifdef KHTML_XSLT
return !m_isXSL;
#endif
}
}
}
}
return true;
}
StyleSheetImpl* ProcessingInstructionImpl::sheet() const
{
return m_sheet;
}
bool ProcessingInstructionImpl::isLoading() const
{
if (m_loading)
return true;
if (!m_sheet)
return false;
return m_sheet->isLoading();
}
void ProcessingInstructionImpl::sheetLoaded()
{
if (!isLoading())
getDocument()->stylesheetLoaded();
}
void ProcessingInstructionImpl::setStyleSheet(const DOMString &url, const DOMString &sheet)
{
if (m_sheet)
m_sheet->deref();
#ifdef KHTML_XSLT
if (m_isXSL)
m_sheet = new XSLStyleSheetImpl(this, url);
else
#endif
m_sheet = new CSSStyleSheetImpl(this, url);
m_sheet->ref();
m_sheet->parseString(sheet);
if (m_cachedSheet)
m_cachedSheet->deref(this);
m_cachedSheet = 0;
m_loading = false;
// Tell the doc about the sheet.
if (!isLoading() && m_sheet)
getDocument()->stylesheetLoaded();
}
void ProcessingInstructionImpl::setStyleSheet(CSSStyleSheetImpl* sheet)
{
if (m_sheet)
m_sheet->deref();
m_sheet = sheet;
if (m_sheet)
m_sheet->ref();
}
DOMString ProcessingInstructionImpl::toString() const
{
DOMString result = "<?";
result += m_target;
result += " ";
result += m_data;
result += ">";
return result;
}
} // namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -