1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2015 The Qt Company Ltd. 4 ** Contact: http://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see http://www.qt.io/terms-conditions. For further 15 ** information use the contact form at http://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 2.1 or version 3 as published by the Free 20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and 21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the 22 ** following information to ensure the GNU Lesser General Public License 23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and 24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 25 ** 26 ** As a special exception, The Qt Company gives you certain additional 27 ** rights. These rights are described in The Qt Company LGPL Exception 28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 29 ** 30 ** GNU General Public License Usage 31 ** Alternatively, this file may be used under the terms of the GNU 32 ** General Public License version 3.0 as published by the Free Software 33 ** Foundation and appearing in the file LICENSE.GPL included in the 34 ** packaging of this file. Please review the following information to 35 ** ensure the GNU General Public License version 3.0 requirements will be 36 ** met: http://www.gnu.org/copyleft/gpl.html. 37 ** 38 ** $QT_END_LICENSE$ 39 ** 40 ****************************************************************************/ 41 42 // 43 // W A R N I N G 44 // ------------- 45 // 46 // This file is not part of the Qt API. It exists purely as an 47 // implementation detail. This header file may change from version to 48 // version without notice, or even be removed. 49 // 50 // We mean it. 51 52 #ifndef Patternist_XsdValidatingInstanceReader_H 53 #define Patternist_XsdValidatingInstanceReader_H 54 55 #include "qxsdidchelper_p.h" 56 #include "qxsdinstancereader_p.h" 57 #include "qxsdstatemachine_p.h" 58 #include "qxsdvalidatedxmlnodemodel_p.h" 59 60 #include <QtCore/QStack> 61 62 QT_BEGIN_HEADER 63 64 QT_BEGIN_NAMESPACE 65 66 class QXmlQuery; 67 68 namespace QPatternist 69 { 70 /** 71 * @short The validating schema instance reader. 72 * 73 * This class reads in a xml instance document from a QAbstractXmlNodeModel and 74 * validates it against a given xml schema. 75 * 76 * @ingroup Patternist_schema 77 * @author Tobias Koenig <tobias.koenig@nokia.com> 78 */ 79 class XsdValidatingInstanceReader : public XsdInstanceReader 80 { 81 public: 82 typedef QExplicitlySharedDataPointer<XsdValidatingInstanceReader> Ptr; 83 84 /** 85 * Creates a new validating instance reader that reads the data from 86 * the given @p model. 87 * 88 * @param model The model the data shall be read from. 89 * @param documentUri The uri of the document the model is from. 90 * @param context The context that is used to report errors etc. 91 */ 92 XsdValidatingInstanceReader(XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context); 93 94 /** 95 * Adds a new @p schema to the pool of schemas that shall be used 96 * for validation. 97 * The schema is located at the given @p url. 98 */ 99 void addSchema(const XsdSchema::Ptr &schema, const QUrl &url); 100 101 /** 102 * Reads and validates the instance document. 103 */ 104 bool read(); 105 106 private: 107 /** 108 * Loads a schema with the given @p targetNamespace from the given @p location 109 * and adds it to the pool of schemas that are used for validation. 110 * 111 * This method is used to load schemas defined in the xsi:schemaLocation or 112 * xsi:noNamespaceSchemaLocation attributes in the instance document. 113 */ 114 bool loadSchema(const QString &targetNamespace, const QUrl &location); 115 116 /** 117 * Reports an error via the report context. 118 */ 119 void error(const QString &msg) const; 120 121 /** 122 * Validates the current element tag of the instance document. 123 * 124 * @param hasStateMachine Used to remember whether this element represents the start tag 125 * of a complex type and therefor pushes a new state machine on the stack. 126 * @param element Used to remember which element has been validated in this step. 127 */ 128 bool validate(bool &hasStateMachine, XsdElement::Ptr &element); 129 130 /** 131 * Validates the current tag of the instance document against the given element @p declaration. 132 * 133 * @param declaration The element declaration to validate against. 134 * @param hasStateMachine Used to remember whether this element represents the start tag 135 * of a complex type and therefor pushes a new state machine on the stack. 136 */ 137 bool validateElement(const XsdElement::Ptr &declaration, bool &hasStateMachine); 138 139 /** 140 * Validates the current tag of the instance document against the given @p type of the element @p declaration. 141 * 142 * @param declaration The element declaration to validate against. 143 * @param type The type to validate against. 144 * @param isNilled Defines whether the element is nilled by the instance document. 145 * @param hasStateMachine Used to remember whether this element represents the start tag 146 * of a complex type and therefor pushes a new state machine on the stack. 147 * 148 * @note The @p type can differ from the element @p declaration type if the instance document has defined 149 * it via xsi:type attribute. 150 */ 151 bool validateElementType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine); 152 153 /** 154 * Validates the current tag of the instance document against the given simple @p type of the element @p declaration. 155 * 156 * @param declaration The element declaration to validate against. 157 * @param type The type to validate against. 158 * @param isNilled Defines whether the element is nilled by the instance document. 159 * 160 * @note The @p type can differ from the element @p declaration type if the instance document has defined 161 * it via xsi:type attribute. 162 */ 163 bool validateElementSimpleType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled); 164 165 /** 166 * Validates the current tag of the instance document against the given complex @p type of the element @p declaration. 167 * 168 * @param declaration The element declaration to validate against. 169 * @param type The type to validate against. 170 * @param isNilled Defines whether the element is nilled by the instance document. 171 * @param hasStateMachine Used to remember whether this element represents the start tag 172 * of a complex type and therefor pushes a new state machine on the stack. 173 * 174 * @note The @p type can differ from the element @p declaration type if the instance document has defined 175 * it via xsi:type attribute. 176 */ 177 bool validateElementComplexType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine); 178 179 /** 180 * Validates the given @p value against the attribute use @p declaration. 181 */ 182 bool validateAttribute(const XsdAttributeUse::Ptr &declaration, const QString &value); 183 184 /** 185 * Validates the given @p value against the attribute @p declaration. 186 */ 187 bool validateAttribute(const XsdAttribute::Ptr &declaration, const QString &value); 188 189 /** 190 * Validates the given @p attributeName against the @p wildcard. 191 */ 192 bool validateAttributeWildcard(const QXmlName &attributeName, const XsdWildcard::Ptr &wildcard); 193 194 /** 195 * Validates the identity constraints of an @p element. 196 */ 197 bool validateIdentityConstraint(const XsdElement::Ptr &element, const QXmlItem ¤tItem); 198 199 /** 200 * Validates the <em>unique</em> identity @p constraint of the @p element. 201 */ 202 bool validateUniqueIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet); 203 204 /** 205 * Validates the <em>key</em> identity @p constraint of the @p element. 206 */ 207 bool validateKeyIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &targetNodeSet, const TargetNode::Set &qualifiedNodeSet); 208 209 /** 210 * Validates the <em>keyref</em> identity @p constraint of the @p element. 211 */ 212 bool validateKeyRefIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet); 213 214 /** 215 * Selects two sets of nodes that match the given identity @p constraint. 216 * 217 * @param element The element the identity constraint belongs to. 218 * @param currentItem The current element that will be used as focus for the XQuery. 219 * @param constraint The constraint (selector and fields) that describe the two sets. 220 * @param targetNodeSet The target node set as defined by the schema specification. 221 * @param qualifiedNodeSet The qualified node set as defined by the schema specification. 222 */ 223 bool selectNodeSets(const XsdElement::Ptr &element, const QXmlItem ¤tItem, const XsdIdentityConstraint::Ptr &constraint, TargetNode::Set &targetNodeSet, TargetNode::Set &qualifiedNodeSet); 224 225 /** 226 * Creates an QXmlQuery object with the defined @p namespaceBindings that has the @p contextNode as focus 227 * and will execute @p query. 228 */ 229 QXmlQuery createXQuery(const QList<QXmlName> &namespaceBindings, const QXmlItem &contextNode, const QString &query) const; 230 231 /** 232 * Returns the element declaration with the given @p name from the pool of all schemas. 233 */ 234 XsdElement::Ptr elementByName(const QXmlName &name) const; 235 236 /** 237 * Returns the attribute declaration with the given @p name from the pool of all schemas. 238 */ 239 XsdAttribute::Ptr attributeByName(const QXmlName &name) const; 240 241 /** 242 * Returns the type declaration with the given @p name from the pool of all schemas. 243 */ 244 SchemaType::Ptr typeByName(const QXmlName &name) const; 245 246 /** 247 * Adds the ID/IDREF binding to the validated model and checks for duplicates. 248 */ 249 void addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding); 250 251 /** 252 * Helper method that reads an attribute of type xs:QName and does 253 * syntax checking. 254 */ 255 QString qNameAttribute(const QXmlName &attributeName); 256 257 /** 258 * Returns the xs:anyType that is used to build up the state machine. 259 * We need that as the BuiltinTypes::xsAnyType is not a XsdComplexType. 260 */ 261 XsdComplexType::Ptr anyType(); 262 263 /** 264 * Helper method that creates a state machine for the given @p particle 265 * and pushes it on the state machine stack. 266 */ 267 void createAndPushStateMachine(const XsdParticle::Ptr &particle); 268 269 typedef QHash<QUrl, QStringList> MergedSchemas; 270 typedef QHashIterator<QUrl, QStringList> MergedSchemasIterator; 271 272 XsdValidatedXmlNodeModel::Ptr m_model; 273 MergedSchemas m_mergedSchemas; 274 XsdSchema::Ptr m_schema; 275 const NamePool::Ptr m_namePool; 276 const QXmlName m_xsiNilName; 277 const QXmlName m_xsiTypeName; 278 const QXmlName m_xsiSchemaLocationName; 279 const QXmlName m_xsiNoNamespaceSchemaLocationName; 280 281 QStack<XsdStateMachine<XsdTerm::Ptr> > m_stateMachines; 282 QUrl m_documentUri; 283 XsdComplexType::Ptr m_anyType; 284 QSet<QString> m_processedNamespaces; 285 QSet<QString> m_processedSchemaLocations; 286 QSet<QString> m_idRefs; 287 QHash<QXmlName, TargetNode::Set> m_idcKeys; 288 SchemaType::Ptr m_idRefsType; 289 }; 290 } 291 292 QT_END_NAMESPACE 293 294 QT_END_HEADER 295 296 #endif 297