📄 xml_tokenizer.cpp
字号:
m_cachedScript = m_doc->document()->docLoader()->requestScript(scriptSrc, charset);
++(*m_scriptsIt);
m_cachedScript->ref(this); // will call executeScripts() again if already cached
return;
}
else {
// no src attribute - execute from contents of tag
QString scriptCode = "";
NodeImpl *child;
for (child = m_scriptsIt->current()->firstChild(); child; child = child->nextSibling()) {
if (child->nodeType() == Node::TEXT_NODE || child->nodeType() == Node::CDATA_SECTION_NODE) {
scriptCode += static_cast<TextImpl*>(child)->data().string();
}
}
// the script cannot do document.write until we support incremental parsing
// ### handle the case where the script deletes the node or redirects to
// another page, etc. (also in notifyFinished())
// ### the script may add another script node after this one which should be executed
if (m_view) {
m_view->part()->executeScript(scriptCode);
}
++(*m_scriptsIt);
}
}
// All scripts have finished executing, so calculate the style for the document and close
// the last element
m_doc->document()->updateStyleSelector();
}
void XMLTokenizer::notifyFinished(CachedObject *finishedObj)
{
// This is called when a script has finished loading that was requested from executeScripts(). We execute
// the script, and then call executeScripts() again to continue iterating through the list of scripts in
// the document
if (finishedObj == m_cachedScript) {
DOMString scriptSource = m_cachedScript->script();
m_cachedScript->deref(this);
m_cachedScript = 0;
m_view->part()->executeScript(scriptSource.string());
executeScripts();
}
}
bool XMLTokenizer::isWaitingForScripts() const
{
return m_cachedScript != 0;
}
#ifdef KHTML_XSLT
void XMLTokenizer::setTransformSource(DocumentImpl* doc)
{
// Time to spin up a new parse and save the xmlDocPtr.
// 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 QChar BOM(0xFEFF);
const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char *>(&BOM);
xmlDocPtr sourceDoc = xmlReadMemory(reinterpret_cast<const char *>(m_xmlCode.unicode()),
m_xmlCode.length() * sizeof(QChar),
doc->URL().ascii(),
BOMHighByte == 0xFF ? "UTF-16LE" : "UTF-16BE",
XML_PARSE_NOCDATA|XML_PARSE_DTDATTR|XML_PARSE_NOENT);
doc->setTransformSource(sourceDoc);
}
#endif
Tokenizer *newXMLTokenizer(DocumentPtr *d, KHTMLView *v)
{
return new XMLTokenizer(d, v);
}
int XMLTokenizer::lineNumber() const
{
return m_context->input->line;
}
int XMLTokenizer::columnNumber() const
{
return m_context->input->col;
}
void XMLTokenizer::stopParsing()
{
xmlStopParser(m_context);
m_parserStopped = true;
}
#if 0
bool XMLHandler::attributeDecl(const QString &/*eName*/, const QString &/*aName*/, const QString &/*type*/,
const QString &/*valueDefault*/, const QString &/*value*/)
{
// qt's xml parser (as of 2.2.3) does not currently give us values for type, valueDefault and
// value. When it does, we can store these somewhere and have default attributes on elements
return true;
}
bool XMLHandler::externalEntityDecl(const QString &/*name*/, const QString &/*publicId*/, const QString &/*systemId*/)
{
// ### insert these too - is there anything special we have to do here?
return true;
}
bool XMLHandler::internalEntityDecl(const QString &name, const QString &value)
{
EntityImpl *e = new EntityImpl(m_doc,name);
// ### further parse entities inside the value and add them as separate nodes (or entityreferences)?
e->addChild(m_doc->document()->createTextNode(value));
// ### FIXME
// if (m_doc->document()->doctype())
// static_cast<GenericRONamedNodeMapImpl*>(m_doc->document()->doctype()->entities())->addNode(e);
return true;
}
bool XMLHandler::notationDecl(const QString &name, const QString &publicId, const QString &systemId)
{
// ### FIXME
// if (m_doc->document()->doctype()) {
// NotationImpl *n = new NotationImpl(m_doc,name,publicId,systemId);
// static_cast<GenericRONamedNodeMapImpl*>(m_doc->document()->doctype()->notations())->addNode(n);
// }
return true;
}
#endif
// --------------------------------
XMLNamespaceStack::~XMLNamespaceStack()
{
while (XMLNamespace *ns = m_namespaceStack.pop())
ns->deref();
}
void XMLNamespaceStack::popNamespaces()
{
XMLNamespace *ns = m_namespaceStack.pop();
if (ns)
ns->deref();
}
XMLNamespace *XMLNamespaceStack::pushNamespaces(XMLAttributes& attrs)
{
XMLNamespace *ns = m_namespaceStack.current();
if (!ns)
ns = new XMLNamespace;
// Search for any xmlns attributes.
for (int i = 0; i < attrs.length(); i++) {
QString qName = attrs.qName(i);
if (qName == "xmlns")
ns = new XMLNamespace(QString::null, attrs.value(i), ns);
else if (qName.startsWith("xmlns:"))
ns = new XMLNamespace(qName.right(qName.length()-6), attrs.value(i), ns);
}
m_namespaceStack.push(ns);
ns->ref();
return ns;
}
// --------------------------------
struct AttributeParseState {
QMap<QString, QString> attributes;
bool gotAttributes;
};
static void attributesStartElementHandler(void *userData, const xmlChar *name, const xmlChar **libxmlAttributes)
{
if (strcmp(reinterpret_cast<const char *>(name), "attrs") != 0) {
return;
}
AttributeParseState *state = static_cast<AttributeParseState *>(userData);
state->gotAttributes = true;
XMLAttributes attributes(reinterpret_cast<const char **>(libxmlAttributes));
XMLNamespaceStack stack;
attributes.split(stack.pushNamespaces(attributes));
int length = attributes.length();
for (int i = 0; i != length; ++i) {
state->attributes.insert(attributes.qName(i), attributes.value(i));
}
}
QMap<QString, QString> parseAttributes(const DOMString &string, bool &attrsOK)
{
AttributeParseState state;
state.gotAttributes = false;
xmlSAXHandler sax;
memset(&sax, 0, sizeof(sax));
sax.startElement = attributesStartElementHandler;
xmlParserCtxtPtr parser = createQStringParser(&sax, &state);
parseQString(parser, "<?xml version=\"1.0\"?><attrs " + string.string() + " />");
xmlFreeParserCtxt(parser);
attrsOK = state.gotAttributes;
return state.attributes;
}
// --------------------------------
XMLAttributes::XMLAttributes(const char **saxStyleAttributes)
: _ref(0), _uris(0)
{
int length = 0;
if (saxStyleAttributes) {
for (const char **p = saxStyleAttributes; *p; p += 2) {
++length;
}
}
_length = length;
if (!length) {
_names = 0;
_values = 0;
_uris = 0;
} else {
_names = new QString [length];
_values = new QString [length];
}
if (saxStyleAttributes) {
int i = 0;
for (const char **p = saxStyleAttributes; *p; p += 2) {
_names[i] = QString::fromUtf8(p[0]);
_values[i] = QString::fromUtf8(p[1]);
++i;
}
}
}
XMLAttributes::~XMLAttributes()
{
if (_ref && !--*_ref) {
delete _ref;
_ref = 0;
}
if (!_ref) {
delete [] _names;
delete [] _values;
delete [] _uris;
}
}
XMLAttributes::XMLAttributes(const XMLAttributes &other)
: _ref(other._ref)
, _length(other._length)
, _names(other._names)
, _values(other._values)
, _uris(other._uris)
{
if (!_ref) {
_ref = new int (2);
other._ref = _ref;
} else {
++*_ref;
}
}
XMLAttributes &XMLAttributes::operator=(const XMLAttributes &other)
{
if (_ref && !--*_ref) {
delete _ref;
_ref = 0;
}
if (!_ref) {
delete [] _names;
delete [] _values;
delete [] _uris;
}
_ref = other._ref;
_length = other._length;
_names = other._names;
_values = other._values;
_uris = other._uris;
if (!_ref) {
_ref = new int (2);
other._ref = _ref;
} else {
++*_ref;
}
return *this;
}
QString XMLAttributes::localName(int index) const
{
int colonPos = _names[index].find(':');
if (colonPos != -1)
// Peel off the prefix to return the localName.
return _names[index].right(_names[index].length() - colonPos - 1);
return _names[index];
}
QString XMLAttributes::value(const QString &name) const
{
for (int i = 0; i != _length; ++i) {
if (name == _names[i]) {
return _values[i];
}
}
return QString::null;
}
void XMLAttributes::split(XMLNamespace* ns)
{
for (int i = 0; i < _length; ++i) {
int colonPos = _names[i].find(':');
if (colonPos != -1) {
QString prefix = _names[i].left(colonPos);
QString uri;
if (prefix == "xmlns") {
// FIXME: The URI is the xmlns namespace? I seem to recall DOM lvl 3 saying something about this.
}
else
uri = ns->uriForPrefix(prefix);
if (!uri.isEmpty()) {
if (!_uris)
_uris = new QString[_length];
_uris[i] = uri;
}
}
}
}
}
#include "xml_tokenizer.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -