1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
44 * @short This file is included by qcastingplatform_p.h.
45 * If you need includes in this file, put them in CasttingPlatform.h,
46 * outside of the namespace.
49 template<typename TokenLookupClass,
51 MaintainingReader<TokenLookupClass, LookupKey>::MaintainingReader(const typename ElementDescription<TokenLookupClass, LookupKey>::Hash &elementDescriptions,
52 const QSet<typename TokenLookupClass::NodeName> &standardAttributes,
53 const ReportContext::Ptr &context,
54 QIODevice *const queryDevice) : QXmlStreamReader(queryDevice)
55 , m_hasHandledStandardAttributes(false)
57 , m_elementDescriptions(elementDescriptions)
58 , m_standardAttributes(standardAttributes)
61 Q_ASSERT(!m_elementDescriptions.isEmpty());
63 /* We start with stripping. */
64 m_stripWhitespace.push(true);
67 template<typename TokenLookupClass,
69 MaintainingReader<TokenLookupClass, LookupKey>::~MaintainingReader()
73 template<typename TokenLookupClass,
75 QSourceLocation MaintainingReader<TokenLookupClass, LookupKey>::currentLocation() const
77 return QSourceLocation(documentURI(),
82 template<typename TokenLookupClass,
84 QXmlStreamReader::TokenType MaintainingReader<TokenLookupClass, LookupKey>::readNext()
86 const TokenType retval = QXmlStreamReader::readNext();
92 m_currentElementName = TokenLookupClass::toToken(name());
93 m_currentAttributes = attributes();
94 m_hasHandledStandardAttributes = false;
96 if(!m_currentAttributes.hasAttribute(QLatin1String("xml:space")))
97 m_stripWhitespace.push(m_stripWhitespace.top());
101 m_currentElementName = TokenLookupClass::toToken(name());
102 m_stripWhitespace.pop();
111 template<typename TokenLookupClass,
113 bool MaintainingReader<TokenLookupClass, LookupKey>::isWhitespace() const
115 return QXmlStreamReader::isWhitespace()
116 || XPathHelper::isWhitespaceOnly(text());
120 template<typename TokenLookupClass,
122 void MaintainingReader<TokenLookupClass, LookupKey>::error(const QString &message,
123 const ReportContext::ErrorCode code) const
125 m_context->error(message, code, currentLocation());
128 template<typename TokenLookupClass,
130 void MaintainingReader<TokenLookupClass, LookupKey>::warning(const QString &message) const
132 m_context->warning(message, currentLocation());
135 template<typename TokenLookupClass,
137 typename TokenLookupClass::NodeName MaintainingReader<TokenLookupClass, LookupKey>::currentElementName() const
139 return m_currentElementName;
142 template<typename TokenLookupClass,
144 void MaintainingReader<TokenLookupClass, LookupKey>::validateElement(const LookupKey elementName) const
146 Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
148 if(m_elementDescriptions.contains(elementName))
150 // QHash::value breaks in Metrowerks Compiler
151 const ElementDescription<TokenLookupClass, LookupKey> &desc = *m_elementDescriptions.find(elementName);
152 const int attCount = m_currentAttributes.count();
154 QSet<typename TokenLookupClass::NodeName> encounteredXSLTAtts;
156 for(int i = 0; i < attCount; ++i)
158 const QXmlStreamAttribute &attr = m_currentAttributes.at(i);
159 if(attr.namespaceUri().isEmpty())
161 const typename TokenLookupClass::NodeName attrName(TokenLookupClass::toToken(attr.name()));
162 encounteredXSLTAtts.insert(attrName);
164 if(!desc.requiredAttributes.contains(attrName) &&
165 !desc.optionalAttributes.contains(attrName) &&
166 !m_standardAttributes.contains(attrName) &&
167 !isAnyAttributeAllowed())
169 QString translationString;
171 QList<typename TokenLookupClass::NodeName> all(desc.requiredAttributes.toList() + desc.optionalAttributes.toList());
172 const int totalCount = all.count();
175 for(int i = 0; i < totalCount; ++i)
176 allowed.append(QPatternist::formatKeyword(TokenLookupClass::toString(all.at(i))));
178 /* Note, we can't run toString() on attrName, because we're in this branch,
179 * the token lookup doesn't have the string(!).*/
180 const QString stringedName(attr.name().toString());
184 translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Only the standard attributes can appear.")
185 .arg(formatKeyword(stringedName),
186 formatKeyword(name()));
188 else if(totalCount == 1)
190 translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Only %3 is allowed, and the standard attributes.")
191 .arg(formatKeyword(stringedName),
192 formatKeyword(name()),
195 else if(totalCount == 1)
197 /* Note, allowed has already had formatKeyword() applied. */
198 translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Allowed is %3, %4, and the standard attributes.")
199 .arg(formatKeyword(stringedName),
200 formatKeyword(name()),
206 /* Note, allowed has already had formatKeyword() applied. */
207 translationString = QtXmlPatterns::tr("Attribute %1 cannot appear on the element %2. Allowed is %3, and the standard attributes.")
208 .arg(formatKeyword(stringedName),
209 formatKeyword(name()),
210 allowed.join(QLatin1String(", ")));
213 m_context->error(translationString,
214 ReportContext::XTSE0090,
218 else if(attr.namespaceUri() == namespaceUri())
220 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.")
221 .arg(formatKeyword(attr.name())),
222 ReportContext::XTSE0090,
225 /* Else, attributes in other namespaces are allowed, continue. */
228 const QSet<typename TokenLookupClass::NodeName> requiredButMissing(QSet<typename TokenLookupClass::NodeName>(desc.requiredAttributes).subtract(encounteredXSLTAtts));
230 if(!requiredButMissing.isEmpty())
232 error(QtXmlPatterns::tr("The attribute %1 must appear on element %2.")
233 .arg(QPatternist::formatKeyword(TokenLookupClass::toString(*requiredButMissing.constBegin())),
234 formatKeyword(name())),
235 ReportContext::XTSE0010);
240 error(QtXmlPatterns::tr("The element with local name %1 does not exist in XSL-T.").arg(formatKeyword(name())),
241 ReportContext::XTSE0010);
245 template<typename TokenLookupClass,
247 bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &namespaceURI,
248 const QString &localName) const
250 Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
251 return m_currentAttributes.hasAttribute(namespaceURI, localName);
254 template<typename TokenLookupClass,
256 bool MaintainingReader<TokenLookupClass, LookupKey>::hasAttribute(const QString &localName) const
258 return hasAttribute(QString(), localName);
261 template<typename TokenLookupClass,
263 QString MaintainingReader<TokenLookupClass, LookupKey>::readAttribute(const QString &localName,
264 const QString &namespaceURI) const
266 Q_ASSERT(tokenType() == QXmlStreamReader::StartElement);
268 Q_ASSERT_X(m_currentAttributes.hasAttribute(namespaceURI, localName),
270 "Validation must be done before this function is called.");
272 return m_currentAttributes.value(namespaceURI, localName).toString();