bbf8d9dea2583dfc031d69ba72d93cbf4cc06204
[profile/ivi/qtxmlpatterns.git] / src / xmlpatterns / api / qxmlschemavalidator.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qxmlschemavalidator.h"
43 #include "qxmlschemavalidator_p.h"
44
45 #include "qacceltreeresourceloader_p.h"
46 #include "qxmlschema.h"
47 #include "qxmlschema_p.h"
48 #include "qxsdvalidatinginstancereader_p.h"
49
50 #include <QtCore/QBuffer>
51 #include <QtCore/QIODevice>
52 #include <QtCore/QUrl>
53
54 QT_BEGIN_NAMESPACE
55
56 /*!
57   \class QXmlSchemaValidator
58
59   \brief The QXmlSchemaValidator class validates XML instance documents against a W3C XML Schema.
60
61   \reentrant
62   \since 4.6
63   \ingroup xml-tools
64   \inmodule QtXmlPatterns
65
66   The QXmlSchemaValidator class loads, parses an XML instance document and validates it
67   against a W3C XML Schema that has been compiled with \l{QXmlSchema}.
68
69   The following example shows how to load a XML Schema from a local
70   file, check whether it is a valid schema document and use it for validation
71   of an XML instance document:
72
73   \snippet qxmlschemavalidator/main.cpp 3
74
75   \section1 XML Schema Version
76
77   This class implements schema validation according to the \l{XML Schema} 1.0
78   specification.
79
80   \sa QXmlSchema, {xmlpatterns/schema}{XML Schema Validation Example}
81 */
82
83 /*!
84   Constructs a schema validator.
85   The schema used for validation must be referenced in the XML instance document
86   via the \c xsi:schemaLocation or \c xsi:noNamespaceSchemaLocation attribute.
87  */
88 QXmlSchemaValidator::QXmlSchemaValidator()
89     : d(new QXmlSchemaValidatorPrivate(QXmlSchema()))
90 {
91 }
92
93 /*!
94   Constructs a schema validator that will use \a schema for validation.
95   If an empty \l {QXmlSchema} schema is passed to the validator, the schema used
96   for validation must be referenced in the XML instance document
97   via the \c xsi:schemaLocation or \c xsi:noNamespaceSchemaLocation attribute.
98  */
99 QXmlSchemaValidator::QXmlSchemaValidator(const QXmlSchema &schema)
100     : d(new QXmlSchemaValidatorPrivate(schema))
101 {
102 }
103
104 /*!
105   Destroys this QXmlSchemaValidator.
106  */
107 QXmlSchemaValidator::~QXmlSchemaValidator()
108 {
109     delete d;
110 }
111
112 /*!
113   Sets the \a schema that shall be used for further validation.
114   If the schema is empty, the schema used for validation must be referenced
115   in the XML instance document via the \c xsi:schemaLocation or
116   \c xsi:noNamespaceSchemaLocation attribute.
117  */
118 void QXmlSchemaValidator::setSchema(const QXmlSchema &schema)
119 {
120     d->setSchema(schema);
121 }
122
123 /*!
124   Validates the XML instance document read from \a data with the
125   given \a documentUri against the schema.
126
127   Returns \c true if the XML instance document is valid according to the
128   schema, \c false otherwise.
129
130   Example:
131
132   \snippet qxmlschemavalidator/main.cpp 2
133  */
134 bool QXmlSchemaValidator::validate(const QByteArray &data, const QUrl &documentUri) const
135 {
136     QByteArray localData(data);
137
138     QBuffer buffer(&localData);
139     buffer.open(QIODevice::ReadOnly);
140
141     return validate(&buffer, documentUri);
142 }
143
144 /*!
145   Validates the XML instance document read from \a source against the schema.
146
147   Returns \c true if the XML instance document is valid according to the
148   schema, \c false otherwise.
149
150   Example:
151
152   \snippet qxmlschemavalidator/main.cpp 0
153  */
154 bool QXmlSchemaValidator::validate(const QUrl &source) const
155 {
156     d->m_context->setMessageHandler(messageHandler());
157     d->m_context->setUriResolver(uriResolver());
158     d->m_context->setNetworkAccessManager(networkAccessManager());
159
160     const QPatternist::AutoPtr<QNetworkReply> reply(QPatternist::AccelTreeResourceLoader::load(source, d->m_context->networkAccessManager(),
161                                                                                                d->m_context, QPatternist::AccelTreeResourceLoader::ContinueOnError));
162     if (reply)
163         return validate(reply.data(), source);
164     else
165         return false;
166 }
167
168 /*!
169   Validates the XML instance document read from \a source with the
170   given \a documentUri against the schema.
171
172   Returns \c true if the XML instance document is valid according to the
173   schema, \c false otherwise.
174
175   Example:
176
177   \snippet qxmlschemavalidator/main.cpp 1
178  */
179 bool QXmlSchemaValidator::validate(QIODevice *source, const QUrl &documentUri) const
180 {
181     if (!source) {
182         qWarning("A null QIODevice pointer cannot be passed.");
183         return false;
184     }
185
186     if (!source->isReadable()) {
187         qWarning("The device must be readable.");
188         return false;
189     }
190
191     const QUrl normalizedUri = QPatternist::XPathHelper::normalizeQueryURI(documentUri);
192
193     d->m_context->setMessageHandler(messageHandler());
194     d->m_context->setUriResolver(uriResolver());
195     d->m_context->setNetworkAccessManager(networkAccessManager());
196
197     QPatternist::NetworkAccessDelegator::Ptr delegator(new QPatternist::NetworkAccessDelegator(d->m_context->networkAccessManager(),
198                                                                                                d->m_context->networkAccessManager()));
199
200     QPatternist::AccelTreeResourceLoader loader(d->m_context->namePool(), delegator, QPatternist::AccelTreeBuilder<true>::SourceLocationsFeature);
201
202     QPatternist::Item item;
203     try {
204         item = loader.openDocument(source, normalizedUri, d->m_context);
205     } catch (QPatternist::Exception) {
206         return false;
207     }
208
209     const QAbstractXmlNodeModel *model = item.asNode().model();
210
211     QPatternist::XsdValidatedXmlNodeModel *validatedModel = new QPatternist::XsdValidatedXmlNodeModel(model);
212
213     QPatternist::XsdValidatingInstanceReader reader(validatedModel, normalizedUri, d->m_context);
214     if (d->m_schema)
215         reader.addSchema(d->m_schema, d->m_schemaDocumentUri);
216     try {
217         reader.read();
218     } catch (QPatternist::Exception) {
219         return false;
220     }
221
222     return true;
223 }
224
225 /*!
226   Returns the name pool used by this QXmlSchemaValidator for constructing \l
227   {QXmlName} {names}. There is no setter for the name pool, because
228   mixing name pools causes errors due to name confusion.
229  */
230 QXmlNamePool QXmlSchemaValidator::namePool() const
231 {
232     return d->m_namePool;
233 }
234
235 /*!
236   Returns the schema that is used for validation.
237  */
238 QXmlSchema QXmlSchemaValidator::schema() const
239 {
240     return d->m_originalSchema;
241 }
242
243 /*!
244   Changes the \l {QAbstractMessageHandler}{message handler} for this
245   QXmlSchemaValidator to \a handler. The schema validator sends all parsing and
246   validation messages to this message handler. QXmlSchemaValidator does not take
247   ownership of \a handler.
248
249   Normally, the default message handler is sufficient. It writes
250   compile and validation messages to \e stderr. The default message
251   handler includes color codes if \e stderr can render colors.
252
253   When QXmlSchemaValidator calls QAbstractMessageHandler::message(),
254   the arguments are as follows:
255
256   \table
257   \header
258     \li message() argument
259     \li Semantics
260   \row
261     \li QtMsgType type
262     \li Only QtWarningMsg and QtFatalMsg are used. The former
263        identifies a warning, while the latter identifies an error.
264   \row
265     \li const QString & description
266     \li An XHTML document which is the actual message. It is translated
267        into the current language.
268   \row
269     \li const QUrl &identifier
270     \li Identifies the error with a URI, where the fragment is
271        the error code, and the rest of the URI is the error namespace.
272   \row
273     \li const QSourceLocation & sourceLocation
274     \li Identifies where the error occurred.
275   \endtable
276
277  */
278 void QXmlSchemaValidator::setMessageHandler(QAbstractMessageHandler *handler)
279 {
280     d->m_userMessageHandler = handler;
281 }
282
283 /*!
284     Returns the message handler that handles parsing and validation
285     messages for this QXmlSchemaValidator.
286  */
287 QAbstractMessageHandler *QXmlSchemaValidator::messageHandler() const
288 {
289     if (d->m_userMessageHandler)
290         return d->m_userMessageHandler;
291
292     return d->m_messageHandler.data()->value;
293 }
294
295 /*!
296   Sets the URI resolver to \a resolver. QXmlSchemaValidator does not take
297   ownership of \a resolver.
298
299   \sa uriResolver()
300  */
301 void QXmlSchemaValidator::setUriResolver(const QAbstractUriResolver *resolver)
302 {
303     d->m_uriResolver = resolver;
304 }
305
306 /*!
307   Returns the schema's URI resolver. If no URI resolver has been set,
308   Qt XML Patterns will use the URIs in instance documents as they are.
309
310   The URI resolver provides a level of abstraction, or \e{polymorphic
311   URIs}. A resolver can rewrite \e{logical} URIs to physical ones, or
312   it can translate obsolete or invalid URIs to valid ones.
313
314   When Qt XML Patterns calls QAbstractUriResolver::resolve() the
315   absolute URI is the URI mandated by the schema specification, and the
316   relative URI is the URI specified by the user.
317
318   \sa setUriResolver()
319  */
320 const QAbstractUriResolver *QXmlSchemaValidator::uriResolver() const
321 {
322     return d->m_uriResolver;
323 }
324
325 /*!
326   Sets the network manager to \a manager.
327   QXmlSchemaValidator does not take ownership of \a manager.
328
329   \sa networkAccessManager()
330  */
331 void QXmlSchemaValidator::setNetworkAccessManager(QNetworkAccessManager *manager)
332 {
333     d->m_userNetworkAccessManager = manager;
334 }
335
336 /*!
337   Returns the network manager, or 0 if it has not been set.
338
339   \sa setNetworkAccessManager()
340  */
341 QNetworkAccessManager *QXmlSchemaValidator::networkAccessManager() const
342 {
343     if (d->m_userNetworkAccessManager)
344         return d->m_userNetworkAccessManager;
345
346     return d->m_networkAccessManager.data()->value;
347 }
348
349 QT_END_NAMESPACE