1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
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.
52 #ifndef Patternist_XsdSchemaParser_H
53 #define Patternist_XsdSchemaParser_H
55 #include <private/qnamespacesupport_p.h>
56 #include <private/qxsdalternative_p.h>
57 #include <private/qxsdattribute_p.h>
58 #include <private/qxsdattributegroup_p.h>
59 #include <private/qxsdattributeterm_p.h>
60 #include <private/qxsdcomplextype_p.h>
61 #include <private/qxsdelement_p.h>
62 #include <private/qxsdidcache_p.h>
63 #include <private/qxsdmodelgroup_p.h>
64 #include <private/qxsdnotation_p.h>
65 #include <private/qxsdsimpletype_p.h>
66 #include <private/qxsdschemacontext_p.h>
67 #include <private/qxsdschemaparsercontext_p.h>
68 #include <private/qxsdstatemachine_p.h>
70 #include <QtCore/QHash>
71 #include <QtCore/QSet>
72 #include <QtCore/QUrl>
73 #include <QtCore/QXmlStreamReader>
74 #include <QtXmlPatterns/QXmlNamePool>
83 * @short Implements the parsing of XML schema file.
85 * This class parses a XML schema in XML presentation from an QIODevice
86 * and returns object representation as XsdSchema.
88 * @ingroup Patternist_schema
89 * @author Tobias Koenig <tobias.koenig@nokia.com>
91 class XsdSchemaParser : public MaintainingReader<XsdSchemaToken, XsdTagScope::Type>
93 friend class ElementNamespaceHandler;
94 friend class TagValidationHandler;
106 * Creates a new schema parser object.
108 XsdSchemaParser(const XsdSchemaContext::Ptr &context, const XsdSchemaParserContext::Ptr &parserContext, QIODevice *device);
111 * Parses the XML schema file.
113 * @return @c true on success, @c false if the schema is somehow invalid.
115 bool parse(ParserType parserType = TopLevelParser);
118 * Describes a set of namespace URIs
120 typedef QSet<QUrl> NamespaceSet;
123 * Adds @p schemas to the list of already included schemas, so the parser
124 * can detect multiple includes of the same schema.
126 void addIncludedSchemas(const NamespaceSet &schemas);
129 * Sets which @p schemas have been included already, so the parser
130 * can detect multiple includes of the same schema.
132 void setIncludedSchemas(const NamespaceSet &schemas);
135 * Adds @p schemas to the list of already imported schemas, so the parser
136 * can detect multiple imports of the same schema.
138 void addImportedSchemas(const NamespaceSet &schemas);
141 * Sets which @p schemas have been imported already, so the parser
142 * can detect circular imports.
144 void setImportedSchemas(const NamespaceSet &schemas);
147 * Adds @p schemas to the list of already redefined schemas, so the parser
148 * can detect multiple redefines of the same schema.
150 void addRedefinedSchemas(const NamespaceSet &schemas);
153 * Sets which @p schemas have been redefined already, so the parser
154 * can detect multiple redefines of the same schema.
156 void setRedefinedSchemas(const NamespaceSet &schemas);
159 * Sets the target namespace of the schema to parse.
161 void setTargetNamespace(const QString &targetNamespace);
164 * Sets the document URI of the schema to parse.
166 void setDocumentURI(const QUrl &uri);
169 * Returns the document URI of the schema to parse.
171 QUrl documentURI() const;
174 * Reimplemented from MaintainingReader, always returns @c false.
176 bool isAnyAttributeAllowed() const;
180 * Used internally to report any kind of parsing error or
181 * schema inconsistency.
183 virtual void error(const QString &msg);
185 void attributeContentError(const char *attributeName, const char *elementName, const QString &value, const SchemaType::Ptr &type = SchemaType::Ptr());
188 * Sets the target namespace of the schema to parse.
190 void setTargetNamespaceExtended(const QString &targetNamespace);
193 * This method is called for parsing the top-level <em>schema</em> object.
195 void parseSchema(ParserType parserType);
198 * This method is called for parsing any top-level <em>include</em> object.
203 * This method is called for parsing any top-level <em>import</em> object.
208 * This method is called for parsing any top-level <em>redefine</em> object.
210 void parseRedefine();
213 * This method is called for parsing any <em>annotation</em> object everywhere
216 XsdAnnotation::Ptr parseAnnotation();
219 * This method is called for parsing an <em>appinfo</em> object as child of
220 * an <em>annotation</em> object.
222 XsdApplicationInformation::Ptr parseAppInfo();
225 * This method is called for parsing a <em>documentation</em> object as child of
226 * an <em>annotation</em> object.
228 XsdDocumentation::Ptr parseDocumentation();
231 * This method is called for parsing a <em>defaultOpenContent</em> object.
233 void parseDefaultOpenContent();
236 * This method is called for parsing any top-level <em>simpleType</em> object.
238 XsdSimpleType::Ptr parseGlobalSimpleType();
241 * This method is called for parsing any <em>simpleType</em> object as descendant
242 * of an <em>element</em> or <em>complexType</em> object.
244 XsdSimpleType::Ptr parseLocalSimpleType();
247 * This method is called for parsing a <em>restriction</em> object as child
248 * of a <em>simpleType</em> object.
250 void parseSimpleRestriction(const XsdSimpleType::Ptr &ptr);
253 * This method is called for parsing a <em>list</em> object as child
254 * of a <em>simpleType</em> object.
256 void parseList(const XsdSimpleType::Ptr &ptr);
259 * This method is called for parsing a <em>union</em> object as child
260 * of a <em>simpleType</em> object.
262 void parseUnion(const XsdSimpleType::Ptr &ptr);
265 * This method is called for parsing a <em>minExclusive</em> object as child
266 * of a <em>restriction</em> object.
268 XsdFacet::Ptr parseMinExclusiveFacet();
271 * This method is called for parsing a <em>minInclusive</em> object as child
272 * of a <em>restriction</em> object.
274 XsdFacet::Ptr parseMinInclusiveFacet();
277 * This method is called for parsing a <em>maxExclusive</em> object as child
278 * of a <em>restriction</em> object.
280 XsdFacet::Ptr parseMaxExclusiveFacet();
283 * This method is called for parsing a <em>maxInclusive</em> object as child
284 * of a <em>restriction</em> object.
286 XsdFacet::Ptr parseMaxInclusiveFacet();
289 * This method is called for parsing a <em>totalDigits</em> object as child
290 * of a <em>restriction</em> object.
292 XsdFacet::Ptr parseTotalDigitsFacet();
295 * This method is called for parsing a <em>fractionDigits</em> object as child
296 * of a <em>restriction</em> object.
298 XsdFacet::Ptr parseFractionDigitsFacet();
301 * This method is called for parsing a <em>length</em> object as child
302 * of a <em>restriction</em> object.
304 XsdFacet::Ptr parseLengthFacet();
307 * This method is called for parsing a <em>minLength</em> object as child
308 * of a <em>restriction</em> object.
310 XsdFacet::Ptr parseMinLengthFacet();
313 * This method is called for parsing a <em>maxLength</em> object as child
314 * of a <em>restriction</em> object.
316 XsdFacet::Ptr parseMaxLengthFacet();
319 * This method is called for parsing an <em>enumeration</em> object as child
320 * of a <em>restriction</em> object.
322 XsdFacet::Ptr parseEnumerationFacet();
325 * This method is called for parsing a <em>whiteSpace</em> object as child
326 * of a <em>restriction</em> object.
328 XsdFacet::Ptr parseWhiteSpaceFacet();
331 * This method is called for parsing a <em>pattern</em> object as child
332 * of a <em>restriction</em> object.
334 XsdFacet::Ptr parsePatternFacet();
337 * This method is called for parsing an <em>assertion</em> object as child
338 * of a <em>restriction</em> object.
340 XsdFacet::Ptr parseAssertionFacet();
343 * This method is called for parsing any top-level <em>complexType</em> object.
345 XsdComplexType::Ptr parseGlobalComplexType();
348 * This method is called for parsing any <em>complexType</em> object as descendant
349 * of an <em>element</em> object.
351 XsdComplexType::Ptr parseLocalComplexType();
354 * This method resolves the content type of the @p complexType for the given
355 * @p effectiveMixed value.
357 void resolveComplexContentType(const XsdComplexType::Ptr &complexType, bool effectiveMixed);
360 * This method is called for parsing a <em>simpleContent</em> object as child
361 * of a <em>complexType</em> object.
363 void parseSimpleContent(const XsdComplexType::Ptr &complexType);
366 * This method is called for parsing a <em>restriction</em> object as child
367 * of a <em>simpleContent</em> object.
369 void parseSimpleContentRestriction(const XsdComplexType::Ptr &complexType);
372 * This method is called for parsing an <em>extension</em> object as child
373 * of a <em>simpleContent</em> object.
375 void parseSimpleContentExtension(const XsdComplexType::Ptr &complexType);
378 * This method is called for parsing a <em>complexContent</em> object as child
379 * of a <em>complexType</em> object.
381 * @param complexType The complex type the complex content belongs to.
382 * @param mixed The output parameter for the mixed value.
384 void parseComplexContent(const XsdComplexType::Ptr &complexType, bool *mixed);
387 * This method is called for parsing a <em>restriction</em> object as child
388 * of a <em>complexContent</em> object.
390 void parseComplexContentRestriction(const XsdComplexType::Ptr &complexType);
393 * This method is called for parsing an <em>extension</em> object as child
394 * of a <em>complexContent</em> object.
396 void parseComplexContentExtension(const XsdComplexType::Ptr &complexType);
399 * This method is called for parsing an <em>assert</em> object as child
400 * of a <em>complexType</em> or parsing a <em>assertion</em> facet object as
401 * child of a <em>simpleType</em>.
403 * @param nodeName Either XsdSchemaToken::Assert or XsdSchemaToken::Assertion.
404 * @param tag Either XsdTagScope::Assert or XsdTagScope::Assertion.
406 XsdAssertion::Ptr parseAssertion(const XsdSchemaToken::NodeName &nodeName, const XsdTagScope::Type &tag);
409 * This method is called for parsing an <em>openContent</em> object.
411 XsdComplexType::OpenContent::Ptr parseOpenContent();
414 * This method is called for parsing a top-level <em>group</em> object.
416 XsdModelGroup::Ptr parseNamedGroup();
419 * This method is called for parsing a non-top-level <em>group</em> object
420 * that contains a <em>ref</em> attribute.
422 XsdTerm::Ptr parseReferredGroup(const XsdParticle::Ptr &particle);
425 * This method is called for parsing an <em>all</em> object as child
426 * of a top-level <em>group</em> object.
428 * @param parent The schema component the <em>all</em> object is part of.
430 XsdModelGroup::Ptr parseAll(const NamedSchemaComponent::Ptr &parent);
433 * This method is called for parsing an <em>all</em> object as descendant
434 * of a <em>complexType</em> object.
436 * @param particle The particle the <em>all</em> object belongs to.
437 * @param parent The schema component the <em>all</em> object is part of.
439 XsdModelGroup::Ptr parseLocalAll(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent);
442 * This method is called for parsing a <em>choice</em> object as child
443 * of a top-level <em>group</em> object.
445 * @param parent The schema component the <em>choice</em> object is part of.
447 XsdModelGroup::Ptr parseChoice(const NamedSchemaComponent::Ptr &parent);
450 * This method is called for parsing a <em>choice</em> object as descendant
451 * of a <em>complexType</em> object or a <em>choice</em> object.
453 * @param particle The particle the <em>choice</em> object belongs to.
454 * @param parent The schema component the <em>choice</em> object is part of.
456 XsdModelGroup::Ptr parseLocalChoice(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent);
459 * This method is called for parsing a <em>sequence</em> object as child
460 * of a top-level <em>group</em> object.
462 * @param parent The schema component the <em>sequence</em> object is part of.
464 XsdModelGroup::Ptr parseSequence(const NamedSchemaComponent::Ptr &parent);
467 * This method is called for parsing a <em>sequence</em> object as descendant
468 * of a <em>complexType</em> object or a <em>sequence</em> object.
470 * @param particle The particle the <em>sequence</em> object belongs to.
471 * @param parent The schema component the <em>sequence</em> object is part of.
473 XsdModelGroup::Ptr parseLocalSequence(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent);
476 * A helper method that parses the minOccurs and maxOccurs constraints for
477 * the given @p particle that has the given @p tagName.
479 bool parseMinMaxConstraint(const XsdParticle::Ptr &particle, const char* tagName);
482 * This method is called for parsing any top-level <em>attribute</em> object.
484 XsdAttribute::Ptr parseGlobalAttribute();
487 * This method is called for parsing any non-top-level <em>attribute</em> object as a
488 * descendant of a <em>complexType</em> object or an <em>attributeGroup</em> object.
490 * @param parent The parent component the <em>attribute</em> object is part of.
492 XsdAttributeUse::Ptr parseLocalAttribute(const NamedSchemaComponent::Ptr &parent);
495 * This method is called for parsing a top-level <em>attributeGroup</em> object.
497 XsdAttributeGroup::Ptr parseNamedAttributeGroup();
500 * This method is called for parsing a non-top-level <em>attributeGroup</em> object
501 * that contains a <em>ref</em> attribute.
503 XsdAttributeUse::Ptr parseReferredAttributeGroup();
506 * This method is called for parsing any top-level <em>element</em> object.
508 XsdElement::Ptr parseGlobalElement();
511 * This method is called for parsing any non-top-level <em>element</em> object as a
512 * descendant of a <em>complexType</em> object or a <em>group</em> object.
514 * @param particle The particle the <em>element</em> object belongs to.
515 * @param parent The parent component the <em>element</em> object is part of.
517 XsdTerm::Ptr parseLocalElement(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent);
520 * This method is called for parsing a <em>unique</em> object as child of an <em>element</em> object.
522 XsdIdentityConstraint::Ptr parseUnique();
525 * This method is called for parsing a <em>key</em> object as child of an <em>element</em> object.
527 XsdIdentityConstraint::Ptr parseKey();
530 * This method is called for parsing a <em>keyref</em> object as child of an <em>element</em> object.
532 XsdIdentityConstraint::Ptr parseKeyRef(const XsdElement::Ptr &element);
535 * This method is called for parsing a <em>selector</em> object as child of an <em>unique</em> object,
536 * <em>key</em> object or <em>keyref</em> object,
538 * @param ptr The identity constraint it belongs to.
540 void parseSelector(const XsdIdentityConstraint::Ptr &ptr);
543 * This method is called for parsing a <em>field</em> object as child of an <em>unique</em> object,
544 * <em>key</em> object or <em>keyref</em> object,
546 * @param ptr The identity constraint it belongs to.
548 void parseField(const XsdIdentityConstraint::Ptr &ptr);
551 * This method is called for parsing an <em>alternative</em> object inside an <em>element</em> object.
553 XsdAlternative::Ptr parseAlternative();
556 * This method is called for parsing a top-level <em>notation</em> object.
558 XsdNotation::Ptr parseNotation();
561 * This method is called for parsing an <em>any</em> object somewhere in
564 * @param particle The particle the <em>any</em> object belongs to.
566 XsdWildcard::Ptr parseAny(const XsdParticle::Ptr &particle);
569 * This method is called for parsing an <em>anyAttribute</em> object somewhere in
572 XsdWildcard::Ptr parseAnyAttribute();
575 * This method is called for parsing unknown object as descendant of the <em>annotation</em> object.
577 void parseUnknownDocumentation();
580 * This method is called for parsing unknown object in the schema.
585 * Returnes an source location for the current position.
587 QSourceLocation currentSourceLocation() const;
590 * Converts a @p qualified name into a QXmlName @p name and does some error handling.
592 void convertName(const QString &qualified, NamespaceSupport::NameType type, QXmlName &name);
595 * A helper method that reads in a 'name' attribute and checks it for syntactic errors.
597 inline QString readNameAttribute(const char *elementName);
600 * A helper method that reads in an attribute that contains an QName and
601 * checks it for syntactic errors.
603 inline QString readQNameAttribute(const QString &typeAttribute, const char *elementName);
606 * A helper method that reads in a namespace attribute and checks for syntactic errors.
608 inline QString readNamespaceAttribute(const QString &attributeName, const char *elementName);
611 * A helper method that reads the final attribute and does correct handling of schema default definitions.
613 inline SchemaType::DerivationConstraints readDerivationConstraintAttribute(const SchemaType::DerivationConstraints &allowedConstraints, const char *elementName);
616 * A helper method that reads the block attribute and does correct handling of schema default definitions.
618 inline NamedSchemaComponent::BlockingConstraints readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints &allowedConstraints, const char *elementName);
621 * A helper method that reads all components for a xpath expression for the current scope.
623 XsdXPathExpression::Ptr readXPathExpression(const char *elementName);
626 * Describes the type of XPath that is allowed by the readXPathAttribute method.
635 * A helper method that reads an attribute that represents a xpath query and does basic
638 QString readXPathAttribute(const QString &attributeName, XPathType type, const char *elementName);
641 * A helper method that reads in an "id" attribute, checks it for syntactic errors
642 * and tests whether a component with the same id has already been parsed.
644 inline void validateIdAttribute(const char *elementName);
647 * Adds an @p element to the schema and checks for duplicated entries.
649 void addElement(const XsdElement::Ptr &element);
652 * Adds an @p attribute to the schema and checks for duplicated entries.
654 void addAttribute(const XsdAttribute::Ptr &attribute);
657 * Adds a @p type to the schema and checks for duplicated entries.
659 void addType(const SchemaType::Ptr &type);
662 * Adds an anonymous @p type to the schema and checks for duplicated entries.
664 void addAnonymousType(const SchemaType::Ptr &type);
667 * Adds an attribute @p group to the schema and checks for duplicated entries.
669 void addAttributeGroup(const XsdAttributeGroup::Ptr &group);
672 * Adds an element @p group to the schema and checks for duplicated entries.
674 void addElementGroup(const XsdModelGroup::Ptr &group);
677 * Adds a @p notation to the schema and checks for duplicated entries.
679 void addNotation(const XsdNotation::Ptr ¬ation);
682 * Adds an identity @p constraint to the schema and checks for duplicated entries.
684 void addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint);
687 * Adds the @p facet to the list of @p facets for @p type and checks for duplicates.
689 void addFacet(const XsdFacet::Ptr &facet, XsdFacet::Hash &facets, const SchemaType::Ptr &type);
692 * Sets up the state machines for validating the right occurrence of xml elements.
694 void setupStateMachines();
697 * Sets up a list of names of known builtin types.
699 void setupBuiltinTypeNames();
702 * Checks whether the given @p tag is equal to the given @p token and
703 * the given @p namespaceToken is the XML Schema namespace.
705 inline bool isSchemaTag(XsdSchemaToken::NodeName tag, XsdSchemaToken::NodeName token, XsdSchemaToken::NodeName namespaceToken) const;
707 XsdSchemaContext::Ptr m_context;
708 XsdSchemaParserContext::Ptr m_parserContext;
709 NamePool::Ptr m_namePool;
710 NamespaceSupport m_namespaceSupport;
711 XsdSchemaResolver::Ptr m_schemaResolver;
712 XsdSchema::Ptr m_schema;
714 QString m_targetNamespace;
715 QString m_attributeFormDefault;
716 QString m_elementFormDefault;
717 QString m_blockDefault;
718 QString m_finalDefault;
719 QString m_xpathDefaultNamespace;
720 QXmlName m_defaultAttributes;
721 XsdComplexType::OpenContent::Ptr m_defaultOpenContent;
722 bool m_defaultOpenContentAppliesToEmpty;
724 NamespaceSet m_includedSchemas;
725 NamespaceSet m_importedSchemas;
726 NamespaceSet m_redefinedSchemas;
728 XsdIdCache::Ptr m_idCache;
729 QHash<XsdTagScope::Type, XsdStateMachine<XsdSchemaToken::NodeName> > m_stateMachines;
730 ComponentLocationHash m_componentLocationHash;
731 QSet<QXmlName> m_builtinTypeNames;