📄 qxmlstream.cpp
字号:
/* uses namespaceForPrefix and builds the attribute vector */void QXmlStreamReaderPrivate::resolveTag(){ tagStack.top().namespaceDeclaration.namespaceUri = namespaceUri = namespaceForPrefix(prefix); int n = attributeStack.size(); attributes.resize(n); for (int i = 0; i < n; ++i) { QXmlStreamAttribute &attribute = attributes[i]; Attribute &attrib = attributeStack[i]; QStringRef prefix(symPrefix(attrib.key)); QStringRef name(symString(attrib.key)); QStringRef qualifiedName(symName(attrib.key)); QStringRef value(symString(attrib.value)); attribute.m_name = QXmlStreamStringRef(name); attribute.m_qualifiedName = QXmlStreamStringRef(qualifiedName); attribute.m_value = QXmlStreamStringRef(value); if (!prefix.isEmpty()) { QStringRef attributeNamespaceUri = namespaceForPrefix(prefix); attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri); } for (int j = 0; j < i; ++j) { if (attributes[j].name() == attribute.name() && attributes[j].namespaceUri() == attribute.namespaceUri() && (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName())) raiseWellFormedError(QXmlStream::tr("Attribute redefined.")); } } for (int a = 0; a < dtdAttributes.size(); ++a) { DtdAttribute &dtdAttribute = dtdAttributes[a]; if (dtdAttribute.defaultValue.isNull() || dtdAttribute.tagName != qualifiedName || dtdAttribute.attributeQualifiedName.isNull()) continue; int i = 0; while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName) ++i; if (i != n) continue; QXmlStreamAttribute attribute; attribute.m_name = QXmlStreamStringRef(dtdAttribute.attributeName); attribute.m_qualifiedName = QXmlStreamStringRef(dtdAttribute.attributeQualifiedName); attribute.m_value = QXmlStreamStringRef(dtdAttribute.defaultValue); if (!dtdAttribute.attributePrefix.isEmpty()) { QStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix); attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri); } attribute.m_isDefault = true; attributes.append(attribute); } attributeStack.clear();}void QXmlStreamReaderPrivate::resolvePublicNamespaces(){ const Tag &tag = tagStack.top(); int n = namespaceDeclarations.size() - tag.namespaceDeclarationsSize; publicNamespaceDeclarations.resize(n); for (int i = 0; i < n; ++i) { const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(tag.namespaceDeclarationsSize + i); QXmlStreamNamespaceDeclaration &publicNamespaceDeclaration = publicNamespaceDeclarations[i]; publicNamespaceDeclaration.m_prefix = QXmlStreamStringRef(namespaceDeclaration.prefix); publicNamespaceDeclaration.m_namespaceUri = QXmlStreamStringRef(namespaceDeclaration.namespaceUri); }}void QXmlStreamReaderPrivate::resolveDtd(){ publicNotationDeclarations.resize(notationDeclarations.size()); for (int i = 0; i < notationDeclarations.size(); ++i) { const QXmlStreamReaderPrivate::NotationDeclaration ¬ationDeclaration = notationDeclarations.at(i); QXmlStreamNotationDeclaration &publicNotationDeclaration = publicNotationDeclarations[i]; publicNotationDeclaration.m_name = QXmlStreamStringRef(notationDeclaration.name); publicNotationDeclaration.m_systemId = QXmlStreamStringRef(notationDeclaration.systemId); publicNotationDeclaration.m_publicId = QXmlStreamStringRef(notationDeclaration.publicId); } notationDeclarations.clear(); publicEntityDeclarations.resize(entityDeclarations.size()); for (int i = 0; i < entityDeclarations.size(); ++i) { const QXmlStreamReaderPrivate::EntityDeclaration &entityDeclaration = entityDeclarations.at(i); QXmlStreamEntityDeclaration &publicEntityDeclaration = publicEntityDeclarations[i]; publicEntityDeclaration.m_name = QXmlStreamStringRef(entityDeclaration.name); publicEntityDeclaration.m_notationName = QXmlStreamStringRef(entityDeclaration.notationName); publicEntityDeclaration.m_systemId = QXmlStreamStringRef(entityDeclaration.systemId); publicEntityDeclaration.m_publicId = QXmlStreamStringRef(entityDeclaration.publicId); publicEntityDeclaration.m_value = QXmlStreamStringRef(entityDeclaration.value); } entityDeclarations.clear(); parameterEntityHash.clear();}uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex){ bool ok = true; uint s; // ### add toXShort to QStringRef? if (sym(symbolIndex).c == 'x') s = symString(symbolIndex, 1).toString().toUInt(&ok, 16); else s = symString(symbolIndex).toString().toUInt(&ok, 10); ok &= (s == 0x9 || s == 0xa || s == 0xd || (s >= 0x20 && s <= 0xd7ff) || (s >= 0xe000 && s <= 0xfffd) || (s >= 0x10000 && s <= 0x10ffff)); return ok ? s : 0;}void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId){//#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] const ushort *data = reinterpret_cast<const ushort *>(publicId.constData()); uchar c = 0; int i; for (i = publicId.size() - 1; i >= 0; --i) { if (data[i] < 256) switch ((c = data[i])) { case ' ': case '\n': case '\r': case '-': case '(': case ')': case '+': case ',': case '.': case '/': case ':': case '=': case '?': case ';': case '!': case '*': case '#': case '@': case '$': case '_': case '%': case '\'': case '\"': continue; default: if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) continue; } break; } if (i >= 0) raiseWellFormedError(QXmlStream::tr("Unexpected character '%1' in public id literal.").arg(QChar(QLatin1Char(c))));}/* Checks whether the document starts with an xml declaration. If it does, this function returns true; otherwise it sets up everything for a synthetic start document event and returns false. */bool QXmlStreamReaderPrivate::checkStartDocument(){ hasCheckedStartDocument = true; if (scanString(spell[XML], XML)) return true; type = QXmlStreamReader::StartDocument; if (atEnd) { hasCheckedStartDocument = false; raiseError(QXmlStreamReader::PrematureEndOfDocumentError); } return false;}void QXmlStreamReaderPrivate::startDocument(const QStringRef &version){ QString err; if (version != QLatin1String("1.0")) { if (version.toString().contains(QLatin1Char(' '))) err = QXmlStream::tr("Invalid XML version string."); else err = QXmlStream::tr("Unsupported XML version."); } initTagStack(); int n = attributeStack.size(); /* We use this bool to ensure that the pesudo attributes are in the * proper order: * * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */ bool hasStandalone = false; for (int i = 0; err.isNull() && i < n; ++i) { Attribute &attrib = attributeStack[i]; QStringRef prefix(symPrefix(attrib.key)); QStringRef key(symString(attrib.key)); QStringRef value(symString(attrib.value)); if (prefix.isEmpty() && key == QLatin1String("encoding")) { const QString name(value.toString()); if(hasStandalone) err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding."); if(!QXmlUtils::isEncName(name)) err = QXmlStream::tr("%1 is an invalid encoding name.").arg(name); else {#ifdef QT_NO_TEXTCODEC readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);#else QTextCodec *const newCodec = QTextCodec::codecForName(name.toLatin1()); if (!newCodec) err = QXmlStream::tr("Encoding %1 is unsupported").arg(name); else if (newCodec != codec && !lockEncoding) { codec = newCodec; delete decoder; decoder = codec->makeDecoder(); decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread); }#endif // QT_NO_TEXTCODEC } } else if (prefix.isEmpty() && key == QLatin1String("standalone")) { hasStandalone = true; if (value == QLatin1String("yes")) standalone = true; else if (value == QLatin1String("no")) standalone = false; else err = QXmlStream::tr("Standalone accepts only yes or no."); } else { err = QXmlStream::tr("Invalid attribute in XML declaration."); } } if (!err.isNull()) raiseWellFormedError(err); attributeStack.clear();}void QXmlStreamReaderPrivate::raiseError(QXmlStreamReader::Error error, const QString& message){ this->error = error; errorString = message; if (errorString.isNull()) { if (error == QXmlStreamReader::PrematureEndOfDocumentError) errorString = QXmlStream::tr("Premature end of document."); else if (error == QXmlStreamReader::CustomError) errorString = QXmlStream::tr("Invalid document."); } type = QXmlStreamReader::Invalid;}void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message){ raiseError(QXmlStreamReader::NotWellFormedError, message);}void QXmlStreamReaderPrivate::parseError(){ if (token == EOF_SYMBOL) { raiseError(QXmlStreamReader::PrematureEndOfDocumentError); return; } const int nmax = 4; QString error_message; int ers = state_stack[tos]; int nexpected = 0; int expected[nmax]; if (token != ERROR) for (int tk = 0; tk < TERMINAL_COUNT; ++tk) { int k = t_action(ers, tk); if (k <= 0) continue; if (spell[tk]) { if (nexpected < nmax) expected[nexpected++] = tk; } } error_message.clear (); if (nexpected && nexpected < nmax) { bool first = true; for (int s = 0; s < nexpected; ++s) { if (first) error_message += QXmlStream::tr ("Expected "); else if (s == nexpected - 1) error_message += QLatin1String (nexpected > 2 ? ", or " : " or "); else error_message += QLatin1String (", "); first = false; error_message += QLatin1String("\'"); error_message += QLatin1String (spell [expected[s]]); error_message += QLatin1String("\'"); } error_message += QXmlStream::tr(", but got \'"); error_message += QLatin1String(spell [token]); error_message += QLatin1String("\'"); } else { error_message += QXmlStream::tr("Unexpected \'"); error_message += QLatin1String(spell [token]); error_message += QLatin1String("\'"); } error_message += QLatin1Char('.'); raiseWellFormedError(error_message);}void QXmlStreamReaderPrivate::resume(int rule) { resumeReduction = rule; if (error == QXmlStreamReader::NoError) raiseError(QXmlStreamReader::PrematureEndOfDocumentError);}/*! Returns the current line number, starting with 1.\sa columnNumber(), characterOffset() */qint64 QXmlStreamReader::lineNumber() const{ Q_D(const QXmlStreamReader); return d->lineNumber + 1; // in public we start with 1}/*! Returns the current column number, starting with 0.\sa lineNumber(), characterOffset() */qint64 QXmlStreamReader::columnNumber() const{ Q_D(const QXmlStreamReader); return d->characterOffset - d->lastLineStart + d->readBufferPos;}/*! Returns the current character offset, starting with 0.\sa lineNumber(), columnNumber()*/qint64 QXmlStreamReader::characterOffset() const{ Q_D(const QXmlStreamReader); return d->characterOffset + d->readBufferPos;}/*! Returns the text of \l Characters, \l Comment, \l DTD, or EntityReference. */QStringRef QXmlStreamReader::text() const{ Q_D(const QXmlStreamReader); return d->text;}/*! If the state() is \l DTD, this function returns the DTD's notation declarations. Otherwise an empty vector is returned. The QXmlStreamNotationDeclarations class is defined to be a QVector of QXmlStreamNotationDeclaration. */QXmlStreamNotationDeclarations QXmlStreamReader::notationDeclarations() const{ Q_D(const QXmlStreamReader); if (d->notationDeclarations.size()) const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd(); return d->publicNotationDeclarations;}/*! If the state() is \l DTD, this function returns the DTD's unparsed (external) entity declarations. Otherwise an empty vector is returned. The QXmlStreamEntityDeclarations class is defined to be a QVector of QXmlStreamEntityDeclaration. */QXmlStreamEntityDeclarations QXmlStreamReader::entityDeclarations() const{ Q_D(const QXmlStreamReader); if (d->entityDeclarations.size()) const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd(); return d->publicEntityDeclarations;}/*! If the state() is \l StartElement, this function returns the element's namespace declarations. Otherwise an empty vector is returned. The QXmlStreamNamespaceDeclaration class is defined to be a QVector of QXmlStreamNamespaceDeclaration. */QXmlStreamNamespaceDeclarations QXmlStreamReader::namespaceDeclarations() const{ Q_D(const QXmlStreamReader); if (d->publicNamespaceDeclarations.isEmpty() && d->type == StartElement) const_cast<QXmlStreamReaderPrivate *>(d)->resolvePublicNamespaces(); return d->publicNamespaceDeclarations;}/*! Convenience function to be called in case a StartElement was read. Reads until the corresponding EndElement and returns all text in-between. In case of no error, the token after having called this function is EndElement. The function concatenates text() when it reads either \l Characters or EntityReference tokens, but skips ProcessingInstruction and \l Comment. In case anything else is read before reaching EndElement, the function returns what it read so far and raises an UnexpectedElementError. If the current token is not StartElement, an empty string is returned. */QString QXmlStreamReader::readElementText(){ Q_D(QXmlStreamReader); if (isStartElement()) { QString result; forever { switch (readNext()) { case Characters: case EntityReference: result.insert(result.size(), d->text.unicode(), d->text.size()); break; case EndElement: return result; case ProcessingInstruction: case Comment: break; default: if (!d->error) d->raiseError(UnexpectedElementError, QXmlStream::tr("Expected character data.")); return result; } } } return QString();}/*! Raises a custom error with an optional error \a message. \sa error(), errorString() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -