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