| /**************************************************************************** |
| ** |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** This file is part of the QtXmlPatterns module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** GNU Lesser General Public License Usage |
| ** This file may be used under the terms of the GNU Lesser General Public |
| ** License version 2.1 as published by the Free Software Foundation and |
| ** appearing in the file LICENSE.LGPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU Lesser |
| ** General Public License version 2.1 requirements will be met: |
| ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU General |
| ** Public License version 3.0 as published by the Free Software Foundation |
| ** and appearing in the file LICENSE.GPL included in the packaging of this |
| ** file. Please review the following information to ensure the GNU General |
| ** Public License version 3.0 requirements will be met: |
| ** http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** Other Usage |
| ** Alternatively, this file may be used in accordance with the terms and |
| ** conditions contained in a signed written agreement between you and Nokia. |
| ** |
| ** |
| ** |
| ** |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /** |
| * @file |
| * @short This file is included by qcastingplatform_p.h. |
| * If you need includes in this file, put them in CasttingPlatform.h, |
| * outside of the namespace. |
| */ |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| MaintainingReader<TokenLookupClass, LookupKey>::MaintainingReader(const typename ElementDescription<TokenLookupClass, LookupKey>::Hash &elementDescriptions, |
| const QSet<typename TokenLookupClass::NodeName> &standardAttributes, |
| const ReportContext::Ptr &context, |
| QIODevice *const queryDevice) : QXmlStreamReader(queryDevice) |
| , m_hasHandledStandardAttributes(false) |
| , m_context(context) |
| , m_elementDescriptions(elementDescriptions) |
| , m_standardAttributes(standardAttributes) |
| { |
| Q_ASSERT(m_context); |
| Q_ASSERT(!m_elementDescriptions.isEmpty()); |
| |
| /* We start with stripping. */ |
| m_stripWhitespace.push(true); |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| MaintainingReader<TokenLookupClass, LookupKey>::~MaintainingReader() |
| { |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| QSourceLocation MaintainingReader<TokenLookupClass, LookupKey>::currentLocation() const |
| { |
| return QSourceLocation(documentURI(), |
| lineNumber(), |
| columnNumber()); |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| QXmlStreamReader::TokenType MaintainingReader<TokenLookupClass, LookupKey>::readNext() |
| { |
| const TokenType retval = QXmlStreamReader::readNext(); |
| |
| switch(retval) |
| { |
| case StartElement: |
| { |
| m_currentElementName = TokenLookupClass::toToken(name()); |
| m_currentAttributes = attributes(); |
| m_hasHandledStandardAttributes = false; |
| |
| if(!m_currentAttributes.hasAttribute(QLatin1String("xml:space"))) |
| m_stripWhitespace.push(m_stripWhitespace.top()); |
| break; |
| } |
| case EndElement: |
| m_currentElementName = TokenLookupClass::toToken(name()); |
| m_stripWhitespace.pop(); |
| break; |
| default: |
| break; |
| } |
| |
| return retval; |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| bool MaintainingReader<TokenLookupClass, LookupKey>::isWhitespace() const |
| { |
| return QXmlStreamReader::isWhitespace() |
| || XPathHelper::isWhitespaceOnly(text()); |
| } |
| |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| void MaintainingReader<TokenLookupClass, LookupKey>::error(const QString &message, |
| const ReportContext::ErrorCode code) const |
| { |
| m_context->error(message, code, currentLocation()); |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| void MaintainingReader<TokenLookupClass, LookupKey>::warning(const QString &message) const |
| { |
| m_context->warning(message, currentLocation()); |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| typename TokenLookupClass::NodeName MaintainingReader<TokenLookupClass, LookupKey>::currentElementName() const |
| { |
| return m_currentElementName; |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| void MaintainingReader<TokenLookupClass, LookupKey>::validateElement(const LookupKey elementName) const |
| { |
| Q_ASSERT(tokenType() == QXmlStreamReader::StartElement); |
| |
| if(m_elementDescriptions.contains(elementName)) |
| { |
| // QHash::value breaks in Metrowerks Compiler |
| const ElementDescription<TokenLookupClass, LookupKey> &desc = *m_elementDescriptions.find(elementName); |
| const int attCount = m_currentAttributes.count(); |
| |
| QSet<typename TokenLookupClass::NodeName> encounteredXSLTAtts; |
| |
| for(int i = 0; i < attCount; ++i) |
| { |
| const QXmlStreamAttribute &attr = m_currentAttributes.at(i); |
| if(attr.namespaceUri().isEmpty()) |
| { |
| const typename TokenLookupClass::NodeName attrName(TokenLookupClass::toToken(attr.name())); |
| encounteredXSLTAtts.insert(attrName); |
| |
| if(!desc.requiredAttributes.contains(attrName) && |
| !desc.optionalAttributes.contains(attrName) && |
| !m_standardAttributes.contains(attrName) && |
| !isAnyAttributeAllowed()) |
| { |
| QString translationString; |
| |
| QList<typename TokenLookupClass::NodeName> all(desc.requiredAttributes.toList() + desc.optionalAttributes.toList()); |
| const int totalCount = all.count(); |
| QStringList allowed; |
| |
| for(int i = 0; i < totalCount; ++i) |
| allowed.append(QPatternist::formatKeyword(TokenLookupClass::toString(all.at(i)))); |
| |
| /* Note, we can't run toString() on attrName, because we're in this branch, |
| * the token lookup doesn't have the string(!).*/ |
| const QString stringedName(attr.name().toString()); |
| |
| if(totalCount == 0) |
| { |
| translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Only the standard attributes can appear.") |
| .arg(formatKeyword(stringedName), |
| formatKeyword(name())); |
| } |
| else if(totalCount == 1) |
| { |
| translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Only %3 is allowed, and the standard attributes.") |
| .arg(formatKeyword(stringedName), |
| formatKeyword(name()), |
| allowed.first()); |
| } |
| else if(totalCount == 1) |
| { |
| /* Note, allowed has already had formatKeyword() applied. */ |
| translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Allowed is %3, %4, and the standard attributes.") |
| .arg(formatKeyword(stringedName), |
| formatKeyword(name()), |
| allowed.first(), |
| allowed.last()); |
| } |
| else |
| { |
| /* Note, allowed has already had formatKeyword() applied. */ |
| translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Allowed is %3, and the standard attributes.") |
| .arg(formatKeyword(stringedName), |
| formatKeyword(name()), |
| allowed.join(QLatin1String(", "))); |
| } |
| |
| m_context->error(translationString, |
| ReportContext::XTSE0090, |
| currentLocation()); |
| } |
| } |
| else if(attr.namespaceUri() == namespaceUri()) |
| { |
| m_context->error(QtXmlPatterns::tr("XSL-T attributes on XSL-T elements must be in the null namespace, not in the XSL-T namespace which %1 is.") |
| .arg(formatKeyword(attr.name())), |
| ReportContext::XTSE0090, |
| currentLocation()); |
| } |
| /* Else, attributes in other namespaces are allowed, continue. */ |
| } |
| |
| const QSet<typename TokenLookupClass::NodeName> requiredButMissing(QSet<typename TokenLookupClass::NodeName>(desc.requiredAttributes).subtract(encounteredXSLTAtts)); |
| |
| if(!requiredButMissing.isEmpty()) |
| { |
| error(QtXmlPatterns::tr("The attribute %1 must appear on element %2.") |
| .arg(QPatternist::formatKeyword(TokenLookupClass::toString(*requiredButMissing.constBegin())), |
| formatKeyword(name())), |
| ReportContext::XTSE0010); |
| } |
| } |
| else |
| { |
| error(QtXmlPatterns::tr("The element with local name %1 does not exist in XSL-T.").arg(formatKeyword(name())), |
| ReportContext::XTSE0010); |
| } |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &namespaceURI, |
| const QString &localName) const |
| { |
| Q_ASSERT(tokenType() == QXmlStreamReader::StartElement); |
| return m_currentAttributes.hasAttribute(namespaceURI, localName); |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &localName) const |
| { |
| return hasAttribute(QString(), localName); |
| } |
| |
| template<typename TokenLookupClass, |
| typename LookupKey> |
| QString MaintainingReader<TokenLookupClass, LookupKey>::readAttribute(const QString &localName, |
| const QString &namespaceURI) const |
| { |
| Q_ASSERT(tokenType() == QXmlStreamReader::StartElement); |
| |
| Q_ASSERT_X(m_currentAttributes.hasAttribute(namespaceURI, localName), |
| Q_FUNC_INFO, |
| "Validation must be done before this function is called."); |
| |
| return m_currentAttributes.value(namespaceURI, localName).toString(); |
| } |
| |