1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://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 https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://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 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qxsdschemaparser_p.h"
41 
42 #include "private/qxmlutils_p.h"
43 #include "qacceltreeresourceloader_p.h"
44 #include "qautoptr_p.h"
45 #include "qboolean_p.h"
46 #include "qcommonnamespaces_p.h"
47 #include "qderivedinteger_p.h"
48 #include "qderivedstring_p.h"
49 #include "qqnamevalue_p.h"
50 #include "qxmlquery_p.h"
51 #include "qxpathhelper_p.h"
52 #include "qxsdattributereference_p.h"
53 #include "qxsdreference_p.h"
54 #include "qxsdschematoken_p.h"
55 
56 #include <QtCore/QFile>
57 #include <QtXmlPatterns/QXmlQuery>
58 
59 QT_BEGIN_NAMESPACE
60 
61 /**
62  * @page schema_overview Overview
63  * @section structure_and_components Structure and Components
64  *
65  * The schema validator code consists of 4 major components
66  *
67  * <dl>
68  *  <dt>The schema parser (QPatternist::XsdSchemaParser)</dt>
69  *  <dd>This component parses a XML document that is supplied via a QIODevice. It creates
70  *      a so called (incomplete) 'compiled schema', which is a representation of the XML Schema
71  *      structure as C++ objects.
72  *      As the parser is a streaming parser, it can't resolve references to types or elements/attributes
73  *      in place, therefore it creates resolver tasks which are passed to the schema resolver component
74  *      for resolving at a later point in time.
75  *      The parser does furthermore the basic XML structure constraint checking, e.g. if all required
76  *      attributes are available or the order of the elements is correct.</dd>
77  *
78  *  <dt>The schema resolver (QPatternist::XsdSchemaResolver)</dt>
79  *  <dd>This component is activated after the schema parser component has been finished the parsing
80  *      of all schemas. The resolver has been supplied with resolve tasks by the schema parser that
81  *      it will resolve in this step now. Between working on the single resolver tasks, the resolver
82  *      calls check methods from the schema checker component to make sure that some assertions are
83  *      valid (e.g. no circular inheritance of types), so that the resolver can work without hassle.
84  *      During resoving references to attribute or element groups it also checks for circular references
85  *      of these groups.
86  *      At the end of that phase we have a compiled schema that is fully resolved (not necessarily valid though).</dd>
87  *
88  *  <dt>The schema checker (QPatternist::XsdSchemaChecker)</dt>
89  *  <dd>This component does all the schema constraint checking as given by the Schema specification.
90  *      At the end of that phase we have fully resolved and valid compiled schema that can be used for validation
91  *      of instance documents.</dd>
92  *
93  *  <dt>The validator (QPatternist::XsdValidatingInstanceReader)</dt>
94  *  <dd>This component is responsible for validating a XML instance document, provided via a QIODevice, against
95  *      a valid compiled schema.</dd>
96  * </dl>
97  *
98  * @ingroup Patternist_schema
99  */
100 
101 using namespace QPatternist;
102 
103 namespace QPatternist
104 {
105 
106 /**
107  * @short A helper class for automatically handling namespace scopes of elements.
108  *
109  * This class should be instantiated at the beginning of each parse XYZ method.
110  */
111 class ElementNamespaceHandler
112 {
113     public:
114         /**
115          * Creates a new element namespace handler object.
116          *
117          * It checks whether the @p parser is on the right @p tag and it creates a new namespace
118          * context that contains the inherited and local namespace declarations.
119          */
ElementNamespaceHandler(const XsdSchemaToken::NodeName & tag,XsdSchemaParser * parser)120         ElementNamespaceHandler(const XsdSchemaToken::NodeName &tag, XsdSchemaParser *parser)
121             : m_parser(parser)
122         {
123             Q_ASSERT(m_parser->isStartElement() && (XsdSchemaToken::toToken(m_parser->name()) == tag) && (XsdSchemaToken::toToken(m_parser->namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI));
124             Q_UNUSED(tag)
125             m_parser->m_namespaceSupport.pushContext();
126             m_parser->m_namespaceSupport.setPrefixes(m_parser->namespaceDeclarations());
127         }
128 
129         /**
130          * Destroys the element namespace handler object.
131          *
132          * It destroys the local namespace context.
133          */
~ElementNamespaceHandler()134         ~ElementNamespaceHandler()
135         {
136             m_parser->m_namespaceSupport.popContext();
137         }
138 
139     private:
140         XsdSchemaParser *m_parser;
141 };
142 
143 /**
144  * A helper class that checks for the right occurrence of
145  * xml tags with the help of a DFA.
146  */
147 class TagValidationHandler
148 {
149     public:
TagValidationHandler(XsdTagScope::Type tag,XsdSchemaParser * parser,const NamePool::Ptr & namePool)150         TagValidationHandler(XsdTagScope::Type tag, XsdSchemaParser *parser, const NamePool::Ptr &namePool)
151             : m_parser(parser), m_machine(namePool)
152         {
153             Q_ASSERT(m_parser->m_stateMachines.contains(tag));
154 
155             m_machine = m_parser->m_stateMachines.value(tag);
156             m_machine.reset();
157         }
158 
validate(XsdSchemaToken::NodeName token)159         void validate(XsdSchemaToken::NodeName token)
160         {
161             if (token == XsdSchemaToken::NoKeyword) {
162                 const QList<XsdSchemaToken::NodeName> tokens = m_machine.possibleTransitions();
163 
164                 QStringList elementNames;
165                 for (int i = 0; i < tokens.count(); ++i)
166                     elementNames.append(formatElement(XsdSchemaToken::toString(tokens.at(i))));
167 
168                 m_parser->error(QtXmlPatterns::tr("Can not process unknown element %1, expected elements are: %2.")
169                                                  .arg(formatElement(m_parser->name().toString()))
170                                                  .arg(elementNames.join(QLatin1String(", "))));
171                 return;
172             }
173 
174             if (!m_machine.proceed(token)) {
175                 const QList<XsdSchemaToken::NodeName> tokens = m_machine.possibleTransitions();
176 
177                 QStringList elementNames;
178                 for (int i = 0; i < tokens.count(); ++i)
179                     elementNames.append(formatElement(XsdSchemaToken::toString(tokens.at(i))));
180 
181                 m_parser->error(QtXmlPatterns::tr("Element %1 is not allowed in this scope, possible elements are: %2.")
182                                                  .arg(formatElement(XsdSchemaToken::toString(token)))
183                                                  .arg(elementNames.join(QLatin1String(", "))));
184                 return;
185             }
186         }
187 
finalize() const188         void finalize() const
189         {
190             if (!m_machine.inEndState()) {
191                 const QList<XsdSchemaToken::NodeName> tokens = m_machine.possibleTransitions();
192 
193                 QStringList elementNames;
194                 for (int i = 0; i < tokens.count(); ++i)
195                     elementNames.append(formatElement(XsdSchemaToken::toString(tokens.at(i))));
196 
197                 m_parser->error(QtXmlPatterns::tr("Child element is missing in that scope, possible child elements are: %1.")
198                                                  .arg(elementNames.join(QLatin1String(", "))));
199             }
200         }
201 
202         private:
203             XsdSchemaParser *m_parser;
204             XsdStateMachine<XsdSchemaToken::NodeName> m_machine;
205 };
206 
207 }
208 
209 /**
210  * Returns a list of all particles with group references that appear at any level of
211  * the given unresolved @p group.
212  */
collectGroupRef(const XsdModelGroup::Ptr & group)213 static XsdParticle::List collectGroupRef(const XsdModelGroup::Ptr &group)
214 {
215     XsdParticle::List refParticles;
216 
217     XsdParticle::List particles = group->particles();
218     for (int i = 0; i < particles.count(); ++i) {
219         if (particles.at(i)->term()->isReference()) {
220             const XsdReference::Ptr reference(particles.at(i)->term());
221             if (reference->type() == XsdReference::ModelGroup)
222                 refParticles.append(particles.at(i));
223         }
224         if (particles.at(i)->term()->isModelGroup()) {
225             refParticles << collectGroupRef(XsdModelGroup::Ptr(particles.at(i)->term()));
226         }
227     }
228 
229     return refParticles;
230 }
231 
232 /**
233  * Helper function that works around the limited facilities of
234  * QUrl/AnyURI::fromLexical to detect invalid URIs
235  */
isValidUri(const QString & string)236 inline static bool isValidUri(const QString &string)
237 {
238     // an empty URI points to the current document as defined in RFC 2396 (4.2)
239     if (string.isEmpty())
240         return true;
241 
242     // explicit check as that is not checked by the code below
243     if (string.startsWith(QLatin1String("##")))
244         return false;
245 
246     const AnyURI::Ptr uri = AnyURI::fromLexical(string);
247     return (!(uri->hasError()));
248 }
249 
XsdSchemaParser(const XsdSchemaContext::Ptr & context,const XsdSchemaParserContext::Ptr & parserContext,QIODevice * device)250 XsdSchemaParser::XsdSchemaParser(const XsdSchemaContext::Ptr &context, const XsdSchemaParserContext::Ptr &parserContext, QIODevice *device)
251     : MaintainingReader<XsdSchemaToken, XsdTagScope::Type>(parserContext->elementDescriptions(), QSet<XsdSchemaToken::NodeName>(), context, device)
252     , m_context(context)
253     , m_parserContext(parserContext)
254     , m_namePool(m_parserContext->namePool())
255     , m_namespaceSupport(m_namePool)
256     , m_defaultOpenContentAppliesToEmpty(false)
257 {
258     m_schema = m_parserContext->schema();
259     m_schemaResolver = m_parserContext->resolver();
260     m_idCache = XsdIdCache::Ptr(new XsdIdCache());
261 
262     setupStateMachines();
263     setupBuiltinTypeNames();
264 }
265 
addIncludedSchemas(const NamespaceSet & schemas)266 void XsdSchemaParser::addIncludedSchemas(const NamespaceSet &schemas)
267 {
268     m_includedSchemas += schemas;
269 }
270 
setIncludedSchemas(const NamespaceSet & schemas)271 void XsdSchemaParser::setIncludedSchemas(const NamespaceSet &schemas)
272 {
273     m_includedSchemas = schemas;
274 }
275 
addImportedSchemas(const NamespaceSet & schemas)276 void XsdSchemaParser::addImportedSchemas(const NamespaceSet &schemas)
277 {
278     m_importedSchemas += schemas;
279 }
280 
setImportedSchemas(const NamespaceSet & schemas)281 void XsdSchemaParser::setImportedSchemas(const NamespaceSet &schemas)
282 {
283     m_importedSchemas = schemas;
284 }
285 
addRedefinedSchemas(const NamespaceSet & schemas)286 void XsdSchemaParser::addRedefinedSchemas(const NamespaceSet &schemas)
287 {
288     m_redefinedSchemas += schemas;
289 }
290 
setRedefinedSchemas(const NamespaceSet & schemas)291 void XsdSchemaParser::setRedefinedSchemas(const NamespaceSet &schemas)
292 {
293     m_redefinedSchemas = schemas;
294 }
295 
setTargetNamespace(const QString & targetNamespace)296 void XsdSchemaParser::setTargetNamespace(const QString &targetNamespace)
297 {
298     m_targetNamespace = targetNamespace;
299 }
300 
setTargetNamespaceExtended(const QString & targetNamespace)301 void XsdSchemaParser::setTargetNamespaceExtended(const QString &targetNamespace)
302 {
303     m_targetNamespace = targetNamespace;
304     m_namespaceSupport.setTargetNamespace(m_namePool->allocateNamespace(m_targetNamespace));
305 }
306 
setDocumentURI(const QUrl & uri)307 void XsdSchemaParser::setDocumentURI(const QUrl &uri)
308 {
309     m_documentURI = uri;
310 
311     // prevent to get included/imported/redefined twice
312     m_includedSchemas.insert(uri);
313     m_importedSchemas.insert(uri);
314     m_redefinedSchemas.insert(uri);
315 }
316 
documentURI() const317 QUrl XsdSchemaParser::documentURI() const
318 {
319     return m_documentURI;
320 }
321 
isAnyAttributeAllowed() const322 bool XsdSchemaParser::isAnyAttributeAllowed() const
323 {
324     return false;
325 }
326 
parse(ParserType parserType)327 bool XsdSchemaParser::parse(ParserType parserType)
328 {
329     m_componentLocationHash.clear();
330 
331     while (!atEnd()) {
332         readNext();
333 
334         if (isStartElement()) {
335             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
336             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
337 
338             if (isSchemaTag(XsdSchemaToken::Schema, token, namespaceToken)) {
339                 parseSchema(parserType);
340             } else {
341                 error(QtXmlPatterns::tr("Document is not a XML schema."));
342             }
343         }
344     }
345 
346     m_schemaResolver->addComponentLocationHash(m_componentLocationHash);
347     m_schemaResolver->setDefaultOpenContent(m_defaultOpenContent, m_defaultOpenContentAppliesToEmpty);
348 
349     if (QXmlStreamReader::error() != QXmlStreamReader::NoError)
350         error(errorString());
351 
352     return true;
353 }
354 
error(const QString & msg)355 void XsdSchemaParser::error(const QString &msg)
356 {
357     MaintainingReader<XsdSchemaToken, XsdTagScope::Type>::error(msg, XsdSchemaContext::XSDError);
358 }
359 
attributeContentError(const char * attributeName,const char * elementName,const QString & value,const SchemaType::Ptr & type)360 void XsdSchemaParser::attributeContentError(const char *attributeName, const char *elementName, const QString &value, const SchemaType::Ptr &type)
361 {
362     if (type) {
363         error(QtXmlPatterns::tr("%1 attribute of %2 element contains invalid content: {%3} is not a value of type %4.")
364                                .arg(formatAttribute(attributeName))
365                                .arg(formatElement(elementName))
366                                .arg(formatData(value))
367                                .arg(formatType(m_namePool, type)));
368     } else {
369         error(QtXmlPatterns::tr("%1 attribute of %2 element contains invalid content: {%3}.")
370                                .arg(formatAttribute(attributeName))
371                                .arg(formatElement(elementName))
372                                .arg(formatData(value)));
373     }
374 }
375 
parseSchema(ParserType parserType)376 void XsdSchemaParser::parseSchema(ParserType parserType)
377 {
378     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Schema, this);
379 
380     validateElement(XsdTagScope::Schema);
381 
382     // parse attributes
383 
384     if (parserType == TopLevelParser) {
385         if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
386             m_targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
387         }
388     } else if (parserType == IncludeParser) {
389         // m_targetNamespace is set to the target namespace of the including schema at this point
390 
391         if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
392             const QString targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
393 
394             if (m_targetNamespace != targetNamespace) {
395                 error(QtXmlPatterns::tr("Target namespace %1 of included schema is different from the target namespace %2 as defined by the including schema.")
396                                        .arg(formatURI(targetNamespace)).arg(formatURI(m_targetNamespace)));
397                 return;
398             }
399         }
400     } else if (parserType == ImportParser) {
401         // m_targetNamespace is set to the target namespace from the namespace attribute of the <import> tag at this point
402 
403         QString targetNamespace;
404         if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
405             targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
406         }
407 
408         if (m_targetNamespace != targetNamespace) {
409             error(QtXmlPatterns::tr("Target namespace %1 of imported schema is different from the target namespace %2 as defined by the importing schema.")
410                                    .arg(formatURI(targetNamespace)).arg(formatURI(m_targetNamespace)));
411             return;
412         }
413     } else if (parserType == RedefineParser) {
414         // m_targetNamespace is set to the target namespace of the redefining schema at this point
415 
416         if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
417             const QString targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
418 
419             if (m_targetNamespace != targetNamespace) {
420                 error(QtXmlPatterns::tr("Target namespace %1 of imported schema is different from the target namespace %2 as defined by the importing schema.")
421                                        .arg(formatURI(targetNamespace)).arg(formatURI(m_targetNamespace)));
422                 return;
423             }
424         }
425     }
426 
427     if (hasAttribute(QString::fromLatin1("attributeFormDefault"))) {
428         const QString value = readAttribute(QString::fromLatin1("attributeFormDefault"));
429         if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
430             attributeContentError("attributeFormDefault", "schema", value);
431             return;
432         }
433 
434         m_attributeFormDefault = value;
435     } else {
436         m_attributeFormDefault = QString::fromLatin1("unqualified");
437     }
438 
439     if (hasAttribute(QString::fromLatin1("elementFormDefault"))) {
440         const QString value = readAttribute(QString::fromLatin1("elementFormDefault"));
441         if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
442             attributeContentError("elementFormDefault", "schema", value);
443             return;
444         }
445 
446         m_elementFormDefault = value;
447     } else {
448         m_elementFormDefault = QString::fromLatin1("unqualified");
449     }
450 
451     if (hasAttribute(QString::fromLatin1("blockDefault"))) {
452         const QString blockDefault = readAttribute(QString::fromLatin1("blockDefault"));
453         const QStringList blockDefaultList = blockDefault.split(QLatin1Char(' '), Qt::SkipEmptyParts);
454         for (int i = 0; i < blockDefaultList.count(); ++i) {
455             const QString value = blockDefaultList.at(i);
456             if (value != QString::fromLatin1("#all") &&
457                 value != QString::fromLatin1("extension") &&
458                 value != QString::fromLatin1("restriction") &&
459                 value != QString::fromLatin1("substitution")) {
460                 attributeContentError("blockDefault", "schema", value);
461                 return;
462             }
463         }
464 
465         m_blockDefault = blockDefault;
466     }
467 
468     if (hasAttribute(QString::fromLatin1("finalDefault"))) {
469         const QString finalDefault = readAttribute(QString::fromLatin1("finalDefault"));
470         const QStringList finalDefaultList = finalDefault.split(QLatin1Char(' '), Qt::SkipEmptyParts);
471         for (int i = 0; i < finalDefaultList.count(); ++i) {
472             const QString value = finalDefaultList.at(i);
473             if (value != QString::fromLatin1("#all") &&
474                 value != QString::fromLatin1("extension") &&
475                 value != QString::fromLatin1("restriction") &&
476                 value != QString::fromLatin1("list") &&
477                 value != QString::fromLatin1("union")) {
478                 attributeContentError("finalDefault", "schema", value);
479                 return;
480             }
481         }
482 
483         m_finalDefault = finalDefault;
484     }
485 
486     if (hasAttribute(QString::fromLatin1("xpathDefaultNamespace"))) {
487         const QString xpathDefaultNamespace = readAttribute(QString::fromLatin1("xpathDefaultNamespace"));
488         if (xpathDefaultNamespace != QString::fromLatin1("##defaultNamespace") &&
489             xpathDefaultNamespace != QString::fromLatin1("##targetNamespace") &&
490             xpathDefaultNamespace != QString::fromLatin1("##local")) {
491             if (!isValidUri(xpathDefaultNamespace)) {
492                 attributeContentError("xpathDefaultNamespace", "schema", xpathDefaultNamespace);
493                 return;
494             }
495         }
496         m_xpathDefaultNamespace = xpathDefaultNamespace;
497     } else {
498         m_xpathDefaultNamespace = QString::fromLatin1("##local");
499     }
500 
501     if (hasAttribute(QString::fromLatin1("defaultAttributes"))) {
502         const QString attrGroupName = readQNameAttribute(QString::fromLatin1("defaultAttributes"), "schema");
503         convertName(attrGroupName, NamespaceSupport::ElementName, m_defaultAttributes); // translate qualified name into QXmlName
504     }
505 
506     if (hasAttribute(QString::fromLatin1("version"))) {
507         const QString version = readAttribute(QString::fromLatin1("version"));
508     }
509 
510     if (hasAttribute(CommonNamespaces::XML, QString::fromLatin1("lang"))) {
511         const QString value = readAttribute(QString::fromLatin1("lang"), CommonNamespaces::XML);
512 
513         QRegExp exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*"));
514         if (!exp.exactMatch(value)) {
515             attributeContentError("xml:lang", "schema", value);
516             return;
517         }
518     }
519 
520     validateIdAttribute("schema");
521 
522     TagValidationHandler tagValidator(XsdTagScope::Schema, this, m_namePool);
523 
524     while (!atEnd()) {
525         readNext();
526 
527         if (isEndElement())
528             break;
529 
530         if (isStartElement()) {
531             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
532             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
533 
534             tagValidator.validate(token);
535 
536             if (isSchemaTag(XsdSchemaToken::Include, token, namespaceToken)) {
537                 parseInclude();
538             } else if (isSchemaTag(XsdSchemaToken::Import, token, namespaceToken)) {
539                 parseImport();
540             } else if (isSchemaTag(XsdSchemaToken::Redefine, token, namespaceToken)) {
541                 parseRedefine();
542             } else if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
543                 const XsdAnnotation::Ptr annotation = parseAnnotation();
544                 m_schema->addAnnotation(annotation);
545             } else if (isSchemaTag(XsdSchemaToken::DefaultOpenContent, token, namespaceToken)) {
546                 parseDefaultOpenContent();
547             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
548                 const XsdSimpleType::Ptr type = parseGlobalSimpleType();
549                 addType(type);
550             } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
551                 const XsdComplexType::Ptr type = parseGlobalComplexType();
552                 addType(type);
553             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
554                 const XsdModelGroup::Ptr group = parseNamedGroup();
555                 addElementGroup(group);
556             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
557                 XsdAttributeGroup::Ptr attributeGroup = parseNamedAttributeGroup();
558                 addAttributeGroup(attributeGroup);
559             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
560                 const XsdElement::Ptr element = parseGlobalElement();
561                 addElement(element);
562             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
563                 const XsdAttribute::Ptr attribute = parseGlobalAttribute();
564                 addAttribute(attribute);
565             } else if (isSchemaTag(XsdSchemaToken::Notation, token, namespaceToken)) {
566                 const XsdNotation::Ptr notation = parseNotation();
567                 addNotation(notation);
568             } else {
569                 parseUnknown();
570             }
571         }
572     }
573 
574     tagValidator.finalize();
575 
576     m_schema->setTargetNamespace(m_targetNamespace);
577 }
578 
parseInclude()579 void XsdSchemaParser::parseInclude()
580 {
581     Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Include &&
582                                  XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI);
583 
584     validateElement(XsdTagScope::Include);
585 
586     // parse attributes
587     const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation"));
588 
589     QUrl url(schemaLocation);
590     if (url.isRelative()) {
591         Q_ASSERT(m_documentURI.isValid());
592 
593         url = m_documentURI.resolved(url);
594     }
595 
596     if (m_includedSchemas.contains(url)) {
597         // we have included that file already, according to the schema spec we are
598         // allowed to silently skip it.
599     } else {
600         m_includedSchemas.insert(url);
601 
602         const AutoPtr<QNetworkReply> reply(AccelTreeResourceLoader::load(url, m_context->networkAccessManager(),
603                                                                          m_context, AccelTreeResourceLoader::ContinueOnError));
604         if (reply) {
605             // parse the included schema by a different parser but with the same context
606             XsdSchemaParser parser(m_context, m_parserContext, reply.data());
607             parser.setDocumentURI(url);
608             parser.setTargetNamespaceExtended(m_targetNamespace);
609             parser.setIncludedSchemas(m_includedSchemas);
610             parser.setImportedSchemas(m_importedSchemas);
611             parser.setRedefinedSchemas(m_redefinedSchemas);
612             if (!parser.parse(XsdSchemaParser::IncludeParser)) {
613                 return;
614             } else {
615                 // add indirectly loaded schemas to the list of already loaded ones
616                 addIncludedSchemas(parser.m_includedSchemas);
617                 addImportedSchemas(parser.m_importedSchemas);
618                 addRedefinedSchemas(parser.m_redefinedSchemas);
619             }
620         }
621     }
622 
623     validateIdAttribute("include");
624 
625     TagValidationHandler tagValidator(XsdTagScope::Include, this, m_namePool);
626 
627     while (!atEnd()) {
628         readNext();
629 
630         if (isEndElement())
631             break;
632 
633         if (isStartElement()) {
634             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
635             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
636 
637             tagValidator.validate(token);
638 
639             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
640                 const XsdAnnotation::Ptr annotation = parseAnnotation();
641                 m_schema->addAnnotation(annotation);
642             } else {
643                 parseUnknown();
644             }
645         }
646     }
647 
648     tagValidator.finalize();
649 }
650 
parseImport()651 void XsdSchemaParser::parseImport()
652 {
653     Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Import &&
654                                  XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI);
655 
656     validateElement(XsdTagScope::Import);
657 
658     // parse attributes
659     QString importNamespace;
660     if (hasAttribute(QString::fromLatin1("namespace"))) {
661         importNamespace = readAttribute(QString::fromLatin1("namespace"));
662         if (importNamespace == m_targetNamespace) {
663             error(QtXmlPatterns::tr("%1 element is not allowed to have the same %2 attribute value as the target namespace %3.")
664                                    .arg(formatElement("import"))
665                                    .arg(formatAttribute("namespace"))
666                                    .arg(formatURI(m_targetNamespace)));
667             return;
668         }
669     } else {
670         if (m_targetNamespace.isEmpty()) {
671             error(QtXmlPatterns::tr("%1 element without %2 attribute is not allowed inside schema without target namespace.")
672                                    .arg(formatElement("import"))
673                                    .arg(formatAttribute("namespace")));
674             return;
675         }
676     }
677 
678     if (hasAttribute(QString::fromLatin1("schemaLocation"))) {
679         const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation"));
680 
681         QUrl url(schemaLocation);
682         if (url.isRelative()) {
683             Q_ASSERT(m_documentURI.isValid());
684 
685             url = m_documentURI.resolved(url);
686         }
687 
688         if (m_importedSchemas.contains(url)) {
689             // we have imported that file already, according to the schema spec we are
690             // allowed to silently skip it.
691         } else {
692             m_importedSchemas.insert(url);
693 
694             // as it is possible that well known schemas (e.g. XSD for XML) are only referenced by
695             // namespace we should add it as well
696             m_importedSchemas.insert(importNamespace);
697 
698             AutoPtr<QNetworkReply> reply(AccelTreeResourceLoader::load(url, m_context->networkAccessManager(),
699                                                                        m_context, AccelTreeResourceLoader::ContinueOnError));
700             if (reply) {
701                 // parse the included schema by a different parser but with the same context
702                 XsdSchemaParser parser(m_context, m_parserContext, reply.data());
703                 parser.setDocumentURI(url);
704                 parser.setTargetNamespace(importNamespace);
705                 parser.setIncludedSchemas(m_includedSchemas);
706                 parser.setImportedSchemas(m_importedSchemas);
707                 parser.setRedefinedSchemas(m_redefinedSchemas);
708                 if (!parser.parse(XsdSchemaParser::ImportParser)) {
709                     return;
710                 } else {
711                     // add indirectly loaded schemas to the list of already loaded ones
712                     addIncludedSchemas(parser.m_includedSchemas);
713                     addImportedSchemas(parser.m_importedSchemas);
714                     addRedefinedSchemas(parser.m_redefinedSchemas);
715                 }
716             }
717         }
718     } else {
719         // check whether it is a known namespace we have a builtin schema for
720         if (!importNamespace.isEmpty()) {
721             if (!m_importedSchemas.contains(importNamespace)) {
722                 m_importedSchemas.insert(importNamespace);
723 
724                 QFile file(QString::fromLatin1(":") + importNamespace);
725                 if (file.open(QIODevice::ReadOnly)) {
726                     XsdSchemaParser parser(m_context, m_parserContext, &file);
727                     parser.setDocumentURI(importNamespace);
728                     parser.setTargetNamespace(importNamespace);
729                     parser.setIncludedSchemas(m_includedSchemas);
730                     parser.setImportedSchemas(m_importedSchemas);
731                     parser.setRedefinedSchemas(m_redefinedSchemas);
732                     if (!parser.parse(XsdSchemaParser::ImportParser)) {
733                         return;
734                     } else {
735                         // add indirectly loaded schemas to the list of already loaded ones
736                         addIncludedSchemas(parser.m_includedSchemas);
737                         addImportedSchemas(parser.m_importedSchemas);
738                         addRedefinedSchemas(parser.m_redefinedSchemas);
739                     }
740                 }
741             }
742         } else {
743             // we don't import anything... that is valid according to the schema
744         }
745     }
746 
747     validateIdAttribute("import");
748 
749     TagValidationHandler tagValidator(XsdTagScope::Import, this, m_namePool);
750 
751     while (!atEnd()) {
752         readNext();
753 
754         if (isEndElement())
755             break;
756 
757         if (isStartElement()) {
758             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
759             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
760 
761             tagValidator.validate(token);
762 
763             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
764                 const XsdAnnotation::Ptr annotation = parseAnnotation();
765                 m_schema->addAnnotation(annotation);
766             } else {
767                 parseUnknown();
768             }
769         }
770     }
771 
772     tagValidator.finalize();
773 }
774 
parseRedefine()775 void XsdSchemaParser::parseRedefine()
776 {
777     Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Redefine &&
778                                  XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI);
779 
780     validateElement(XsdTagScope::Redefine);
781 
782     // parse attributes
783     validateIdAttribute("redefine");
784 
785     const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation"));
786 
787     TagValidationHandler tagValidator(XsdTagScope::Redefine, this, m_namePool);
788 
789     XsdSimpleType::List redefinedSimpleTypes;
790     XsdComplexType::List redefinedComplexTypes;
791     XsdModelGroup::List redefinedGroups;
792     XsdAttributeGroup::List redefinedAttributeGroups;
793 
794     while (!atEnd()) {
795         readNext();
796 
797         if (isEndElement())
798             break;
799 
800         if (isStartElement()) {
801             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
802             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
803 
804             tagValidator.validate(token);
805 
806             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
807                 const XsdAnnotation::Ptr annotation = parseAnnotation();
808                 m_schema->addAnnotation(annotation);
809             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
810                 const XsdSimpleType::Ptr type = parseGlobalSimpleType();
811                 redefinedSimpleTypes.append(type);
812 
813                 const QXmlName baseTypeName = m_parserContext->resolver()->baseTypeNameOfType(type);
814                 if (baseTypeName != type->name(m_namePool)) {
815                     error(QString::fromLatin1("redefined simple type %1 must have itself as base type").arg(formatType(m_namePool, type)));
816                     return;
817                 }
818             } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
819                 const XsdComplexType::Ptr type = parseGlobalComplexType();
820                 redefinedComplexTypes.append(type);
821 
822                 // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
823 
824                 // 5
825                 const QXmlName baseTypeName = m_parserContext->resolver()->baseTypeNameOfType(type);
826                 if (baseTypeName != type->name(m_namePool)) {
827                     error(QString::fromLatin1("redefined complex type %1 must have itself as base type").arg(formatType(m_namePool, type)));
828                     return;
829                 }
830             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
831                 const XsdModelGroup::Ptr group = parseNamedGroup();
832                 redefinedGroups.append(group);
833             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
834                 const XsdAttributeGroup::Ptr group = parseNamedAttributeGroup();
835                 redefinedAttributeGroups.append(group);
836 
837             } else {
838                 parseUnknown();
839             }
840         }
841     }
842 
843     bool locationMustResolve = false;
844     if (!redefinedSimpleTypes.isEmpty() || !redefinedComplexTypes.isEmpty() ||
845         !redefinedGroups.isEmpty() || !redefinedAttributeGroups.isEmpty()) {
846         locationMustResolve = true;
847     }
848 
849     QUrl url(schemaLocation);
850     if (url.isRelative()) {
851         Q_ASSERT(m_documentURI.isValid());
852 
853         url = m_documentURI.resolved(url);
854     }
855 
856     // we parse the schema given in the redefine tag into its own context
857     const XsdSchemaParserContext::Ptr redefinedContext(new XsdSchemaParserContext(m_namePool, m_context));
858 
859     if (m_redefinedSchemas.contains(url)) {
860         // we have redefined that file already, according to the schema spec we are
861         // allowed to silently skip it.
862     } else {
863         m_redefinedSchemas.insert(url);
864         QNetworkReply *reply = AccelTreeResourceLoader::load(url, m_context->networkAccessManager(),
865                                                              m_context,
866                                                              (locationMustResolve ? AccelTreeResourceLoader::FailOnError : AccelTreeResourceLoader::ContinueOnError));
867         if (reply) {
868             // parse the included schema by a different parser but with the same context
869             XsdSchemaParser parser(m_context, redefinedContext, reply);
870             parser.setDocumentURI(url);
871             parser.setTargetNamespaceExtended(m_targetNamespace);
872             parser.setIncludedSchemas(m_includedSchemas);
873             parser.setImportedSchemas(m_importedSchemas);
874             parser.setRedefinedSchemas(m_redefinedSchemas);
875             if (!parser.parse(XsdSchemaParser::RedefineParser)) {
876                 return;
877             } else {
878                 // add indirectly loaded schemas to the list of already loaded ones
879                 addIncludedSchemas(parser.m_includedSchemas);
880                 addImportedSchemas(parser.m_importedSchemas);
881                 addRedefinedSchemas(parser.m_redefinedSchemas);
882             }
883 
884             delete reply;
885         }
886     }
887 
888     XsdSimpleType::List contextSimpleTypes = redefinedContext->schema()->simpleTypes();
889     XsdComplexType::List contextComplexTypes = redefinedContext->schema()->complexTypes();
890     XsdModelGroup::List contextGroups = redefinedContext->schema()->elementGroups();
891     XsdAttributeGroup::List contextAttributeGroups = redefinedContext->schema()->attributeGroups();
892 
893     // now we do the actual redefinition:
894 
895     // iterate over all redefined simple types
896     for (int i = 0; i < redefinedSimpleTypes.count(); ++i) {
897         XsdSimpleType::Ptr redefinedType = redefinedSimpleTypes.at(i);
898 
899         //TODONEXT: validation
900 
901         // search the definition they override in the context types
902         bool found = false;
903         for (int j = 0; j < contextSimpleTypes.count(); ++j) {
904             XsdSimpleType::Ptr contextType = contextSimpleTypes.at(j);
905 
906             if (redefinedType->name(m_namePool) == contextType->name(m_namePool)) { // we found the right type
907                 found = true;
908 
909                 // 1) set name of context type to empty name
910                 contextType->setName(m_parserContext->createAnonymousName(QString()));
911 
912                 // 2) set the context type as base type for the redefined type
913                 redefinedType->setWxsSuperType(contextType);
914 
915                 // 3) remove the base type resolving job from the resolver as
916                 //    we have set the base type here explicitly
917                 m_parserContext->resolver()->removeSimpleRestrictionBase(redefinedType);
918 
919                 // 4) add the redefined type to the schema
920                 addType(redefinedType);
921 
922                 // 5) add the context type as anonymous type, so the resolver
923                 //    can resolve it further.
924                 addAnonymousType(contextType);
925 
926                 // 6) remove the context type from the list
927                 contextSimpleTypes.removeAt(j);
928 
929                 break;
930             }
931         }
932 
933         if (!found) {
934             error(QString::fromLatin1("no matching type found to redefine simple type %1").arg(formatType(m_namePool, redefinedType)));
935             return;
936         }
937     }
938 
939     // add all remaining context simple types to the schema
940     for (int i = 0; i < contextSimpleTypes.count(); ++i) {
941         addType(contextSimpleTypes.at(i));
942     }
943 
944     // iterate over all redefined complex types
945     for (int i = 0; i < redefinedComplexTypes.count(); ++i) {
946         XsdComplexType::Ptr redefinedType = redefinedComplexTypes.at(i);
947 
948         //TODONEXT: validation
949 
950         // search the definition they override in the context types
951         bool found = false;
952         for (int j = 0; j < contextComplexTypes.count(); ++j) {
953             XsdComplexType::Ptr contextType = contextComplexTypes.at(j);
954 
955             if (redefinedType->name(m_namePool) == contextType->name(m_namePool)) { // we found the right type
956                 found = true;
957 
958                 // 1) set name of context type to empty name
959                 contextType->setName(m_parserContext->createAnonymousName(QString()));
960 
961                 // 2) set the context type as base type for the redefined type
962                 redefinedType->setWxsSuperType(contextType);
963 
964                 // 3) remove the base type resolving job from the resolver as
965                 //    we have set the base type here explicitly
966                 m_parserContext->resolver()->removeComplexBaseType(redefinedType);
967 
968                 // 4) add the redefined type to the schema
969                 addType(redefinedType);
970 
971                 // 5) add the context type as anonymous type, so the resolver
972                 //    can resolve its attribute uses etc.
973                 addAnonymousType(contextType);
974 
975                 // 6) remove the context type from the list
976                 contextComplexTypes.removeAt(j);
977 
978                 break;
979             }
980         }
981 
982         if (!found) {
983             error(QString::fromLatin1("no matching type found to redefine complex type %1").arg(formatType(m_namePool, redefinedType)));
984             return;
985         }
986     }
987 
988     // iterate over all redefined element groups
989     for (int i = 0; i < redefinedGroups.count(); ++i) {
990         const XsdModelGroup::Ptr group(redefinedGroups.at(i));
991 
992         // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
993 
994         // 6
995         const XsdParticle::List particles = collectGroupRef(group);
996         XsdParticle::Ptr referencedParticle;
997         int sameNameCounter = 0;
998         for (int i = 0; i < particles.count(); ++i) {
999             const XsdReference::Ptr ref(particles.at(i)->term());
1000             if (ref->referenceName() == group->name(m_namePool)) {
1001                 referencedParticle = particles.at(i);
1002 
1003                 if (referencedParticle->minimumOccurs() != 1 || referencedParticle->maximumOccurs() != 1 || referencedParticle->maximumOccursUnbounded()) { // 6.1.2
1004                     error(QString::fromLatin1("redefined group %1 can not contain reference to itself with minOccurs or maxOccurs != 1").arg(formatKeyword(group->displayName(m_namePool))));
1005                     return;
1006                 }
1007                 sameNameCounter++;
1008             }
1009         }
1010 
1011         // 6.1.1
1012         if (sameNameCounter > 1) {
1013             error(QString::fromLatin1("redefined group %1 can not contain multiple references to itself").arg(formatKeyword(group->displayName(m_namePool))));
1014             return;
1015         }
1016 
1017         // search the group definition in the included schema (S2)
1018         XsdModelGroup::Ptr contextGroup;
1019         for (int j = 0; j < contextGroups.count(); ++j) {
1020             if (group->name(m_namePool) == contextGroups.at(j)->name(m_namePool)) {
1021                 contextGroup = contextGroups.at(j);
1022                 break;
1023             }
1024         }
1025 
1026         if (!contextGroup) { // 6.2.1
1027             error(QString::fromLatin1("redefined group %1 has no occurrence in included schema").arg(formatKeyword(group->displayName(m_namePool))));
1028             return;
1029         }
1030 
1031         if (sameNameCounter == 1) {
1032             // there was a self reference in the redefined group, so use the
1033             // group from the included schema
1034 
1035             // set a anonymous name to the group of the included schema
1036             contextGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(contextGroup->name(m_namePool).namespaceURI())));
1037 
1038             // replace the self-reference with the group from the included schema
1039             referencedParticle->setTerm(contextGroup);
1040 
1041             addElementGroup(group);
1042 
1043             addElementGroup(contextGroup);
1044             contextGroups.removeAll(contextGroup);
1045         } else {
1046             // there was no self reference in the redefined group
1047 
1048             // just add the redefined group...
1049             addElementGroup(group);
1050 
1051             // we have to add them, otherwise it is not resolved and we can't validate it later
1052             contextGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(contextGroup->name(m_namePool).namespaceURI())));
1053             addElementGroup(contextGroup);
1054 
1055             m_schemaResolver->addRedefinedGroups(group, contextGroup);
1056 
1057             // ...and forget about the group from the included schema
1058             contextGroups.removeAll(contextGroup);
1059         }
1060     }
1061 
1062     // iterate over all redefined attribute groups
1063     for (int i = 0; i < redefinedAttributeGroups.count(); ++i) {
1064         const XsdAttributeGroup::Ptr group(redefinedAttributeGroups.at(i));
1065 
1066         // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
1067 
1068         // 7
1069 
1070         // 7.1
1071         int sameNameCounter = 0;
1072         for (int j = 0; j < group->attributeUses().count(); ++j) {
1073             const XsdAttributeUse::Ptr attributeUse(group->attributeUses().at(j));
1074             if (attributeUse->isReference()) {
1075                 const XsdAttributeReference::Ptr reference(attributeUse);
1076                 if (reference->type() == XsdAttributeReference::AttributeGroup) {
1077                     if (group->name(m_namePool) == reference->referenceName())
1078                         sameNameCounter++;
1079                 }
1080             }
1081         }
1082         if (sameNameCounter > 1) {
1083             error(QString::fromLatin1("redefined attribute group %1 can not contain multiple references to itself").arg(formatKeyword(group->displayName(m_namePool))));
1084             return;
1085         }
1086 
1087         // search the attribute group definition in the included schema (S2)
1088         XsdAttributeGroup::Ptr baseGroup;
1089         for (int j = 0; j < contextAttributeGroups.count(); ++j) {
1090             const XsdAttributeGroup::Ptr contextGroup(contextAttributeGroups.at(j));
1091             if (group->name(m_namePool) == contextGroup->name(m_namePool)) {
1092                 baseGroup = contextGroup;
1093                 break;
1094             }
1095         }
1096 
1097         if (!baseGroup) { // 7.2.1
1098             error(QString::fromLatin1("redefined attribute group %1 has no occurrence in included schema").arg(formatKeyword(group->displayName(m_namePool))));
1099             return;
1100         }
1101 
1102         if (sameNameCounter == 1) {
1103 
1104             // first set an anonymous name to the attribute group from the included
1105             // schema
1106             baseGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(baseGroup->name(m_namePool).namespaceURI())));
1107 
1108             // iterate over the attribute uses of the redefined attribute group
1109             // and replace the self-reference with the attribute group from the
1110             // included schema
1111             for (int j = 0; j < group->attributeUses().count(); ++j) {
1112                 const XsdAttributeUse::Ptr attributeUse(group->attributeUses().at(j));
1113                 if (attributeUse->isReference()) {
1114                     const XsdAttributeReference::Ptr reference(attributeUse);
1115                     if (reference->type() == XsdAttributeReference::AttributeGroup) {
1116                         if (group->name(m_namePool) == reference->referenceName()) {
1117                             reference->setReferenceName(baseGroup->name(m_namePool));
1118                             break;
1119                         }
1120                     }
1121                 }
1122             }
1123 
1124             // add both groups to the target schema
1125             addAttributeGroup(baseGroup);
1126             addAttributeGroup(group);
1127 
1128             contextAttributeGroups.removeAll(baseGroup);
1129         }
1130 
1131         if (sameNameCounter == 0) { // 7.2
1132 
1133             // we have to add them, otherwise it is not resolved and we can't validate it later
1134             baseGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(baseGroup->name(m_namePool).namespaceURI())));
1135             addAttributeGroup(baseGroup);
1136 
1137             m_schemaResolver->addRedefinedAttributeGroups(group, baseGroup);
1138 
1139             // just add the redefined attribute group to the target schema...
1140             addAttributeGroup(group);
1141 
1142             // ... and forget about the one from the included schema
1143             contextAttributeGroups.removeAll(baseGroup);
1144         }
1145     }
1146 
1147     // add all remaining context complex types to the schema
1148     for (int i = 0; i < contextComplexTypes.count(); ++i) {
1149         addType(contextComplexTypes.at(i));
1150     }
1151 
1152     // add all remaining context element groups to the schema
1153     for (int i = 0; i < contextGroups.count(); ++i) {
1154         addElementGroup(contextGroups.at(i));
1155     }
1156 
1157     // add all remaining context attribute groups to the schema
1158     for (int i = 0; i < contextAttributeGroups.count(); ++i) {
1159         addAttributeGroup(contextAttributeGroups.at(i));
1160     }
1161 
1162     // copy all elements, attributes and notations
1163     const XsdElement::List contextElements = redefinedContext->schema()->elements();
1164     for (int i = 0; i < contextElements.count(); ++i) {
1165         addElement(contextElements.at(i));
1166     }
1167 
1168     const XsdAttribute::List contextAttributes = redefinedContext->schema()->attributes();
1169     for (int i = 0; i < contextAttributes.count(); ++i) {
1170         addAttribute(contextAttributes.at(i));
1171     }
1172 
1173     const XsdNotation::List contextNotations = redefinedContext->schema()->notations();
1174     for (int i = 0; i < contextNotations.count(); ++i) {
1175         addNotation(contextNotations.at(i));
1176     }
1177 
1178     // push all data to resolve from the context resolver to our resolver
1179     redefinedContext->resolver()->copyDataTo(m_parserContext->resolver());
1180 
1181     tagValidator.finalize();
1182 }
1183 
parseAnnotation()1184 XsdAnnotation::Ptr XsdSchemaParser::parseAnnotation()
1185 {
1186     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Annotation, this);
1187 
1188     validateElement(XsdTagScope::Annotation);
1189 
1190     // parse attributes
1191     validateIdAttribute("annotation");
1192 
1193     TagValidationHandler tagValidator(XsdTagScope::Annotation, this, m_namePool);
1194 
1195     const XsdAnnotation::Ptr annotation(new XsdAnnotation());
1196 
1197     while (!atEnd()) {
1198         readNext();
1199 
1200         if (isEndElement())
1201             break;
1202 
1203         if (isStartElement()) {
1204             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1205             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1206 
1207             tagValidator.validate(token);
1208 
1209             if (isSchemaTag(XsdSchemaToken::Appinfo, token, namespaceToken)) {
1210                 const XsdApplicationInformation::Ptr info = parseAppInfo();
1211                 annotation->addApplicationInformation(info);
1212             } else if (isSchemaTag(XsdSchemaToken::Documentation, token, namespaceToken)) {
1213                 const XsdDocumentation::Ptr documentation = parseDocumentation();
1214                 annotation->addDocumentation(documentation);
1215             } else {
1216                 parseUnknown();
1217             }
1218         }
1219     }
1220 
1221     tagValidator.finalize();
1222 
1223     return annotation;
1224 }
1225 
parseAppInfo()1226 XsdApplicationInformation::Ptr XsdSchemaParser::parseAppInfo()
1227 {
1228     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Appinfo, this);
1229 
1230     validateElement(XsdTagScope::AppInfo);
1231 
1232     const XsdApplicationInformation::Ptr info(new XsdApplicationInformation());
1233 
1234     // parse attributes
1235     if (hasAttribute(QString::fromLatin1("source"))) {
1236         const QString value = readAttribute(QString::fromLatin1("source"));
1237 
1238         if (!isValidUri(value)) {
1239             attributeContentError("source", "appinfo", value, BuiltinTypes::xsAnyURI);
1240             return info;
1241         }
1242 
1243         if (!value.isEmpty()) {
1244             const AnyURI::Ptr source = AnyURI::fromLexical(value);
1245             info->setSource(source);
1246         }
1247     }
1248 
1249     while (!atEnd()) { //EVAL: can be anything... what to do?
1250         readNext();
1251 
1252         if (isEndElement())
1253             break;
1254 
1255         if (isStartElement())
1256             parseUnknownDocumentation();
1257     }
1258 
1259     return info;
1260 }
1261 
parseDocumentation()1262 XsdDocumentation::Ptr XsdSchemaParser::parseDocumentation()
1263 {
1264     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Documentation, this);
1265 
1266     validateElement(XsdTagScope::Documentation);
1267 
1268     const XsdDocumentation::Ptr documentation(new XsdDocumentation());
1269 
1270     // parse attributes
1271     if (hasAttribute(QString::fromLatin1("source"))) {
1272         const QString value = readAttribute(QString::fromLatin1("source"));
1273 
1274         if (!isValidUri(value)) {
1275             attributeContentError("source", "documentation", value, BuiltinTypes::xsAnyURI);
1276             return documentation;
1277         }
1278 
1279         if (!value.isEmpty()) {
1280             const AnyURI::Ptr source = AnyURI::fromLexical(value);
1281             documentation->setSource(source);
1282         }
1283     }
1284 
1285     if (hasAttribute(CommonNamespaces::XML, QString::fromLatin1("lang"))) {
1286         const QString value = readAttribute(QString::fromLatin1("lang"), CommonNamespaces::XML);
1287 
1288         QRegExp exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*"));
1289         if (!exp.exactMatch(value)) {
1290             attributeContentError("xml:lang", "documentation", value);
1291             return documentation;
1292         }
1293     }
1294 
1295     while (!atEnd()) { //EVAL: can by any... what to do?
1296         readNext();
1297 
1298         if (isEndElement())
1299             break;
1300 
1301         if (isStartElement())
1302             parseUnknownDocumentation();
1303     }
1304 
1305     return documentation;
1306 }
1307 
parseDefaultOpenContent()1308 void XsdSchemaParser::parseDefaultOpenContent()
1309 {
1310     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::DefaultOpenContent, this);
1311 
1312     validateElement(XsdTagScope::DefaultOpenContent);
1313 
1314     m_defaultOpenContent = XsdComplexType::OpenContent::Ptr(new XsdComplexType::OpenContent());
1315 
1316     if (hasAttribute(QString::fromLatin1("appliesToEmpty"))) {
1317         const QString value = readAttribute(QString::fromLatin1("appliesToEmpty"));
1318         const Boolean::Ptr appliesToEmpty = Boolean::fromLexical(value);
1319         if (appliesToEmpty->hasError()) {
1320             attributeContentError("appliesToEmpty", "defaultOpenContent", value, BuiltinTypes::xsBoolean);
1321             return;
1322         }
1323 
1324         m_defaultOpenContentAppliesToEmpty = appliesToEmpty->as<Boolean>()->value();
1325     } else {
1326         m_defaultOpenContentAppliesToEmpty = false;
1327     }
1328 
1329     if (hasAttribute(QString::fromLatin1("mode"))) {
1330         const QString mode = readAttribute(QString::fromLatin1("mode"));
1331 
1332         if (mode == QString::fromLatin1("interleave")) {
1333             m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave);
1334         } else if (mode == QString::fromLatin1("suffix")) {
1335             m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Suffix);
1336         } else {
1337             attributeContentError("mode", "defaultOpenContent", mode);
1338             return;
1339         }
1340     } else {
1341         m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave);
1342     }
1343 
1344     validateIdAttribute("defaultOpenContent");
1345 
1346     TagValidationHandler tagValidator(XsdTagScope::DefaultOpenContent, this, m_namePool);
1347 
1348     while (!atEnd()) {
1349         readNext();
1350 
1351         if (isEndElement())
1352             break;
1353 
1354         if (isStartElement()) {
1355             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1356             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1357 
1358             tagValidator.validate(token);
1359 
1360             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1361                 const XsdAnnotation::Ptr annotation = parseAnnotation();
1362                 m_defaultOpenContent->addAnnotation(annotation);
1363             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
1364                 const XsdParticle::Ptr particle;
1365                 const XsdWildcard::Ptr wildcard = parseAny(particle);
1366                 m_defaultOpenContent->setWildcard(wildcard);
1367             } else {
1368                 parseUnknown();
1369             }
1370         }
1371     }
1372 
1373     tagValidator.finalize();
1374 }
1375 
parseGlobalSimpleType()1376 XsdSimpleType::Ptr XsdSchemaParser::parseGlobalSimpleType()
1377 {
1378     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleType, this);
1379 
1380     validateElement(XsdTagScope::GlobalSimpleType);
1381 
1382     const XsdSimpleType::Ptr simpleType(new XsdSimpleType());
1383     simpleType->setCategory(XsdSimpleType::SimpleTypeAtomic); // just to make sure it's not invalid
1384 
1385     // parse attributes
1386     const SchemaType::DerivationConstraints allowedConstraints(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint | SchemaType::ListConstraint | SchemaType::UnionConstraint);
1387     simpleType->setDerivationConstraints(readDerivationConstraintAttribute(allowedConstraints, "simpleType"));
1388 
1389     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("simpleType"));
1390     simpleType->setName(objectName);
1391 
1392     validateIdAttribute("simpleType");
1393 
1394     TagValidationHandler tagValidator(XsdTagScope::GlobalSimpleType, this, m_namePool);
1395 
1396     while (!atEnd()) {
1397         readNext();
1398 
1399         if (isEndElement())
1400             break;
1401 
1402         if (isStartElement()) {
1403             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1404             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1405 
1406             tagValidator.validate(token);
1407 
1408             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1409                 const XsdAnnotation::Ptr annotation = parseAnnotation();
1410                 simpleType->addAnnotation(annotation);
1411             } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
1412                 parseSimpleRestriction(simpleType);
1413             } else if (isSchemaTag(XsdSchemaToken::List, token, namespaceToken)) {
1414                 parseList(simpleType);
1415             } else if (isSchemaTag(XsdSchemaToken::Union, token, namespaceToken)) {
1416                 parseUnion(simpleType);
1417             } else {
1418                 parseUnknown();
1419             }
1420         }
1421     }
1422 
1423     tagValidator.finalize();
1424 
1425     return simpleType;
1426 }
1427 
parseLocalSimpleType()1428 XsdSimpleType::Ptr XsdSchemaParser::parseLocalSimpleType()
1429 {
1430     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleType, this);
1431 
1432     validateElement(XsdTagScope::LocalSimpleType);
1433 
1434     const XsdSimpleType::Ptr simpleType(new XsdSimpleType());
1435     simpleType->setCategory(XsdSimpleType::SimpleTypeAtomic); // just to make sure it's not invalid
1436     simpleType->setName(m_parserContext->createAnonymousName(m_targetNamespace));
1437 
1438     validateIdAttribute("simpleType");
1439 
1440     TagValidationHandler tagValidator(XsdTagScope::LocalSimpleType, this, m_namePool);
1441 
1442     while (!atEnd()) {
1443         readNext();
1444 
1445         if (isEndElement())
1446             break;
1447 
1448         if (isStartElement()) {
1449             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1450             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1451 
1452             tagValidator.validate(token);
1453 
1454             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1455                 const XsdAnnotation::Ptr annotation = parseAnnotation();
1456                 simpleType->addAnnotation(annotation);
1457             } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
1458                 parseSimpleRestriction(simpleType);
1459             } else if (isSchemaTag(XsdSchemaToken::List, token, namespaceToken)) {
1460                 parseList(simpleType);
1461             } else if (isSchemaTag(XsdSchemaToken::Union, token, namespaceToken)) {
1462                 parseUnion(simpleType);
1463             } else {
1464                 parseUnknown();
1465             }
1466         }
1467     }
1468 
1469     tagValidator.finalize();
1470 
1471     return simpleType;
1472 }
1473 
parseSimpleRestriction(const XsdSimpleType::Ptr & ptr)1474 void XsdSchemaParser::parseSimpleRestriction(const XsdSimpleType::Ptr &ptr)
1475 {
1476     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
1477 
1478     validateElement(XsdTagScope::SimpleRestriction);
1479 
1480     ptr->setDerivationMethod(XsdSimpleType::DerivationRestriction);
1481 
1482     // The base attribute and simpleType member are mutually exclusive,
1483     // so we keep track of that
1484     bool hasBaseAttribute = false;
1485     bool hasBaseTypeSpecified = false;
1486 
1487     QXmlName baseName;
1488     if (hasAttribute(QString::fromLatin1("base"))) {
1489         const QString base = readQNameAttribute(QString::fromLatin1("base"), "restriction");
1490         convertName(base, NamespaceSupport::ElementName, baseName); // translate qualified name into QXmlName
1491         m_schemaResolver->addSimpleRestrictionBase(ptr, baseName, currentSourceLocation()); // add to resolver
1492 
1493         hasBaseAttribute = true;
1494         hasBaseTypeSpecified = true;
1495     }
1496     validateIdAttribute("restriction");
1497 
1498     XsdFacet::Hash facets;
1499     QList<XsdFacet::Ptr> patternFacets;
1500     QList<XsdFacet::Ptr> enumerationFacets;
1501     QList<XsdFacet::Ptr> assertionFacets;
1502 
1503     TagValidationHandler tagValidator(XsdTagScope::SimpleRestriction, this, m_namePool);
1504 
1505     while (!atEnd()) {
1506         readNext();
1507 
1508         if (isEndElement())
1509             break;
1510 
1511         if (isStartElement()) {
1512             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1513             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1514 
1515             tagValidator.validate(token);
1516 
1517             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1518                 const XsdAnnotation::Ptr annotation = parseAnnotation();
1519                 ptr->addAnnotation(annotation);
1520             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
1521                 if (hasBaseAttribute) {
1522                     error(QtXmlPatterns::tr("%1 element is not allowed inside %2 element if %3 attribute is present.")
1523                                            .arg(formatElement("simpleType"))
1524                                            .arg(formatElement("restriction"))
1525                                            .arg(formatAttribute("base")));
1526                     return;
1527                 }
1528 
1529                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
1530                 type->setContext(ptr);
1531                 ptr->setWxsSuperType(type);
1532                 ptr->setCategory(type->category());
1533                 hasBaseTypeSpecified = true;
1534 
1535                 // add it to list of anonymous types as well
1536                 addAnonymousType(type);
1537             } else if (isSchemaTag(XsdSchemaToken::MinExclusive, token, namespaceToken)) {
1538                 const XsdFacet::Ptr facet = parseMinExclusiveFacet();
1539                 addFacet(facet, facets, ptr);
1540             } else if (isSchemaTag(XsdSchemaToken::MinInclusive, token, namespaceToken)) {
1541                 const XsdFacet::Ptr facet = parseMinInclusiveFacet();
1542                 addFacet(facet, facets, ptr);
1543             } else if (isSchemaTag(XsdSchemaToken::MaxExclusive, token, namespaceToken)) {
1544                 const XsdFacet::Ptr facet = parseMaxExclusiveFacet();
1545                 addFacet(facet, facets, ptr);
1546             } else if (isSchemaTag(XsdSchemaToken::MaxInclusive, token, namespaceToken)) {
1547                 const XsdFacet::Ptr facet = parseMaxInclusiveFacet();
1548                 addFacet(facet, facets, ptr);
1549             } else if (isSchemaTag(XsdSchemaToken::TotalDigits, token, namespaceToken)) {
1550                 const XsdFacet::Ptr facet = parseTotalDigitsFacet();
1551                 addFacet(facet, facets, ptr);
1552             } else if (isSchemaTag(XsdSchemaToken::FractionDigits, token, namespaceToken)) {
1553                 const XsdFacet::Ptr facet = parseFractionDigitsFacet();
1554                 addFacet(facet, facets, ptr);
1555             } else if (isSchemaTag(XsdSchemaToken::Length, token, namespaceToken)) {
1556                 const XsdFacet::Ptr facet = parseLengthFacet();
1557                 addFacet(facet, facets, ptr);
1558             } else if (isSchemaTag(XsdSchemaToken::MinLength, token, namespaceToken)) {
1559                 const XsdFacet::Ptr facet = parseMinLengthFacet();
1560                 addFacet(facet, facets, ptr);
1561             } else if (isSchemaTag(XsdSchemaToken::MaxLength, token, namespaceToken)) {
1562                 const XsdFacet::Ptr facet = parseMaxLengthFacet();
1563                 addFacet(facet, facets, ptr);
1564             } else if (isSchemaTag(XsdSchemaToken::Enumeration, token, namespaceToken)) {
1565                 const XsdFacet::Ptr facet = parseEnumerationFacet();
1566                 enumerationFacets.append(facet);
1567             } else if (isSchemaTag(XsdSchemaToken::WhiteSpace, token, namespaceToken)) {
1568                 const XsdFacet::Ptr facet = parseWhiteSpaceFacet();
1569                 addFacet(facet, facets, ptr);
1570             } else if (isSchemaTag(XsdSchemaToken::Pattern, token, namespaceToken)) {
1571                 const XsdFacet::Ptr facet = parsePatternFacet();
1572                 patternFacets.append(facet);
1573             } else if (isSchemaTag(XsdSchemaToken::Assertion, token, namespaceToken)) {
1574                 const XsdFacet::Ptr facet = parseAssertionFacet();
1575                 assertionFacets.append(facet);
1576             } else {
1577                 parseUnknown();
1578             }
1579         }
1580     }
1581 
1582     if (!hasBaseTypeSpecified) {
1583         error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element.")
1584                                .arg(formatElement("restriction"))
1585                                .arg(formatAttribute("base"))
1586                                .arg(formatElement("simpleType")));
1587         return;
1588     }
1589 
1590     // merge all pattern facets into one multi value facet
1591     if (!patternFacets.isEmpty()) {
1592         const XsdFacet::Ptr patternFacet(new XsdFacet());
1593         patternFacet->setType(XsdFacet::Pattern);
1594 
1595         AtomicValue::List multiValue;
1596         for (int i = 0; i < patternFacets.count(); ++i)
1597             multiValue << patternFacets.at(i)->multiValue();
1598 
1599         patternFacet->setMultiValue(multiValue);
1600         addFacet(patternFacet, facets, ptr);
1601     }
1602 
1603     // merge all enumeration facets into one multi value facet
1604     if (!enumerationFacets.isEmpty()) {
1605         const XsdFacet::Ptr enumerationFacet(new XsdFacet());
1606         enumerationFacet->setType(XsdFacet::Enumeration);
1607 
1608         AtomicValue::List multiValue;
1609         for (int i = 0; i < enumerationFacets.count(); ++i)
1610             multiValue << enumerationFacets.at(i)->multiValue();
1611 
1612         enumerationFacet->setMultiValue(multiValue);
1613         addFacet(enumerationFacet, facets, ptr);
1614     }
1615 
1616     // merge all assertion facets into one facet
1617     if (!assertionFacets.isEmpty()) {
1618         const XsdFacet::Ptr assertionFacet(new XsdFacet());
1619         assertionFacet->setType(XsdFacet::Assertion);
1620 
1621         XsdAssertion::List assertions;
1622         for (int i = 0; i < assertionFacets.count(); ++i)
1623             assertions << assertionFacets.at(i)->assertions();
1624 
1625         assertionFacet->setAssertions(assertions);
1626         addFacet(assertionFacet, facets, ptr);
1627     }
1628 
1629     ptr->setFacets(facets);
1630 
1631     tagValidator.finalize();
1632 }
1633 
parseList(const XsdSimpleType::Ptr & ptr)1634 void XsdSchemaParser::parseList(const XsdSimpleType::Ptr &ptr)
1635 {
1636     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::List, this);
1637 
1638     validateElement(XsdTagScope::List);
1639 
1640     ptr->setCategory(XsdSimpleType::SimpleTypeList);
1641     ptr->setDerivationMethod(XsdSimpleType::DerivationList);
1642     ptr->setWxsSuperType(BuiltinTypes::xsAnySimpleType);
1643 
1644     // The itemType attribute and simpleType member are mutually exclusive,
1645     // so we keep track of that
1646     bool hasItemTypeAttribute = false;
1647     bool hasItemTypeSpecified = false;
1648 
1649     if (hasAttribute(QString::fromLatin1("itemType"))) {
1650         const QString itemType = readQNameAttribute(QString::fromLatin1("itemType"), "list");
1651         QXmlName typeName;
1652         convertName(itemType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
1653         m_schemaResolver->addSimpleListType(ptr, typeName, currentSourceLocation()); // add to resolver
1654 
1655         hasItemTypeAttribute = true;
1656         hasItemTypeSpecified = true;
1657     }
1658 
1659     validateIdAttribute("list");
1660 
1661     TagValidationHandler tagValidator(XsdTagScope::List, this, m_namePool);
1662 
1663     while (!atEnd()) {
1664         readNext();
1665 
1666         if (isEndElement())
1667             break;
1668 
1669         if (isStartElement()) {
1670             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1671             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1672 
1673             tagValidator.validate(token);
1674 
1675             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1676                 const XsdAnnotation::Ptr annotation = parseAnnotation();
1677                 ptr->addAnnotation(annotation);
1678             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
1679                 if (hasItemTypeAttribute) {
1680                     error(QtXmlPatterns::tr("%1 element is not allowed inside %2 element if %3 attribute is present.")
1681                                            .arg(formatElement("simpleType"))
1682                                            .arg(formatElement("list"))
1683                                            .arg(formatAttribute("itemType")));
1684                     return;
1685                 }
1686 
1687                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
1688                 type->setContext(ptr);
1689                 ptr->setItemType(type);
1690 
1691                 hasItemTypeSpecified = true;
1692 
1693                 // add it to list of anonymous types as well
1694                 addAnonymousType(type);
1695             } else {
1696                 parseUnknown();
1697             }
1698         }
1699     }
1700 
1701     if (!hasItemTypeSpecified) {
1702         error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element.")
1703                                .arg(formatElement("list"))
1704                                .arg(formatAttribute("itemType"))
1705                                .arg(formatElement("simpleType")));
1706         return;
1707     }
1708 
1709     tagValidator.finalize();
1710 
1711     // add the default white space facet that every simple type with list derivation has
1712     const XsdFacet::Ptr defaultFacet(new XsdFacet());
1713     defaultFacet->setType(XsdFacet::WhiteSpace);
1714     defaultFacet->setFixed(true);
1715     defaultFacet->setValue(DerivedString<TypeString>::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse)));
1716     XsdFacet::Hash facets;
1717     facets.insert(defaultFacet->type(), defaultFacet);
1718     ptr->setFacets(facets);
1719 }
1720 
parseUnion(const XsdSimpleType::Ptr & ptr)1721 void XsdSchemaParser::parseUnion(const XsdSimpleType::Ptr &ptr)
1722 {
1723     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Union, this);
1724 
1725     validateElement(XsdTagScope::Union);
1726 
1727     ptr->setCategory(XsdSimpleType::SimpleTypeUnion);
1728     ptr->setDerivationMethod(XsdSimpleType::DerivationUnion);
1729     ptr->setWxsSuperType(BuiltinTypes::xsAnySimpleType);
1730 
1731     // The memberTypes attribute is not allowed to be empty,
1732     // so we keep track of that
1733     bool hasMemberTypesSpecified = false;
1734 
1735     if (hasAttribute(QString::fromLatin1("memberTypes"))) {
1736         const QStringList memberTypes = readAttribute(QString::fromLatin1("memberTypes")).split(QLatin1Char(' '), Qt::SkipEmptyParts);
1737         QList<QXmlName> typeNames;
1738 
1739         for (int i = 0; i < memberTypes.count(); ++i) {
1740             QXmlName typeName;
1741             convertName(memberTypes.at(i), NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
1742             typeNames.append(typeName);
1743         }
1744 
1745         if (!typeNames.isEmpty()) {
1746             m_schemaResolver->addSimpleUnionTypes(ptr, typeNames, currentSourceLocation()); // add to resolver
1747             hasMemberTypesSpecified = true;
1748         }
1749     }
1750 
1751     validateIdAttribute("union");
1752 
1753     AnySimpleType::List memberTypes;
1754 
1755     TagValidationHandler tagValidator(XsdTagScope::Union, this, m_namePool);
1756 
1757     while (!atEnd()) {
1758         readNext();
1759 
1760         if (isEndElement())
1761             break;
1762 
1763         if (isStartElement()) {
1764             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1765             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1766 
1767             tagValidator.validate(token);
1768 
1769             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1770                 const XsdAnnotation::Ptr annotation = parseAnnotation();
1771                 ptr->addAnnotation(annotation);
1772             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
1773                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
1774                 type->setContext(ptr);
1775                 memberTypes.append(type);
1776 
1777                 // add it to list of anonymous types as well
1778                 addAnonymousType(type);
1779             } else {
1780                 parseUnknown();
1781             }
1782         }
1783     }
1784 
1785     if (!memberTypes.isEmpty()) {
1786         ptr->setMemberTypes(memberTypes);
1787         hasMemberTypesSpecified = true;
1788     }
1789 
1790     if (!hasMemberTypesSpecified) {
1791         error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element.")
1792                                .arg(formatElement("union"))
1793                                .arg(formatAttribute("memberTypes"))
1794                                .arg(formatElement("simpleType")));
1795         return;
1796     }
1797 
1798     tagValidator.finalize();
1799 }
1800 
parseMinExclusiveFacet()1801 XsdFacet::Ptr XsdSchemaParser::parseMinExclusiveFacet()
1802 {
1803     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinExclusive, this);
1804 
1805     validateElement(XsdTagScope::MinExclusiveFacet);
1806 
1807     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
1808     facet->setType(XsdFacet::MinimumExclusive);
1809 
1810     // parse attributes
1811     if (hasAttribute(QString::fromLatin1("fixed"))) {
1812         const QString value = readAttribute(QString::fromLatin1("fixed"));
1813         const Boolean::Ptr fixed = Boolean::fromLexical(value);
1814         if (fixed->hasError()) {
1815             attributeContentError("fixed", "minExclusive", value, BuiltinTypes::xsBoolean);
1816             return facet;
1817         }
1818 
1819         facet->setFixed(fixed->as<Boolean>()->value());
1820     } else {
1821         facet->setFixed(false); // the default value
1822     }
1823 
1824     // as minExclusive can have a value of type anySimpleType, we just read
1825     // the string here and store it for later intepretation
1826     const QString value = readAttribute(QString::fromLatin1("value"));
1827     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
1828     if (string->hasError()) {
1829         attributeContentError("value", "minExclusive", value, BuiltinTypes::xsAnySimpleType);
1830         return facet;
1831     } else {
1832         facet->setValue(string);
1833     }
1834 
1835     validateIdAttribute("minExclusive");
1836 
1837     TagValidationHandler tagValidator(XsdTagScope::MinExclusiveFacet, this, m_namePool);
1838 
1839     while (!atEnd()) {
1840         readNext();
1841 
1842         if (isEndElement())
1843             break;
1844 
1845         if (isStartElement()) {
1846             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1847             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1848 
1849             tagValidator.validate(token);
1850 
1851             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1852                 const XsdAnnotation::Ptr annotation = parseAnnotation();
1853                 facet->addAnnotation(annotation);
1854             } else {
1855                 parseUnknown();
1856             }
1857         }
1858     }
1859 
1860     tagValidator.finalize();
1861 
1862     return facet;
1863 }
1864 
parseMinInclusiveFacet()1865 XsdFacet::Ptr XsdSchemaParser::parseMinInclusiveFacet()
1866 {
1867     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinInclusive, this);
1868 
1869     validateElement(XsdTagScope::MinInclusiveFacet);
1870 
1871     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
1872     facet->setType(XsdFacet::MinimumInclusive);
1873 
1874     // parse attributes
1875     if (hasAttribute(QString::fromLatin1("fixed"))) {
1876         const QString value = readAttribute(QString::fromLatin1("fixed"));
1877         const Boolean::Ptr fixed = Boolean::fromLexical(value);
1878         if (fixed->hasError()) {
1879             attributeContentError("fixed", "minInclusive", value, BuiltinTypes::xsBoolean);
1880             return facet;
1881         }
1882 
1883         facet->setFixed(fixed->as<Boolean>()->value());
1884     } else {
1885         facet->setFixed(false); // the default value
1886     }
1887 
1888     // as minInclusive can have a value of type anySimpleType, we just read
1889     // the string here and store it for later intepretation
1890     const QString value = readAttribute(QString::fromLatin1("value"));
1891     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
1892     if (string->hasError()) {
1893         attributeContentError("value", "minInclusive", value, BuiltinTypes::xsAnySimpleType);
1894         return facet;
1895     } else {
1896         facet->setValue(string);
1897     }
1898 
1899     validateIdAttribute("minInclusive");
1900 
1901     TagValidationHandler tagValidator(XsdTagScope::MinInclusiveFacet, this, m_namePool);
1902 
1903     while (!atEnd()) {
1904         readNext();
1905 
1906         if (isEndElement())
1907             break;
1908 
1909         if (isStartElement()) {
1910             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1911             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1912 
1913             tagValidator.validate(token);
1914 
1915             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1916                 const XsdAnnotation::Ptr annotation = parseAnnotation();
1917                 facet->addAnnotation(annotation);
1918             } else {
1919                 parseUnknown();
1920             }
1921         }
1922     }
1923 
1924     tagValidator.finalize();
1925 
1926     return facet;
1927 }
1928 
parseMaxExclusiveFacet()1929 XsdFacet::Ptr XsdSchemaParser::parseMaxExclusiveFacet()
1930 {
1931     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxExclusive, this);
1932 
1933     validateElement(XsdTagScope::MaxExclusiveFacet);
1934 
1935     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
1936     facet->setType(XsdFacet::MaximumExclusive);
1937 
1938     // parse attributes
1939     if (hasAttribute(QString::fromLatin1("fixed"))) {
1940         const QString value = readAttribute(QString::fromLatin1("fixed"));
1941         const Boolean::Ptr fixed = Boolean::fromLexical(value);
1942         if (fixed->hasError()) {
1943             attributeContentError("fixed", "maxExclusive", value, BuiltinTypes::xsBoolean);
1944             return facet;
1945         }
1946 
1947         facet->setFixed(fixed->as<Boolean>()->value());
1948     } else {
1949         facet->setFixed(false); // the default value
1950     }
1951 
1952     // as maxExclusive can have a value of type anySimpleType, we just read
1953     // the string here and store it for later intepretation
1954     const QString value = readAttribute(QString::fromLatin1("value"));
1955     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
1956     if (string->hasError()) {
1957         attributeContentError("value", "maxExclusive", value, BuiltinTypes::xsAnySimpleType);
1958         return facet;
1959     } else {
1960         facet->setValue(string);
1961     }
1962 
1963     validateIdAttribute("maxExclusive");
1964 
1965     TagValidationHandler tagValidator(XsdTagScope::MaxExclusiveFacet, this, m_namePool);
1966 
1967     while (!atEnd()) {
1968         readNext();
1969 
1970         if (isEndElement())
1971             break;
1972 
1973         if (isStartElement()) {
1974             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1975             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1976 
1977             tagValidator.validate(token);
1978 
1979             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1980                 const XsdAnnotation::Ptr annotation = parseAnnotation();
1981                 facet->addAnnotation(annotation);
1982             } else {
1983                 parseUnknown();
1984             }
1985         }
1986     }
1987 
1988     tagValidator.finalize();
1989 
1990     return facet;
1991 }
1992 
parseMaxInclusiveFacet()1993 XsdFacet::Ptr XsdSchemaParser::parseMaxInclusiveFacet()
1994 {
1995     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxInclusive, this);
1996 
1997     validateElement(XsdTagScope::MaxInclusiveFacet);
1998 
1999     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2000     facet->setType(XsdFacet::MaximumInclusive);
2001 
2002     // parse attributes
2003     if (hasAttribute(QString::fromLatin1("fixed"))) {
2004         const QString value = readAttribute(QString::fromLatin1("fixed"));
2005         const Boolean::Ptr fixed = Boolean::fromLexical(value);
2006         if (fixed->hasError()) {
2007             attributeContentError("fixed", "maxInclusive", value, BuiltinTypes::xsBoolean);
2008             return facet;
2009         }
2010 
2011         facet->setFixed(fixed->as<Boolean>()->value());
2012     } else {
2013         facet->setFixed(false); // the default value
2014     }
2015 
2016     // as maxInclusive can have a value of type anySimpleType, we just read
2017     // the string here and store it for later intepretation
2018     const QString value = readAttribute(QString::fromLatin1("value"));
2019     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
2020     if (string->hasError()) {
2021         attributeContentError("value", "maxInclusive", value, BuiltinTypes::xsAnySimpleType);
2022         return facet;
2023     } else {
2024         facet->setValue(string);
2025     }
2026 
2027     validateIdAttribute("maxInclusive");
2028 
2029     TagValidationHandler tagValidator(XsdTagScope::MaxInclusiveFacet, this, m_namePool);
2030 
2031     while (!atEnd()) {
2032         readNext();
2033 
2034         if (isEndElement())
2035             break;
2036 
2037         if (isStartElement()) {
2038             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2039             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2040 
2041             tagValidator.validate(token);
2042 
2043             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2044                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2045                 facet->addAnnotation(annotation);
2046             } else {
2047                 parseUnknown();
2048             }
2049         }
2050     }
2051 
2052     tagValidator.finalize();
2053 
2054     return facet;
2055 }
2056 
parseTotalDigitsFacet()2057 XsdFacet::Ptr XsdSchemaParser::parseTotalDigitsFacet()
2058 {
2059     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::TotalDigits, this);
2060 
2061     validateElement(XsdTagScope::TotalDigitsFacet);
2062 
2063     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2064     facet->setType(XsdFacet::TotalDigits);
2065 
2066     // parse attributes
2067     if (hasAttribute(QString::fromLatin1("fixed"))) {
2068         const QString value = readAttribute(QString::fromLatin1("fixed"));
2069         const Boolean::Ptr fixed = Boolean::fromLexical(value);
2070         if (fixed->hasError()) {
2071             attributeContentError("fixed", "totalDigits", value, BuiltinTypes::xsBoolean);
2072             return facet;
2073         }
2074 
2075         facet->setFixed(fixed->as<Boolean>()->value());
2076     } else {
2077         facet->setFixed(false); // the default value
2078     }
2079 
2080     const QString value = readAttribute(QString::fromLatin1("value"));
2081     DerivedInteger<TypePositiveInteger>::Ptr integer = DerivedInteger<TypePositiveInteger>::fromLexical(m_namePool, value);
2082     if (integer->hasError()) {
2083         attributeContentError("value", "totalDigits", value, BuiltinTypes::xsPositiveInteger);
2084         return facet;
2085     } else {
2086         facet->setValue(integer);
2087     }
2088 
2089     validateIdAttribute("totalDigits");
2090 
2091     TagValidationHandler tagValidator(XsdTagScope::TotalDigitsFacet, this, m_namePool);
2092 
2093     while (!atEnd()) {
2094         readNext();
2095 
2096         if (isEndElement())
2097             break;
2098 
2099         if (isStartElement()) {
2100             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2101             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2102 
2103             tagValidator.validate(token);
2104 
2105             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2106                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2107                 facet->addAnnotation(annotation);
2108             } else {
2109                 parseUnknown();
2110             }
2111         }
2112     }
2113 
2114     tagValidator.finalize();
2115 
2116     return facet;
2117 }
2118 
parseFractionDigitsFacet()2119 XsdFacet::Ptr XsdSchemaParser::parseFractionDigitsFacet()
2120 {
2121     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::FractionDigits, this);
2122 
2123     validateElement(XsdTagScope::FractionDigitsFacet);
2124 
2125     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2126     facet->setType(XsdFacet::FractionDigits);
2127 
2128     // parse attributes
2129     if (hasAttribute(QString::fromLatin1("fixed"))) {
2130         const QString value = readAttribute(QString::fromLatin1("fixed"));
2131         const Boolean::Ptr fixed = Boolean::fromLexical(value);
2132         if (fixed->hasError()) {
2133             attributeContentError("fixed", "fractionDigits", value, BuiltinTypes::xsBoolean);
2134             return facet;
2135         }
2136 
2137         facet->setFixed(fixed->as<Boolean>()->value());
2138     } else {
2139         facet->setFixed(false); // the default value
2140     }
2141 
2142     const QString value = readAttribute(QString::fromLatin1("value"));
2143     DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
2144     if (integer->hasError()) {
2145         attributeContentError("value", "fractionDigits", value, BuiltinTypes::xsNonNegativeInteger);
2146         return facet;
2147     } else {
2148         facet->setValue(integer);
2149     }
2150 
2151     validateIdAttribute("fractionDigits");
2152 
2153     TagValidationHandler tagValidator(XsdTagScope::FractionDigitsFacet, this, m_namePool);
2154 
2155     while (!atEnd()) {
2156         readNext();
2157 
2158         if (isEndElement())
2159             break;
2160 
2161         if (isStartElement()) {
2162             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2163             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2164 
2165             tagValidator.validate(token);
2166 
2167             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2168                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2169                 facet->addAnnotation(annotation);
2170             } else {
2171                 parseUnknown();
2172             }
2173         }
2174     }
2175 
2176     tagValidator.finalize();
2177 
2178     return facet;
2179 }
2180 
parseLengthFacet()2181 XsdFacet::Ptr XsdSchemaParser::parseLengthFacet()
2182 {
2183     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Length, this);
2184 
2185     validateElement(XsdTagScope::LengthFacet);
2186 
2187     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2188     facet->setType(XsdFacet::Length);
2189 
2190     // parse attributes
2191     if (hasAttribute(QString::fromLatin1("fixed"))) {
2192         const QString value = readAttribute(QString::fromLatin1("fixed"));
2193         const Boolean::Ptr fixed = Boolean::fromLexical(value);
2194         if (fixed->hasError()) {
2195             attributeContentError("fixed", "length", value, BuiltinTypes::xsBoolean);
2196             return facet;
2197         }
2198 
2199         facet->setFixed(fixed->as<Boolean>()->value());
2200     } else {
2201         facet->setFixed(false); // the default value
2202     }
2203 
2204     const QString value = readAttribute(QString::fromLatin1("value"));
2205     DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
2206     if (integer->hasError()) {
2207         attributeContentError("value", "length", value, BuiltinTypes::xsNonNegativeInteger);
2208         return facet;
2209     } else {
2210         facet->setValue(integer);
2211     }
2212 
2213     validateIdAttribute("length");
2214 
2215     TagValidationHandler tagValidator(XsdTagScope::LengthFacet, this, m_namePool);
2216 
2217     while (!atEnd()) {
2218         readNext();
2219 
2220         if (isEndElement())
2221             break;
2222 
2223         if (isStartElement()) {
2224             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2225             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2226 
2227             tagValidator.validate(token);
2228 
2229             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2230                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2231                 facet->addAnnotation(annotation);
2232             } else {
2233                 parseUnknown();
2234             }
2235         }
2236     }
2237 
2238     tagValidator.finalize();
2239 
2240     return facet;
2241 }
2242 
parseMinLengthFacet()2243 XsdFacet::Ptr XsdSchemaParser::parseMinLengthFacet()
2244 {
2245     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinLength, this);
2246 
2247     validateElement(XsdTagScope::MinLengthFacet);
2248 
2249     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2250     facet->setType(XsdFacet::MinimumLength);
2251 
2252     // parse attributes
2253     if (hasAttribute(QString::fromLatin1("fixed"))) {
2254         const QString value = readAttribute(QString::fromLatin1("fixed"));
2255         const Boolean::Ptr fixed = Boolean::fromLexical(value);
2256         if (fixed->hasError()) {
2257             attributeContentError("fixed", "minLength", value, BuiltinTypes::xsBoolean);
2258             return facet;
2259         }
2260 
2261         facet->setFixed(fixed->as<Boolean>()->value());
2262     } else {
2263         facet->setFixed(false); // the default value
2264     }
2265 
2266     const QString value = readAttribute(QString::fromLatin1("value"));
2267     DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
2268     if (integer->hasError()) {
2269         attributeContentError("value", "minLength", value, BuiltinTypes::xsNonNegativeInteger);
2270         return facet;
2271     } else {
2272         facet->setValue(integer);
2273     }
2274 
2275     validateIdAttribute("minLength");
2276 
2277     TagValidationHandler tagValidator(XsdTagScope::MinLengthFacet, this, m_namePool);
2278 
2279     while (!atEnd()) {
2280         readNext();
2281 
2282         if (isEndElement())
2283             break;
2284 
2285         if (isStartElement()) {
2286             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2287             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2288 
2289             tagValidator.validate(token);
2290 
2291             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2292                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2293                 facet->addAnnotation(annotation);
2294             } else {
2295                 parseUnknown();
2296             }
2297         }
2298     }
2299 
2300     tagValidator.finalize();
2301 
2302     return facet;
2303 }
2304 
parseMaxLengthFacet()2305 XsdFacet::Ptr XsdSchemaParser::parseMaxLengthFacet()
2306 {
2307     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxLength, this);
2308 
2309     validateElement(XsdTagScope::MaxLengthFacet);
2310 
2311     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2312     facet->setType(XsdFacet::MaximumLength);
2313 
2314     // parse attributes
2315     if (hasAttribute(QString::fromLatin1("fixed"))) {
2316         const QString value = readAttribute(QString::fromLatin1("fixed"));
2317         const Boolean::Ptr fixed = Boolean::fromLexical(value);
2318         if (fixed->hasError()) {
2319             attributeContentError("fixed", "maxLength", value, BuiltinTypes::xsBoolean);
2320             return facet;
2321         }
2322 
2323         facet->setFixed(fixed->as<Boolean>()->value());
2324     } else {
2325         facet->setFixed(false); // the default value
2326     }
2327 
2328     const QString value = readAttribute(QString::fromLatin1("value"));
2329     DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
2330     if (integer->hasError()) {
2331         attributeContentError("value", "maxLength", value, BuiltinTypes::xsNonNegativeInteger);
2332         return facet;
2333     } else {
2334         facet->setValue(integer);
2335     }
2336 
2337     validateIdAttribute("maxLength");
2338 
2339     TagValidationHandler tagValidator(XsdTagScope::MaxLengthFacet, this, m_namePool);
2340 
2341     while (!atEnd()) {
2342         readNext();
2343 
2344         if (isEndElement())
2345             break;
2346 
2347         if (isStartElement()) {
2348             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2349             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2350 
2351             tagValidator.validate(token);
2352 
2353             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2354                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2355                 facet->addAnnotation(annotation);
2356             } else {
2357                 parseUnknown();
2358             }
2359         }
2360     }
2361 
2362     tagValidator.finalize();
2363 
2364     return facet;
2365 }
2366 
parseEnumerationFacet()2367 XsdFacet::Ptr XsdSchemaParser::parseEnumerationFacet()
2368 {
2369     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Enumeration, this);
2370 
2371     validateElement(XsdTagScope::EnumerationFacet);
2372 
2373     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2374     facet->setType(XsdFacet::Enumeration);
2375 
2376     // parse attributes
2377     facet->setFixed(false); // not defined in schema, but can't hurt
2378 
2379     const QString value = readAttribute(QString::fromLatin1("value"));
2380 
2381     // as enumeration can have a value of type anySimpleType, we just read
2382     // the string here and store it for later intepretation
2383     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
2384     if (string->hasError()) {
2385         attributeContentError("value", "enumeration", value);
2386         return facet;
2387     } else {
2388         AtomicValue::List multiValue;
2389         multiValue << string;
2390         facet->setMultiValue(multiValue);
2391     }
2392     m_schemaResolver->addEnumerationFacetValue(string, m_namespaceSupport);
2393 
2394     validateIdAttribute("enumeration");
2395 
2396     TagValidationHandler tagValidator(XsdTagScope::EnumerationFacet, this, m_namePool);
2397 
2398     while (!atEnd()) {
2399         readNext();
2400 
2401         if (isEndElement())
2402             break;
2403 
2404         if (isStartElement()) {
2405             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2406             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2407 
2408             tagValidator.validate(token);
2409 
2410             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2411                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2412                 facet->addAnnotation(annotation);
2413             } else {
2414                 parseUnknown();
2415             }
2416         }
2417     }
2418 
2419     tagValidator.finalize();
2420 
2421     return facet;
2422 }
2423 
parseWhiteSpaceFacet()2424 XsdFacet::Ptr XsdSchemaParser::parseWhiteSpaceFacet()
2425 {
2426     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::WhiteSpace, this);
2427 
2428     validateElement(XsdTagScope::WhiteSpaceFacet);
2429 
2430     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2431     facet->setType(XsdFacet::WhiteSpace);
2432 
2433     // parse attributes
2434     if (hasAttribute(QString::fromLatin1("fixed"))) {
2435         const QString value = readAttribute(QString::fromLatin1("fixed"));
2436         const Boolean::Ptr fixed = Boolean::fromLexical(value);
2437         if (fixed->hasError()) {
2438             attributeContentError("fixed", "whiteSpace", value, BuiltinTypes::xsBoolean);
2439             return facet;
2440         }
2441 
2442         facet->setFixed(fixed->as<Boolean>()->value());
2443     } else {
2444         facet->setFixed(false); // the default value
2445     }
2446 
2447     const QString value = readAttribute(QString::fromLatin1("value"));
2448     if (value != XsdSchemaToken::toString(XsdSchemaToken::Collapse) &&
2449         value != XsdSchemaToken::toString(XsdSchemaToken::Preserve) &&
2450         value != XsdSchemaToken::toString(XsdSchemaToken::Replace)) {
2451         attributeContentError("value", "whiteSpace", value);
2452         return facet;
2453     } else {
2454         DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
2455         if (string->hasError()) {
2456             attributeContentError("value", "whiteSpace", value);
2457             return facet;
2458         } else {
2459             facet->setValue(string);
2460         }
2461     }
2462 
2463     validateIdAttribute("whiteSpace");
2464 
2465     TagValidationHandler tagValidator(XsdTagScope::WhiteSpaceFacet, this, m_namePool);
2466 
2467     while (!atEnd()) {
2468         readNext();
2469 
2470         if (isEndElement())
2471             break;
2472 
2473         if (isStartElement()) {
2474             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2475             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2476 
2477             tagValidator.validate(token);
2478 
2479             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2480                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2481                 facet->addAnnotation(annotation);
2482             } else {
2483                 parseUnknown();
2484             }
2485         }
2486     }
2487 
2488     tagValidator.finalize();
2489 
2490     return facet;
2491 }
2492 
parsePatternFacet()2493 XsdFacet::Ptr XsdSchemaParser::parsePatternFacet()
2494 {
2495     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Pattern, this);
2496 
2497     validateElement(XsdTagScope::PatternFacet);
2498 
2499     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2500     facet->setType(XsdFacet::Pattern);
2501 
2502     // parse attributes
2503 
2504     // as pattern can have a value of type anySimpleType, we just read
2505     // the string here and store it for later intepretation
2506     const QString value = readAttribute(QString::fromLatin1("value"));
2507     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
2508     if (string->hasError()) {
2509         attributeContentError("value", "pattern", value);
2510         return facet;
2511     } else {
2512         AtomicValue::List multiValue;
2513         multiValue << string;
2514         facet->setMultiValue(multiValue);
2515     }
2516 
2517     validateIdAttribute("pattern");
2518 
2519     TagValidationHandler tagValidator(XsdTagScope::PatternFacet, this, m_namePool);
2520 
2521     while (!atEnd()) {
2522         readNext();
2523 
2524         if (isEndElement())
2525             break;
2526 
2527         if (isStartElement()) {
2528             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2529             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2530 
2531             tagValidator.validate(token);
2532 
2533             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2534                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2535                 facet->addAnnotation(annotation);
2536             } else {
2537                 parseUnknown();
2538             }
2539         }
2540     }
2541 
2542     tagValidator.finalize();
2543 
2544     return facet;
2545 }
2546 
parseAssertionFacet()2547 XsdFacet::Ptr XsdSchemaParser::parseAssertionFacet()
2548 {
2549     // this is just a wrapper function around the parseAssertion() method
2550 
2551     const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assertion, XsdTagScope::Assertion);
2552 
2553     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2554     facet->setType(XsdFacet::Assertion);
2555     facet->setAssertions(XsdAssertion::List() << assertion);
2556 
2557     return facet;
2558 }
2559 
parseGlobalComplexType()2560 XsdComplexType::Ptr XsdSchemaParser::parseGlobalComplexType()
2561 {
2562     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this);
2563 
2564     validateElement(XsdTagScope::GlobalComplexType);
2565 
2566     bool hasTypeSpecified = false;
2567     bool hasComplexContent = false;
2568 
2569     const XsdComplexType::Ptr complexType(new XsdComplexType());
2570 
2571     // parse attributes
2572     if (hasAttribute(QString::fromLatin1("abstract"))) {
2573         const QString abstract = readAttribute(QString::fromLatin1("abstract"));
2574 
2575         const Boolean::Ptr value = Boolean::fromLexical(abstract);
2576         if (value->hasError()) {
2577             attributeContentError("abstract", "complexType", abstract, BuiltinTypes::xsBoolean);
2578             return complexType;
2579         }
2580 
2581         complexType->setIsAbstract(value->as<Boolean>()->value());
2582     } else {
2583         complexType->setIsAbstract(false);  // default value
2584     }
2585 
2586     complexType->setProhibitedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint, "complexType"));
2587     complexType->setDerivationConstraints(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "complexType"));
2588 
2589     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("complexType"));
2590     complexType->setName(objectName);
2591 
2592     bool effectiveMixed = false;
2593     if (hasAttribute(QString::fromLatin1("mixed"))) {
2594         const QString mixed = readAttribute(QString::fromLatin1("mixed"));
2595 
2596         const Boolean::Ptr value = Boolean::fromLexical(mixed);
2597         if (value->hasError()) {
2598             attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean);
2599             return complexType;
2600         }
2601 
2602         effectiveMixed = value->as<Boolean>()->value();
2603     }
2604 
2605     validateIdAttribute("complexType");
2606 
2607     TagValidationHandler tagValidator(XsdTagScope::GlobalComplexType, this, m_namePool);
2608 
2609     while (!atEnd()) {
2610         readNext();
2611 
2612         if (isEndElement())
2613             break;
2614 
2615         if (isStartElement()) {
2616             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2617             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2618 
2619             tagValidator.validate(token);
2620 
2621             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2622                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2623                 complexType->addAnnotation(annotation);
2624             } else if (isSchemaTag(XsdSchemaToken::SimpleContent, token, namespaceToken)) {
2625                 if (effectiveMixed) {
2626                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
2627                                             .arg(formatElement("complexType"))
2628                                             .arg(formatElement("simpleContent"))
2629                                             .arg(formatAttribute("mixed")));
2630                     return complexType;
2631                 }
2632 
2633                 parseSimpleContent(complexType);
2634                 hasTypeSpecified = true;
2635             } else if (isSchemaTag(XsdSchemaToken::ComplexContent, token, namespaceToken)) {
2636                 bool mixed;
2637                 parseComplexContent(complexType, &mixed);
2638                 hasTypeSpecified = true;
2639 
2640                 effectiveMixed = (effectiveMixed || mixed);
2641                 hasComplexContent = true;
2642             } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
2643                 const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
2644                 complexType->contentType()->setOpenContent(openContent);
2645                 hasComplexContent = true;
2646             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
2647                 const XsdParticle::Ptr particle(new XsdParticle());
2648                 const XsdTerm::Ptr term = parseReferredGroup(particle);
2649                 particle->setTerm(term);
2650                 complexType->contentType()->setParticle(particle);
2651 
2652                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2653                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2654                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2655                 hasComplexContent = true;
2656             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
2657                 const XsdParticle::Ptr particle(new XsdParticle());
2658                 const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
2659                 particle->setTerm(term);
2660                 complexType->contentType()->setParticle(particle);
2661 
2662                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2663                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2664                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2665                 hasComplexContent = true;
2666             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
2667                 const XsdParticle::Ptr particle(new XsdParticle());
2668                 const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
2669                 particle->setTerm(term);
2670                 complexType->contentType()->setParticle(particle);
2671 
2672                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2673                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2674                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2675                 hasComplexContent = true;
2676             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
2677                 const XsdParticle::Ptr particle(new XsdParticle());
2678                 const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
2679                 particle->setTerm(term);
2680                 complexType->contentType()->setParticle(particle);
2681 
2682                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2683                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2684                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2685                 hasComplexContent = true;
2686             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
2687                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
2688                 complexType->addAttributeUse(attributeUse);
2689 
2690                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2691                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2692                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2693                 hasComplexContent = true;
2694             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
2695                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
2696                 complexType->addAttributeUse(attributeUse);
2697 
2698                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2699                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2700                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2701                 hasComplexContent = true;
2702             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
2703                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
2704                 complexType->setAttributeWildcard(wildcard);
2705 
2706                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2707                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2708                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2709                 hasComplexContent = true;
2710             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
2711                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
2712                 complexType->addAssertion(assertion);
2713             } else {
2714                 parseUnknown();
2715             }
2716         }
2717     }
2718 
2719     tagValidator.finalize();
2720 
2721     if (!hasTypeSpecified) {
2722         complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2723         complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2724         hasComplexContent = true;
2725     }
2726 
2727     if (hasComplexContent == true) {
2728         resolveComplexContentType(complexType, effectiveMixed);
2729     }
2730 
2731     return complexType;
2732 }
2733 
parseLocalComplexType()2734 XsdComplexType::Ptr XsdSchemaParser::parseLocalComplexType()
2735 {
2736     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this);
2737 
2738     validateElement(XsdTagScope::LocalComplexType);
2739 
2740     bool hasTypeSpecified = false;
2741     bool hasComplexContent = true;
2742 
2743     const XsdComplexType::Ptr complexType(new XsdComplexType());
2744     complexType->setName(m_parserContext->createAnonymousName(m_targetNamespace));
2745 
2746     // parse attributes
2747     bool effectiveMixed = false;
2748     if (hasAttribute(QString::fromLatin1("mixed"))) {
2749         const QString mixed = readAttribute(QString::fromLatin1("mixed"));
2750 
2751         const Boolean::Ptr value = Boolean::fromLexical(mixed);
2752         if (value->hasError()) {
2753             attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean);
2754             return complexType;
2755         }
2756 
2757         effectiveMixed = value->as<Boolean>()->value();
2758     }
2759 
2760     validateIdAttribute("complexType");
2761 
2762     TagValidationHandler tagValidator(XsdTagScope::LocalComplexType, this, m_namePool);
2763 
2764     while (!atEnd()) {
2765         readNext();
2766 
2767         if (isEndElement())
2768             break;
2769 
2770         if (isStartElement()) {
2771             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2772             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2773 
2774             tagValidator.validate(token);
2775 
2776             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2777                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2778                 complexType->addAnnotation(annotation);
2779             } else if (isSchemaTag(XsdSchemaToken::SimpleContent, token, namespaceToken)) {
2780                 parseSimpleContent(complexType);
2781                 hasTypeSpecified = true;
2782             } else if (isSchemaTag(XsdSchemaToken::ComplexContent, token, namespaceToken)) {
2783                 bool mixed;
2784                 parseComplexContent(complexType, &mixed);
2785                 hasTypeSpecified = true;
2786 
2787                 effectiveMixed = (effectiveMixed || mixed);
2788                 hasComplexContent = true;
2789             } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
2790                 const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
2791                 complexType->contentType()->setOpenContent(openContent);
2792                 hasComplexContent = true;
2793             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
2794                 const XsdParticle::Ptr particle(new XsdParticle());
2795                 const XsdTerm::Ptr term = parseReferredGroup(particle);
2796                 particle->setTerm(term);
2797                 complexType->contentType()->setParticle(particle);
2798 
2799                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2800                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2801                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2802                 hasComplexContent = true;
2803             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
2804                 const XsdParticle::Ptr particle(new XsdParticle());
2805                 const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
2806                 particle->setTerm(term);
2807                 complexType->contentType()->setParticle(particle);
2808 
2809                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2810                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2811                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2812                 hasComplexContent = true;
2813             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
2814                 const XsdParticle::Ptr particle(new XsdParticle());
2815                 const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
2816                 particle->setTerm(term);
2817                 complexType->contentType()->setParticle(particle);
2818 
2819                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2820                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2821                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2822                 hasComplexContent = true;
2823             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
2824                 const XsdParticle::Ptr particle(new XsdParticle());
2825                 const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
2826                 particle->setTerm(term);
2827                 complexType->contentType()->setParticle(particle);
2828 
2829                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2830                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2831                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2832                 hasComplexContent = true;
2833             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
2834                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
2835                 complexType->addAttributeUse(attributeUse);
2836 
2837                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2838                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2839                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2840                 hasComplexContent = true;
2841             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
2842                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
2843                 complexType->addAttributeUse(attributeUse);
2844 
2845                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2846                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2847                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2848                 hasComplexContent = true;
2849             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
2850                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
2851                 complexType->setAttributeWildcard(wildcard);
2852 
2853                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2854                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
2855                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2856                 hasComplexContent = true;
2857             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
2858                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
2859                 complexType->addAssertion(assertion);
2860             } else {
2861                 parseUnknown();
2862             }
2863         }
2864     }
2865 
2866     tagValidator.finalize();
2867 
2868     if (!hasTypeSpecified) {
2869         complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2870         complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2871         hasComplexContent = true;
2872     }
2873 
2874     if (hasComplexContent == true) {
2875         resolveComplexContentType(complexType, effectiveMixed);
2876     }
2877 
2878     return complexType;
2879 }
2880 
resolveComplexContentType(const XsdComplexType::Ptr & complexType,bool effectiveMixed)2881 void XsdSchemaParser::resolveComplexContentType(const XsdComplexType::Ptr &complexType, bool effectiveMixed)
2882 {
2883     // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctcc.common
2884 
2885     // 1
2886     // the effectiveMixed contains the effective mixed value
2887 
2888     // 2
2889     bool hasEmptyContent = false;
2890     if (!complexType->contentType()->particle()) {
2891         hasEmptyContent = true; // 2.1.1
2892     } else {
2893         if (complexType->contentType()->particle()->term()->isModelGroup()) {
2894             const XsdModelGroup::Ptr group = complexType->contentType()->particle()->term();
2895             if (group->compositor() == XsdModelGroup::SequenceCompositor || group->compositor() == XsdModelGroup::AllCompositor) {
2896                 if (group->particles().isEmpty())
2897                     hasEmptyContent = true; // 2.1.2
2898             } else if (group->compositor() == XsdModelGroup::ChoiceCompositor) {
2899                 if ((complexType->contentType()->particle()->minimumOccurs() == 0) && group->particles().isEmpty())
2900                     hasEmptyContent = true; // 2.1.3
2901             }
2902 
2903             if ((complexType->contentType()->particle()->maximumOccursUnbounded() == false) && (complexType->contentType()->particle()->maximumOccurs() == 0))
2904                 hasEmptyContent = true; // 2.1.4
2905         }
2906     }
2907 
2908     const XsdParticle::Ptr explicitContent = (hasEmptyContent ? XsdParticle::Ptr() : complexType->contentType()->particle());
2909 
2910     // do all the other work (3, 4, 5 and 6) in the resolver, as they need access to the base type object
2911     m_schemaResolver->addComplexContentType(complexType, explicitContent, effectiveMixed);
2912 }
2913 
parseSimpleContent(const XsdComplexType::Ptr & complexType)2914 void XsdSchemaParser::parseSimpleContent(const XsdComplexType::Ptr &complexType)
2915 {
2916     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleContent, this);
2917 
2918     validateElement(XsdTagScope::SimpleContent);
2919 
2920     complexType->contentType()->setVariety(XsdComplexType::ContentType::Simple);
2921 
2922     // parse attributes
2923     validateIdAttribute("simpleContent");
2924 
2925     TagValidationHandler tagValidator(XsdTagScope::SimpleContent, this, m_namePool);
2926 
2927     while (!atEnd()) {
2928         readNext();
2929 
2930         if (isEndElement())
2931             break;
2932 
2933         if (isStartElement()) {
2934             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2935             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2936 
2937             tagValidator.validate(token);
2938 
2939             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2940                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2941                 complexType->addAnnotation(annotation);
2942             } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
2943                 parseSimpleContentRestriction(complexType);
2944             } else if (isSchemaTag(XsdSchemaToken::Extension, token, namespaceToken)) {
2945                 parseSimpleContentExtension(complexType);
2946             } else {
2947                 parseUnknown();
2948             }
2949         }
2950     }
2951 
2952     tagValidator.finalize();
2953 }
2954 
parseSimpleContentRestriction(const XsdComplexType::Ptr & complexType)2955 void XsdSchemaParser::parseSimpleContentRestriction(const XsdComplexType::Ptr &complexType)
2956 {
2957     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
2958 
2959     validateElement(XsdTagScope::SimpleContentRestriction);
2960 
2961     complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2962 
2963     // parse attributes
2964     const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "restriction");
2965     QXmlName typeName;
2966     convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
2967 
2968     validateIdAttribute("restriction");
2969 
2970     XsdFacet::Hash facets;
2971     QList<XsdFacet::Ptr> patternFacets;
2972     QList<XsdFacet::Ptr> enumerationFacets;
2973     QList<XsdFacet::Ptr> assertionFacets;
2974 
2975     TagValidationHandler tagValidator(XsdTagScope::SimpleContentRestriction, this, m_namePool);
2976 
2977     while (!atEnd()) {
2978         readNext();
2979 
2980         if (isEndElement())
2981             break;
2982 
2983         if (isStartElement()) {
2984             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2985             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2986 
2987             tagValidator.validate(token);
2988 
2989             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2990                 const XsdAnnotation::Ptr annotation = parseAnnotation();
2991                 complexType->addAnnotation(annotation);
2992             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
2993                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
2994                 type->setContext(complexType); //TODO: investigate what the schema spec really wants here?!?
2995                 complexType->contentType()->setSimpleType(type);
2996 
2997                 // add it to list of anonymous types as well
2998                 addAnonymousType(type);
2999             } else if (isSchemaTag(XsdSchemaToken::MinExclusive, token, namespaceToken)) {
3000                 const XsdFacet::Ptr facet = parseMinExclusiveFacet();
3001                 addFacet(facet, facets, complexType);
3002             } else if (isSchemaTag(XsdSchemaToken::MinInclusive, token, namespaceToken)) {
3003                 const XsdFacet::Ptr facet = parseMinInclusiveFacet();
3004                 addFacet(facet, facets, complexType);
3005             } else if (isSchemaTag(XsdSchemaToken::MaxExclusive, token, namespaceToken)) {
3006                 const XsdFacet::Ptr facet = parseMaxExclusiveFacet();
3007                 addFacet(facet, facets, complexType);
3008             } else if (isSchemaTag(XsdSchemaToken::MaxInclusive, token, namespaceToken)) {
3009                 const XsdFacet::Ptr facet = parseMaxInclusiveFacet();
3010                 addFacet(facet, facets, complexType);
3011             } else if (isSchemaTag(XsdSchemaToken::TotalDigits, token, namespaceToken)) {
3012                 const XsdFacet::Ptr facet = parseTotalDigitsFacet();
3013                 addFacet(facet, facets, complexType);
3014             } else if (isSchemaTag(XsdSchemaToken::FractionDigits, token, namespaceToken)) {
3015                 const XsdFacet::Ptr facet = parseFractionDigitsFacet();
3016                 addFacet(facet, facets, complexType);
3017             } else if (isSchemaTag(XsdSchemaToken::Length, token, namespaceToken)) {
3018                 const XsdFacet::Ptr facet = parseLengthFacet();
3019                 addFacet(facet, facets, complexType);
3020             } else if (isSchemaTag(XsdSchemaToken::MinLength, token, namespaceToken)) {
3021                 const XsdFacet::Ptr facet = parseMinLengthFacet();
3022                 addFacet(facet, facets, complexType);
3023             } else if (isSchemaTag(XsdSchemaToken::MaxLength, token, namespaceToken)) {
3024                 const XsdFacet::Ptr facet = parseMaxLengthFacet();
3025                 addFacet(facet, facets, complexType);
3026             } else if (isSchemaTag(XsdSchemaToken::Enumeration, token, namespaceToken)) {
3027                 const XsdFacet::Ptr facet = parseEnumerationFacet();
3028                 enumerationFacets.append(facet);
3029             } else if (isSchemaTag(XsdSchemaToken::WhiteSpace, token, namespaceToken)) {
3030                 const XsdFacet::Ptr facet = parseWhiteSpaceFacet();
3031                 addFacet(facet, facets, complexType);
3032             } else if (isSchemaTag(XsdSchemaToken::Pattern, token, namespaceToken)) {
3033                 const XsdFacet::Ptr facet = parsePatternFacet();
3034                 patternFacets.append(facet);
3035             } else if (isSchemaTag(XsdSchemaToken::Assertion, token, namespaceToken)) {
3036                 const XsdFacet::Ptr facet = parseAssertionFacet();
3037                 assertionFacets.append(facet);
3038             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
3039                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
3040                 complexType->addAttributeUse(attributeUse);
3041             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
3042                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
3043                 complexType->addAttributeUse(attributeUse);
3044             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
3045                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
3046                 complexType->setAttributeWildcard(wildcard);
3047             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
3048                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
3049                 complexType->addAssertion(assertion);
3050             } else {
3051                 parseUnknown();
3052             }
3053         }
3054     }
3055 
3056     tagValidator.finalize();
3057 
3058     // merge all pattern facets into one multi value facet
3059     if (!patternFacets.isEmpty()) {
3060         const XsdFacet::Ptr patternFacet(new XsdFacet());
3061         patternFacet->setType(XsdFacet::Pattern);
3062 
3063         AtomicValue::List multiValue;
3064         for (int i = 0; i < patternFacets.count(); ++i)
3065             multiValue << patternFacets.at(i)->multiValue();
3066 
3067         patternFacet->setMultiValue(multiValue);
3068         addFacet(patternFacet, facets, complexType);
3069     }
3070 
3071     // merge all enumeration facets into one multi value facet
3072     if (!enumerationFacets.isEmpty()) {
3073         const XsdFacet::Ptr enumerationFacet(new XsdFacet());
3074         enumerationFacet->setType(XsdFacet::Enumeration);
3075 
3076         AtomicValue::List multiValue;
3077         for (int i = 0; i < enumerationFacets.count(); ++i)
3078             multiValue << enumerationFacets.at(i)->multiValue();
3079 
3080         enumerationFacet->setMultiValue(multiValue);
3081         addFacet(enumerationFacet, facets, complexType);
3082     }
3083 
3084     // merge all assertion facets into one facet
3085     if (!assertionFacets.isEmpty()) {
3086         const XsdFacet::Ptr assertionFacet(new XsdFacet());
3087         assertionFacet->setType(XsdFacet::Assertion);
3088 
3089         XsdAssertion::List assertions;
3090         for (int i = 0; i < assertionFacets.count(); ++i)
3091             assertions << assertionFacets.at(i)->assertions();
3092 
3093         assertionFacet->setAssertions(assertions);
3094         addFacet(assertionFacet, facets, complexType);
3095     }
3096 
3097     m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation(), facets); // add to resolver
3098 }
3099 
parseSimpleContentExtension(const XsdComplexType::Ptr & complexType)3100 void XsdSchemaParser::parseSimpleContentExtension(const XsdComplexType::Ptr &complexType)
3101 {
3102     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this);
3103 
3104     validateElement(XsdTagScope::SimpleContentExtension);
3105 
3106     complexType->setDerivationMethod(XsdComplexType::DerivationExtension);
3107 
3108     // parse attributes
3109     const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "extension");
3110     QXmlName typeName;
3111     convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
3112     m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver
3113 
3114     validateIdAttribute("extension");
3115 
3116     TagValidationHandler tagValidator(XsdTagScope::SimpleContentExtension, this, m_namePool);
3117 
3118     while (!atEnd()) {
3119         readNext();
3120 
3121         if (isEndElement())
3122             break;
3123 
3124         if (isStartElement()) {
3125             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3126             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3127 
3128             tagValidator.validate(token);
3129 
3130             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3131                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3132                 complexType->addAnnotation(annotation);
3133             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
3134                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
3135                 complexType->addAttributeUse(attributeUse);
3136             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
3137                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
3138                 complexType->addAttributeUse(attributeUse);
3139             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
3140                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
3141                 complexType->setAttributeWildcard(wildcard);
3142             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
3143                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
3144                 complexType->addAssertion(assertion);
3145             } else {
3146                 parseUnknown();
3147             }
3148         }
3149     }
3150 
3151     tagValidator.finalize();
3152 }
3153 
parseComplexContent(const XsdComplexType::Ptr & complexType,bool * mixed)3154 void XsdSchemaParser::parseComplexContent(const XsdComplexType::Ptr &complexType, bool *mixed)
3155 {
3156     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexContent, this);
3157 
3158     validateElement(XsdTagScope::ComplexContent);
3159 
3160     complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
3161 
3162     // parse attributes
3163     if (hasAttribute(QString::fromLatin1("mixed"))) {
3164         const QString mixedStr = readAttribute(QString::fromLatin1("mixed"));
3165 
3166         const Boolean::Ptr value = Boolean::fromLexical(mixedStr);
3167         if (value->hasError()) {
3168             attributeContentError("mixed", "complexType", mixedStr, BuiltinTypes::xsBoolean);
3169             return;
3170         }
3171 
3172         *mixed = value->as<Boolean>()->value();
3173     } else {
3174         *mixed = false;
3175     }
3176 
3177     validateIdAttribute("complexContent");
3178 
3179     TagValidationHandler tagValidator(XsdTagScope::ComplexContent, this, m_namePool);
3180 
3181     while (!atEnd()) {
3182         readNext();
3183 
3184         if (isEndElement())
3185             break;
3186 
3187         if (isStartElement()) {
3188             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3189             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3190 
3191             tagValidator.validate(token);
3192 
3193             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3194                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3195                 complexType->addAnnotation(annotation);
3196             } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
3197                 parseComplexContentRestriction(complexType);
3198             } else if (isSchemaTag(XsdSchemaToken::Extension, token, namespaceToken)) {
3199                 parseComplexContentExtension(complexType);
3200             } else {
3201                 parseUnknown();
3202             }
3203         }
3204     }
3205 
3206     tagValidator.finalize();
3207 }
3208 
parseComplexContentRestriction(const XsdComplexType::Ptr & complexType)3209 void XsdSchemaParser::parseComplexContentRestriction(const XsdComplexType::Ptr &complexType)
3210 {
3211     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
3212 
3213     validateElement(XsdTagScope::ComplexContentRestriction);
3214 
3215     complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
3216 
3217     // parse attributes
3218     const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "restriction");
3219     QXmlName typeName;
3220     convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
3221     m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver
3222 
3223     validateIdAttribute("restriction");
3224 
3225     TagValidationHandler tagValidator(XsdTagScope::ComplexContentRestriction, this, m_namePool);
3226 
3227     bool hasContent = false;
3228     while (!atEnd()) {
3229         readNext();
3230 
3231         if (isEndElement())
3232             break;
3233 
3234         if (isStartElement()) {
3235             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3236             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3237 
3238             tagValidator.validate(token);
3239 
3240             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3241                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3242                 complexType->addAnnotation(annotation);
3243             } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
3244                 const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
3245                 complexType->contentType()->setOpenContent(openContent);
3246                 hasContent = true;
3247             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
3248                 const XsdParticle::Ptr particle(new XsdParticle());
3249                 const XsdTerm::Ptr term = parseReferredGroup(particle);
3250                 particle->setTerm(term);
3251                 complexType->contentType()->setParticle(particle);
3252                 hasContent = true;
3253             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
3254                 const XsdParticle::Ptr particle(new XsdParticle());
3255                 const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
3256                 particle->setTerm(term);
3257                 complexType->contentType()->setParticle(particle);
3258                 hasContent = true;
3259             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
3260                 const XsdParticle::Ptr particle(new XsdParticle());
3261                 const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
3262                 particle->setTerm(term);
3263                 complexType->contentType()->setParticle(particle);
3264                 hasContent = true;
3265             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
3266                 const XsdParticle::Ptr particle(new XsdParticle());
3267                 const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
3268                 particle->setTerm(term);
3269                 complexType->contentType()->setParticle(particle);
3270                 hasContent = true;
3271             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
3272                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
3273                 complexType->addAttributeUse(attributeUse);
3274             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
3275                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
3276                 complexType->addAttributeUse(attributeUse);
3277             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
3278                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
3279                 complexType->setAttributeWildcard(wildcard);
3280             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
3281                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
3282                 complexType->addAssertion(assertion);
3283             } else {
3284                 parseUnknown();
3285             }
3286         }
3287     }
3288 
3289     if (!hasContent)
3290         complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty);
3291 
3292     tagValidator.finalize();
3293 }
3294 
parseComplexContentExtension(const XsdComplexType::Ptr & complexType)3295 void XsdSchemaParser::parseComplexContentExtension(const XsdComplexType::Ptr &complexType)
3296 {
3297     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this);
3298 
3299     validateElement(XsdTagScope::ComplexContentExtension);
3300 
3301     complexType->setDerivationMethod(XsdComplexType::DerivationExtension);
3302 
3303     // parse attributes
3304     const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "extension");
3305     QXmlName typeName;
3306     convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
3307     m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver
3308 
3309     validateIdAttribute("extension");
3310 
3311     TagValidationHandler tagValidator(XsdTagScope::ComplexContentExtension, this, m_namePool);
3312 
3313     bool hasContent = false;
3314     while (!atEnd()) {
3315         readNext();
3316 
3317         if (isEndElement())
3318             break;
3319 
3320         if (isStartElement()) {
3321             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3322             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3323 
3324             tagValidator.validate(token);
3325 
3326             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3327                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3328                 complexType->addAnnotation(annotation);
3329             } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
3330                 const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
3331                 complexType->contentType()->setOpenContent(openContent);
3332                 hasContent = true;
3333             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
3334                 const XsdParticle::Ptr particle(new XsdParticle());
3335                 const XsdTerm::Ptr term = parseReferredGroup(particle);
3336                 particle->setTerm(term);
3337                 complexType->contentType()->setParticle(particle);
3338                 hasContent = true;
3339             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
3340                 const XsdParticle::Ptr particle(new XsdParticle());
3341                 const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
3342                 particle->setTerm(term);
3343                 complexType->contentType()->setParticle(particle);
3344                 hasContent = true;
3345             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
3346                 const XsdParticle::Ptr particle(new XsdParticle());
3347                 const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
3348                 particle->setTerm(term);
3349                 complexType->contentType()->setParticle(particle);
3350                 hasContent = true;
3351             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
3352                 const XsdParticle::Ptr particle(new XsdParticle());
3353                 const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
3354                 particle->setTerm(term);
3355                 complexType->contentType()->setParticle(particle);
3356                 hasContent = true;
3357             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
3358                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
3359                 complexType->addAttributeUse(attributeUse);
3360             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
3361                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
3362                 complexType->addAttributeUse(attributeUse);
3363             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
3364                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
3365                 complexType->setAttributeWildcard(wildcard);
3366             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
3367                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
3368                 complexType->addAssertion(assertion);
3369             } else {
3370                 parseUnknown();
3371             }
3372         }
3373     }
3374 
3375     if (!hasContent)
3376         complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty);
3377 
3378     tagValidator.finalize();
3379 }
3380 
3381 
parseAssertion(const XsdSchemaToken::NodeName & nodeName,const XsdTagScope::Type & tag)3382 XsdAssertion::Ptr XsdSchemaParser::parseAssertion(const XsdSchemaToken::NodeName &nodeName, const XsdTagScope::Type &tag)
3383 {
3384     const ElementNamespaceHandler namespaceHandler(nodeName, this);
3385 
3386     validateElement(tag);
3387 
3388     const XsdAssertion::Ptr assertion(new XsdAssertion());
3389 
3390     // parse attributes
3391 
3392     const XsdXPathExpression::Ptr expression = readXPathExpression("assertion");
3393     assertion->setTest(expression);
3394 
3395     const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "assertion");
3396     expression->setExpression(test);
3397 
3398     validateIdAttribute("assertion");
3399 
3400     TagValidationHandler tagValidator(tag, this, m_namePool);
3401 
3402     while (!atEnd()) {
3403         readNext();
3404 
3405         if (isEndElement())
3406             break;
3407 
3408         if (isStartElement()) {
3409             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3410             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3411 
3412             tagValidator.validate(token);
3413 
3414             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3415                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3416                 assertion->addAnnotation(annotation);
3417             } else {
3418                 parseUnknown();
3419             }
3420         }
3421     }
3422 
3423     tagValidator.finalize();
3424 
3425     return assertion;
3426 }
3427 
parseOpenContent()3428 XsdComplexType::OpenContent::Ptr XsdSchemaParser::parseOpenContent()
3429 {
3430     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::OpenContent, this);
3431 
3432     validateElement(XsdTagScope::OpenContent);
3433 
3434     const XsdComplexType::OpenContent::Ptr openContent(new XsdComplexType::OpenContent());
3435 
3436     if (hasAttribute(QString::fromLatin1("mode"))) {
3437         const QString mode = readAttribute(QString::fromLatin1("mode"));
3438 
3439         if (mode == QString::fromLatin1("none")) {
3440             m_defaultOpenContent->setMode(XsdComplexType::OpenContent::None);
3441         } else if (mode == QString::fromLatin1("interleave")) {
3442             m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave);
3443         } else if (mode == QString::fromLatin1("suffix")) {
3444             m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Suffix);
3445         } else {
3446             attributeContentError("mode", "openContent", mode);
3447             return openContent;
3448         }
3449     } else {
3450         openContent->setMode(XsdComplexType::OpenContent::Interleave);
3451     }
3452 
3453     validateIdAttribute("openContent");
3454 
3455     TagValidationHandler tagValidator(XsdTagScope::OpenContent, this, m_namePool);
3456 
3457     while (!atEnd()) {
3458         readNext();
3459 
3460         if (isEndElement())
3461             break;
3462 
3463         if (isStartElement()) {
3464             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3465             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3466 
3467             tagValidator.validate(token);
3468 
3469             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3470                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3471                 openContent->addAnnotation(annotation);
3472             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
3473                 const XsdParticle::Ptr particle;
3474                 const XsdWildcard::Ptr wildcard = parseAny(particle);
3475                 openContent->setWildcard(wildcard);
3476             } else {
3477                 parseUnknown();
3478             }
3479         }
3480     }
3481 
3482     tagValidator.finalize();
3483 
3484     return openContent;
3485 }
3486 
parseNamedGroup()3487 XsdModelGroup::Ptr XsdSchemaParser::parseNamedGroup()
3488 {
3489     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this);
3490 
3491     validateElement(XsdTagScope::NamedGroup);
3492 
3493     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3494     XsdModelGroup::Ptr group;
3495 
3496     QXmlName objectName;
3497     if (hasAttribute(QString::fromLatin1("name"))) {
3498         objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("group"));
3499     }
3500 
3501     validateIdAttribute("group");
3502 
3503     TagValidationHandler tagValidator(XsdTagScope::NamedGroup, this, m_namePool);
3504 
3505     XsdAnnotation::Ptr annotation;
3506 
3507     while (!atEnd()) {
3508         readNext();
3509 
3510         if (isEndElement())
3511             break;
3512 
3513         if (isStartElement()) {
3514             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3515             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3516 
3517             tagValidator.validate(token);
3518 
3519             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3520                 annotation = parseAnnotation();
3521             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
3522                 group = parseAll(modelGroup);
3523             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
3524                 group = parseChoice(modelGroup);
3525             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
3526                 group = parseSequence(modelGroup);
3527             } else {
3528                 parseUnknown();
3529             }
3530         }
3531     }
3532 
3533     tagValidator.finalize();
3534 
3535     group->setName(objectName);
3536 
3537     if (annotation)
3538         group->addAnnotation(annotation);
3539 
3540     return group;
3541 }
3542 
parseReferredGroup(const XsdParticle::Ptr & particle)3543 XsdTerm::Ptr XsdSchemaParser::parseReferredGroup(const XsdParticle::Ptr &particle)
3544 {
3545     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this);
3546 
3547     validateElement(XsdTagScope::ReferredGroup);
3548 
3549     const XsdReference::Ptr reference(new XsdReference());
3550     reference->setType(XsdReference::ModelGroup);
3551     reference->setSourceLocation(currentSourceLocation());
3552 
3553     // parse attributes
3554     if (!parseMinMaxConstraint(particle, "group")) {
3555         return reference;
3556     }
3557 
3558     const QString value = readQNameAttribute(QString::fromLatin1("ref"), "group");
3559     QXmlName referenceName;
3560     convertName(value, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
3561     reference->setReferenceName(referenceName);
3562 
3563     validateIdAttribute("group");
3564 
3565     TagValidationHandler tagValidator(XsdTagScope::ReferredGroup, this, m_namePool);
3566 
3567     while (!atEnd()) {
3568         readNext();
3569 
3570         if (isEndElement())
3571             break;
3572 
3573         if (isStartElement()) {
3574             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3575             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3576 
3577             tagValidator.validate(token);
3578 
3579             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3580                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3581                 reference->addAnnotation(annotation);
3582             } else {
3583                 parseUnknown();
3584             }
3585         }
3586     }
3587 
3588     tagValidator.finalize();
3589 
3590     return reference;
3591 }
3592 
parseAll(const NamedSchemaComponent::Ptr & parent)3593 XsdModelGroup::Ptr XsdSchemaParser::parseAll(const NamedSchemaComponent::Ptr &parent)
3594 {
3595     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this);
3596 
3597     validateElement(XsdTagScope::All);
3598 
3599     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3600     modelGroup->setCompositor(XsdModelGroup::AllCompositor);
3601 
3602     validateIdAttribute("all");
3603 
3604     TagValidationHandler tagValidator(XsdTagScope::All, this, m_namePool);
3605 
3606     XsdParticle::List particles;
3607     while (!atEnd()) {
3608         readNext();
3609 
3610         if (isEndElement())
3611             break;
3612 
3613         if (isStartElement()) {
3614             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3615             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3616 
3617             tagValidator.validate(token);
3618 
3619             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3620                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3621                 modelGroup->addAnnotation(annotation);
3622             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
3623                 const XsdParticle::Ptr particle(new XsdParticle());
3624                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
3625                 particle->setTerm(term);
3626 
3627                 if (particle->maximumOccursUnbounded() || particle->maximumOccurs() > 1) {
3628                     error(QtXmlPatterns::tr("%1 attribute of %2 element must be %3 or %4.")
3629                                            .arg(formatAttribute("maxOccurs"))
3630                                            .arg(formatElement("all"))
3631                                            .arg(formatData("0"))
3632                                            .arg(formatData("1")));
3633                     return modelGroup;
3634                 }
3635 
3636                 particles.append(particle);
3637             } else {
3638                 parseUnknown();
3639             }
3640         }
3641     }
3642 
3643     modelGroup->setParticles(particles);
3644 
3645     tagValidator.finalize();
3646 
3647     return modelGroup;
3648 }
3649 
parseLocalAll(const XsdParticle::Ptr & particle,const NamedSchemaComponent::Ptr & parent)3650 XsdModelGroup::Ptr XsdSchemaParser::parseLocalAll(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
3651 {
3652     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this);
3653 
3654     validateElement(XsdTagScope::LocalAll);
3655 
3656     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3657     modelGroup->setCompositor(XsdModelGroup::AllCompositor);
3658 
3659     // parse attributes
3660     if (!parseMinMaxConstraint(particle, "all")) {
3661         return modelGroup;
3662     }
3663     if (particle->maximumOccursUnbounded() || particle->maximumOccurs() != 1) {
3664         error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3.")
3665                                .arg(formatAttribute("maxOccurs"))
3666                                .arg(formatElement("all"))
3667                                .arg(formatData("1")));
3668         return modelGroup;
3669     }
3670     if (particle->minimumOccurs() != 0 && particle->minimumOccurs() != 1) {
3671         error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4.")
3672                                .arg(formatAttribute("minOccurs"))
3673                                .arg(formatElement("all"))
3674                                .arg(formatData("0"))
3675                                .arg(formatData("1")));
3676         return modelGroup;
3677     }
3678 
3679     validateIdAttribute("all");
3680 
3681     TagValidationHandler tagValidator(XsdTagScope::LocalAll, this, m_namePool);
3682 
3683     XsdParticle::List particles;
3684     while (!atEnd()) {
3685         readNext();
3686 
3687         if (isEndElement())
3688             break;
3689 
3690         if (isStartElement()) {
3691             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3692             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3693 
3694             tagValidator.validate(token);
3695 
3696             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3697                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3698                 modelGroup->addAnnotation(annotation);
3699             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
3700                 const XsdParticle::Ptr particle(new XsdParticle());
3701                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
3702                 particle->setTerm(term);
3703 
3704                 if (particle->maximumOccursUnbounded() || particle->maximumOccurs() > 1) {
3705                     error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4.")
3706                                            .arg(formatAttribute("maxOccurs"))
3707                                            .arg(formatElement("all"))
3708                                            .arg(formatData("0"))
3709                                            .arg(formatData("1")));
3710                     return modelGroup;
3711                 }
3712 
3713                 particles.append(particle);
3714             } else {
3715                 parseUnknown();
3716             }
3717         }
3718     }
3719 
3720     modelGroup->setParticles(particles);
3721 
3722     tagValidator.finalize();
3723 
3724     return modelGroup;
3725 }
3726 
parseChoice(const NamedSchemaComponent::Ptr & parent)3727 XsdModelGroup::Ptr XsdSchemaParser::parseChoice(const NamedSchemaComponent::Ptr &parent)
3728 {
3729     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this);
3730 
3731     validateElement(XsdTagScope::Choice);
3732 
3733     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3734     modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor);
3735 
3736     validateIdAttribute("choice");
3737 
3738     XsdParticle::List particles;
3739 
3740     TagValidationHandler tagValidator(XsdTagScope::Choice, this, m_namePool);
3741 
3742     while (!atEnd()) {
3743         readNext();
3744 
3745         if (isEndElement())
3746             break;
3747 
3748         if (isStartElement()) {
3749             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3750             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3751 
3752             tagValidator.validate(token);
3753 
3754             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3755                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3756                 modelGroup->addAnnotation(annotation);
3757             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
3758                 const XsdParticle::Ptr particle(new XsdParticle());
3759                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
3760                 particle->setTerm(term);
3761                 particles.append(particle);
3762             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
3763                 const XsdParticle::Ptr particle(new XsdParticle());
3764                 const XsdTerm::Ptr term = parseReferredGroup(particle);
3765                 m_schemaResolver->addAllGroupCheck(term);
3766                 particle->setTerm(term);
3767                 particles.append(particle);
3768             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
3769                 const XsdParticle::Ptr particle(new XsdParticle());
3770                 const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
3771                 particle->setTerm(term);
3772                 particles.append(particle);
3773             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
3774                 const XsdParticle::Ptr particle(new XsdParticle());
3775                 const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
3776                 particle->setTerm(term);
3777                 particles.append(particle);
3778             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
3779                 const XsdParticle::Ptr particle(new XsdParticle());
3780                 const XsdTerm::Ptr term = parseAny(particle);
3781                 particle->setTerm(term);
3782                 particles.append(particle);
3783             } else {
3784                 parseUnknown();
3785             }
3786         }
3787     }
3788 
3789     modelGroup->setParticles(particles);
3790 
3791     tagValidator.finalize();
3792 
3793     return modelGroup;
3794 }
3795 
parseLocalChoice(const XsdParticle::Ptr & particle,const NamedSchemaComponent::Ptr & parent)3796 XsdModelGroup::Ptr XsdSchemaParser::parseLocalChoice(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
3797 {
3798     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this);
3799 
3800     validateElement(XsdTagScope::LocalChoice);
3801 
3802     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3803     modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor);
3804 
3805     // parse attributes
3806     if (!parseMinMaxConstraint(particle, "choice")) {
3807         return modelGroup;
3808     }
3809 
3810     validateIdAttribute("choice");
3811 
3812     XsdParticle::List particles;
3813 
3814     TagValidationHandler tagValidator(XsdTagScope::LocalChoice, this, m_namePool);
3815 
3816     while (!atEnd()) {
3817         readNext();
3818 
3819         if (isEndElement())
3820             break;
3821 
3822         if (isStartElement()) {
3823             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3824             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3825 
3826             tagValidator.validate(token);
3827 
3828             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3829                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3830                 modelGroup->addAnnotation(annotation);
3831             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
3832                 const XsdParticle::Ptr particle(new XsdParticle());
3833                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
3834                 particle->setTerm(term);
3835                 particles.append(particle);
3836             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
3837                 const XsdParticle::Ptr particle(new XsdParticle());
3838                 const XsdTerm::Ptr term = parseReferredGroup(particle);
3839                 m_schemaResolver->addAllGroupCheck(term);
3840                 particle->setTerm(term);
3841                 particles.append(particle);
3842             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
3843                 const XsdParticle::Ptr particle(new XsdParticle());
3844                 const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
3845                 particle->setTerm(term);
3846                 particles.append(particle);
3847             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
3848                 const XsdParticle::Ptr particle(new XsdParticle());
3849                 const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
3850                 particle->setTerm(term);
3851                 particles.append(particle);
3852             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
3853                 const XsdParticle::Ptr particle(new XsdParticle());
3854                 const XsdTerm::Ptr term = parseAny(particle);
3855                 particle->setTerm(term);
3856                 particles.append(particle);
3857             } else {
3858                 parseUnknown();
3859             }
3860         }
3861     }
3862 
3863     modelGroup->setParticles(particles);
3864 
3865     tagValidator.finalize();
3866 
3867     return modelGroup;
3868 }
3869 
parseSequence(const NamedSchemaComponent::Ptr & parent)3870 XsdModelGroup::Ptr XsdSchemaParser::parseSequence(const NamedSchemaComponent::Ptr &parent)
3871 {
3872     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this);
3873 
3874     validateElement(XsdTagScope::Sequence);
3875 
3876     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3877     modelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
3878 
3879     validateIdAttribute("sequence");
3880 
3881     XsdParticle::List particles;
3882 
3883     TagValidationHandler tagValidator(XsdTagScope::Sequence, this, m_namePool);
3884 
3885     while (!atEnd()) {
3886         readNext();
3887 
3888         if (isEndElement())
3889             break;
3890 
3891         if (isStartElement()) {
3892             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3893             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3894 
3895             tagValidator.validate(token);
3896 
3897             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3898                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3899                 modelGroup->addAnnotation(annotation);
3900             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
3901                 const XsdParticle::Ptr particle(new XsdParticle());
3902                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
3903                 particle->setTerm(term);
3904                 particles.append(particle);
3905             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
3906                 const XsdParticle::Ptr particle(new XsdParticle());
3907                 const XsdTerm::Ptr term = parseReferredGroup(particle);
3908                 m_schemaResolver->addAllGroupCheck(term);
3909                 particle->setTerm(term);
3910                 particles.append(particle);
3911             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
3912                 const XsdParticle::Ptr particle(new XsdParticle());
3913                 const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
3914                 particle->setTerm(term);
3915                 particles.append(particle);
3916             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
3917                 const XsdParticle::Ptr particle(new XsdParticle());
3918                 const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
3919                 particle->setTerm(term);
3920                 particles.append(particle);
3921             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
3922                 const XsdParticle::Ptr particle(new XsdParticle());
3923                 const XsdTerm::Ptr term = parseAny(particle);
3924                 particle->setTerm(term);
3925                 particles.append(particle);
3926             } else {
3927                 parseUnknown();
3928             }
3929         }
3930     }
3931 
3932     modelGroup->setParticles(particles);
3933 
3934     tagValidator.finalize();
3935 
3936     return modelGroup;
3937 }
3938 
parseLocalSequence(const XsdParticle::Ptr & particle,const NamedSchemaComponent::Ptr & parent)3939 XsdModelGroup::Ptr XsdSchemaParser::parseLocalSequence(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
3940 {
3941     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this);
3942 
3943     validateElement(XsdTagScope::LocalSequence);
3944 
3945     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3946     modelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
3947 
3948     // parse attributes
3949     if (!parseMinMaxConstraint(particle, "sequence")) {
3950         return modelGroup;
3951     }
3952 
3953     validateIdAttribute("sequence");
3954 
3955     XsdParticle::List particles;
3956 
3957     TagValidationHandler tagValidator(XsdTagScope::LocalSequence, this, m_namePool);
3958 
3959     while (!atEnd()) {
3960         readNext();
3961 
3962         if (isEndElement())
3963             break;
3964 
3965         if (isStartElement()) {
3966             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3967             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3968 
3969             tagValidator.validate(token);
3970 
3971             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3972                 const XsdAnnotation::Ptr annotation = parseAnnotation();
3973                 modelGroup->addAnnotation(annotation);
3974             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
3975                 const XsdParticle::Ptr particle(new XsdParticle());
3976                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
3977                 particle->setTerm(term);
3978                 particles.append(particle);
3979             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
3980                 const XsdParticle::Ptr particle(new XsdParticle());
3981                 const XsdTerm::Ptr term = parseReferredGroup(particle);
3982                 m_schemaResolver->addAllGroupCheck(term);
3983                 particle->setTerm(term);
3984                 particles.append(particle);
3985             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
3986                 const XsdParticle::Ptr particle(new XsdParticle());
3987                 const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
3988                 particle->setTerm(term);
3989                 particles.append(particle);
3990             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
3991                 const XsdParticle::Ptr particle(new XsdParticle());
3992                 const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
3993                 particle->setTerm(term);
3994                 particles.append(particle);
3995             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
3996                 const XsdParticle::Ptr particle(new XsdParticle());
3997                 const XsdTerm::Ptr term = parseAny(particle);
3998                 particle->setTerm(term);
3999                 particles.append(particle);
4000             } else {
4001                 parseUnknown();
4002             }
4003         }
4004     }
4005 
4006     modelGroup->setParticles(particles);
4007 
4008     tagValidator.finalize();
4009 
4010     return modelGroup;
4011 }
4012 
parseGlobalAttribute()4013 XsdAttribute::Ptr XsdSchemaParser::parseGlobalAttribute()
4014 {
4015     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this);
4016 
4017     validateElement(XsdTagScope::GlobalAttribute);
4018 
4019     const XsdAttribute::Ptr attribute(new XsdAttribute());
4020     attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
4021     attribute->scope()->setVariety(XsdAttribute::Scope::Global);
4022 
4023     if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
4024         error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4025                                .arg(formatElement("attribute"))
4026                                .arg(formatAttribute("default"))
4027                                .arg(formatAttribute("fixed")));
4028         return attribute;
4029     }
4030 
4031     // parse attributes
4032     if (hasAttribute(QString::fromLatin1("default"))) {
4033         const QString value = readAttribute(QString::fromLatin1("default"));
4034         attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
4035         attribute->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Default);
4036         attribute->valueConstraint()->setValue(value);
4037     } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4038         const QString value = readAttribute(QString::fromLatin1("fixed"));
4039         attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
4040         attribute->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Fixed);
4041         attribute->valueConstraint()->setValue(value);
4042     }
4043 
4044     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("attribute"));
4045     if ((objectName.namespaceURI() == StandardNamespaces::xsi) &&
4046         (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("type")) &&
4047         (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("nil")) &&
4048         (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("schemaLocation")) &&
4049         (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) {
4050 
4051         error(QtXmlPatterns::tr("Content of %1 attribute of %2 element must not be from namespace %3.")
4052                                .arg(formatAttribute("name"))
4053                                .arg(formatElement("attribute"))
4054                                .arg(formatURI(CommonNamespaces::XSI)));
4055         return attribute;
4056     }
4057     if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) {
4058         error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3.")
4059                                .arg(formatAttribute("name"))
4060                                .arg(formatElement("attribute"))
4061                                .arg(formatData("xmlns")));
4062         return attribute;
4063     }
4064     attribute->setName(objectName);
4065 
4066     bool hasTypeAttribute = false;
4067     bool hasTypeSpecified = false;
4068 
4069     if (hasAttribute(QString::fromLatin1("type"))) {
4070         hasTypeAttribute = true;
4071 
4072         const QString type = readQNameAttribute(QString::fromLatin1("type"), "attribute");
4073         QXmlName typeName;
4074         convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
4075         m_schemaResolver->addAttributeType(attribute, typeName, currentSourceLocation()); // add to resolver
4076         hasTypeSpecified = true;
4077     }
4078 
4079     validateIdAttribute("attribute");
4080 
4081     TagValidationHandler tagValidator(XsdTagScope::GlobalAttribute, this, m_namePool);
4082 
4083     while (!atEnd()) {
4084         readNext();
4085 
4086         if (isEndElement())
4087             break;
4088 
4089         if (isStartElement()) {
4090             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4091             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4092 
4093             tagValidator.validate(token);
4094 
4095             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
4096                 const XsdAnnotation::Ptr annotation = parseAnnotation();
4097                 attribute->addAnnotation(annotation);
4098             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
4099                 if (hasTypeAttribute) {
4100                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4101                                            .arg(formatElement("attribute"))
4102                                            .arg(formatElement("simpleType"))
4103                                            .arg(formatAttribute("type")));
4104                     break;
4105                 }
4106 
4107                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
4108                 type->setContext(attribute);
4109                 attribute->setType(type);
4110                 hasTypeSpecified = true;
4111 
4112                 // add it to list of anonymous types as well
4113                 addAnonymousType(type);
4114             } else {
4115                 parseUnknown();
4116             }
4117         }
4118     }
4119 
4120     if (!hasTypeSpecified) {
4121         attribute->setType(BuiltinTypes::xsAnySimpleType); // default value
4122         return attribute;
4123     }
4124 
4125     tagValidator.finalize();
4126 
4127     return attribute;
4128 }
4129 
parseLocalAttribute(const NamedSchemaComponent::Ptr & parent)4130 XsdAttributeUse::Ptr XsdSchemaParser::parseLocalAttribute(const NamedSchemaComponent::Ptr &parent)
4131 {
4132     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this);
4133 
4134     validateElement(XsdTagScope::LocalAttribute);
4135 
4136     bool hasRefAttribute = false;
4137     bool hasTypeAttribute = false;
4138     bool hasTypeSpecified = false;
4139 
4140     XsdAttributeUse::Ptr attributeUse;
4141     if (hasAttribute(QString::fromLatin1("ref"))) {
4142         const XsdAttributeReference::Ptr reference = XsdAttributeReference::Ptr(new XsdAttributeReference());
4143         reference->setType(XsdAttributeReference::AttributeUse);
4144         reference->setSourceLocation(currentSourceLocation());
4145 
4146         attributeUse = reference;
4147         hasRefAttribute = true;
4148     } else {
4149         attributeUse = XsdAttributeUse::Ptr(new XsdAttributeUse());
4150     }
4151 
4152     if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
4153         error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4154                                .arg(formatElement("attribute"))
4155                                .arg(formatAttribute("default"))
4156                                .arg(formatAttribute("fixed")));
4157         return attributeUse;
4158     }
4159 
4160     if (hasRefAttribute) {
4161         if (hasAttribute(QString::fromLatin1("form"))) {
4162             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4163                                    .arg(formatElement("attribute"))
4164                                    .arg(formatAttribute("ref"))
4165                                    .arg(formatAttribute("form")));
4166             return attributeUse;
4167         }
4168         if (hasAttribute(QString::fromLatin1("name"))) {
4169             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4170                                    .arg(formatElement("attribute"))
4171                                    .arg(formatAttribute("ref"))
4172                                    .arg(formatAttribute("name")));
4173             return attributeUse;
4174         }
4175         if (hasAttribute(QString::fromLatin1("type"))) {
4176             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4177                                    .arg(formatElement("attribute"))
4178                                    .arg(formatAttribute("ref"))
4179                                    .arg(formatAttribute("type")));
4180             return attributeUse;
4181         }
4182     }
4183 
4184     // parse attributes
4185 
4186     // default, fixed and use are handled by both, attribute use and attribute reference
4187     if (hasAttribute(QString::fromLatin1("default"))) {
4188         const QString value = readAttribute(QString::fromLatin1("default"));
4189         attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint()));
4190         attributeUse->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Default);
4191         attributeUse->valueConstraint()->setValue(value);
4192     } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4193         const QString value = readAttribute(QString::fromLatin1("fixed"));
4194         attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint()));
4195         attributeUse->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Fixed);
4196         attributeUse->valueConstraint()->setValue(value);
4197     }
4198 
4199     if (hasAttribute(QString::fromLatin1("use"))) {
4200         const QString value = readAttribute(QString::fromLatin1("use"));
4201         if (value != QString::fromLatin1("optional") &&
4202             value != QString::fromLatin1("prohibited") &&
4203             value != QString::fromLatin1("required")) {
4204             attributeContentError("use", "attribute", value);
4205             return attributeUse;
4206         }
4207 
4208         if (value == QString::fromLatin1("optional"))
4209             attributeUse->setUseType(XsdAttributeUse::OptionalUse);
4210         else if (value == QString::fromLatin1("prohibited"))
4211             attributeUse->setUseType(XsdAttributeUse::ProhibitedUse);
4212         else if (value == QString::fromLatin1("required"))
4213             attributeUse->setUseType(XsdAttributeUse::RequiredUse);
4214 
4215         if (attributeUse->valueConstraint() && attributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Default && value != QString::fromLatin1("optional")) {
4216             error(QtXmlPatterns::tr("%1 attribute of %2 element must have the value %3 because the %4 attribute is set.")
4217                                    .arg(formatAttribute("use"))
4218                                    .arg(formatElement("attribute"))
4219                                    .arg(formatData("optional"))
4220                                    .arg(formatElement("default")));
4221             return attributeUse;
4222         }
4223     }
4224 
4225     const XsdAttribute::Ptr attribute(new XsdAttribute());
4226 
4227     attributeUse->setAttribute(attribute);
4228     m_componentLocationHash.insert(attribute, currentSourceLocation());
4229 
4230     attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
4231     attribute->scope()->setVariety(XsdAttribute::Scope::Local);
4232     attribute->scope()->setParent(parent);
4233 
4234     // now make a difference between attribute reference and attribute use
4235     if (hasRefAttribute) {
4236         const QString reference = readQNameAttribute(QString::fromLatin1("ref"), "attribute");
4237         QXmlName referenceName;
4238         convertName(reference, NamespaceSupport::ElementName, referenceName);   // translate qualified name into QXmlName
4239 
4240         const XsdAttributeReference::Ptr attributeReference = attributeUse;
4241         attributeReference->setReferenceName(referenceName);
4242     } else {
4243         if (hasAttribute(QString::fromLatin1("name"))) {
4244             const QString attributeName = readNameAttribute("attribute");
4245 
4246             QXmlName objectName;
4247             if (hasAttribute(QString::fromLatin1("form"))) {
4248                 const QString value = readAttribute(QString::fromLatin1("form"));
4249                 if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
4250                     attributeContentError("form", "attribute", value);
4251                     return attributeUse;
4252                 }
4253 
4254                 if (value == QString::fromLatin1("qualified")) {
4255                     objectName = m_namePool->allocateQName(m_targetNamespace, attributeName);
4256                 } else {
4257                     objectName = m_namePool->allocateQName(QString(), attributeName);
4258                 }
4259             } else {
4260                 if (m_attributeFormDefault == QString::fromLatin1("qualified")) {
4261                     objectName = m_namePool->allocateQName(m_targetNamespace, attributeName);
4262                 } else {
4263                     objectName = m_namePool->allocateQName(QString(), attributeName);
4264                 }
4265             }
4266 
4267             if ((objectName.namespaceURI() == StandardNamespaces::xsi) &&
4268                 (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("type")) &&
4269                 (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("nil")) &&
4270                 (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("schemaLocation")) &&
4271                 (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) {
4272 
4273                 error(QtXmlPatterns::tr("Content of %1 attribute of %2 element must not be from namespace %3.")
4274                                        .arg(formatAttribute("name"))
4275                                        .arg(formatElement("attribute"))
4276                                        .arg(formatURI(CommonNamespaces::XSI)));
4277                 return attributeUse;
4278             }
4279             if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) {
4280                 error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3.")
4281                                        .arg(formatAttribute("name"))
4282                                        .arg(formatElement("attribute"))
4283                                        .arg(formatData("xmlns")));
4284                 return attributeUse;
4285             }
4286 
4287             attribute->setName(objectName);
4288         }
4289 
4290         if (hasAttribute(QString::fromLatin1("type"))) {
4291             hasTypeAttribute = true;
4292 
4293             const QString type = readQNameAttribute(QString::fromLatin1("type"), "attribute");
4294             QXmlName typeName;
4295             convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
4296             m_schemaResolver->addAttributeType(attribute, typeName, currentSourceLocation()); // add to resolver
4297             hasTypeSpecified = true;
4298         }
4299 
4300         if (attributeUse->valueConstraint()) {
4301             //TODO: check whether assigning the value constraint of the attribute use to the attribute is correct
4302             if (!attribute->valueConstraint())
4303                 attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
4304 
4305             attribute->valueConstraint()->setVariety((XsdAttribute::ValueConstraint::Variety)attributeUse->valueConstraint()->variety());
4306             attribute->valueConstraint()->setValue(attributeUse->valueConstraint()->value());
4307             attribute->valueConstraint()->setLexicalForm(attributeUse->valueConstraint()->lexicalForm());
4308         }
4309     }
4310 
4311     validateIdAttribute("attribute");
4312 
4313     TagValidationHandler tagValidator(XsdTagScope::LocalAttribute, this, m_namePool);
4314 
4315     while (!atEnd()) {
4316         readNext();
4317 
4318         if (isEndElement())
4319             break;
4320 
4321         if (isStartElement()) {
4322             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4323             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4324 
4325             tagValidator.validate(token);
4326 
4327             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
4328                 const XsdAnnotation::Ptr annotation = parseAnnotation();
4329                 attribute->addAnnotation(annotation);
4330             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
4331                 if (hasTypeAttribute) {
4332                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4333                                            .arg(formatElement("attribute"))
4334                                            .arg(formatElement("simpleType"))
4335                                            .arg(formatAttribute("type")));
4336                     break;
4337                 }
4338                 if (hasRefAttribute) {
4339                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4340                                            .arg(formatElement("attribute"))
4341                                            .arg(formatElement("simpleType"))
4342                                            .arg(formatAttribute("ref")));
4343                     break;
4344                 }
4345 
4346                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
4347                 type->setContext(attribute);
4348                 attribute->setType(type);
4349                 hasTypeSpecified = true;
4350 
4351                 // add it to list of anonymous types as well
4352                 addAnonymousType(type);
4353             } else {
4354                 parseUnknown();
4355             }
4356         }
4357     }
4358 
4359     if (!hasTypeSpecified) {
4360         attribute->setType(BuiltinTypes::xsAnySimpleType); // default value
4361     }
4362 
4363     tagValidator.finalize();
4364 
4365     return attributeUse;
4366 }
4367 
parseNamedAttributeGroup()4368 XsdAttributeGroup::Ptr XsdSchemaParser::parseNamedAttributeGroup()
4369 {
4370     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this);
4371 
4372     validateElement(XsdTagScope::NamedAttributeGroup);
4373 
4374     const XsdAttributeGroup::Ptr attributeGroup(new XsdAttributeGroup());
4375 
4376     // parse attributes
4377     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("attributeGroup"));
4378     attributeGroup->setName(objectName);
4379 
4380     validateIdAttribute("attributeGroup");
4381 
4382     TagValidationHandler tagValidator(XsdTagScope::NamedAttributeGroup, this, m_namePool);
4383 
4384     while (!atEnd()) {
4385         readNext();
4386 
4387         if (isEndElement())
4388             break;
4389 
4390         if (isStartElement()) {
4391             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4392             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4393 
4394             tagValidator.validate(token);
4395 
4396             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
4397                 const XsdAnnotation::Ptr annotation = parseAnnotation();
4398                 attributeGroup->addAnnotation(annotation);
4399             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
4400                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(attributeGroup);
4401 
4402                 if (attributeUse->useType() == XsdAttributeUse::ProhibitedUse) {
4403                     warning(QtXmlPatterns::tr("Specifying use='prohibited' inside an attribute group has no effect."));
4404                 } else {
4405                     attributeGroup->addAttributeUse(attributeUse);
4406                 }
4407             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
4408                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
4409                 attributeGroup->addAttributeUse(attributeUse);
4410             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
4411                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
4412                 attributeGroup->setWildcard(wildcard);
4413             } else {
4414                 parseUnknown();
4415             }
4416         }
4417     }
4418 
4419     tagValidator.finalize();
4420 
4421     return attributeGroup;
4422 }
4423 
parseReferredAttributeGroup()4424 XsdAttributeUse::Ptr XsdSchemaParser::parseReferredAttributeGroup()
4425 {
4426     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this);
4427 
4428     validateElement(XsdTagScope::ReferredAttributeGroup);
4429 
4430     const XsdAttributeReference::Ptr attributeReference(new XsdAttributeReference());
4431     attributeReference->setType(XsdAttributeReference::AttributeGroup);
4432     attributeReference->setSourceLocation(currentSourceLocation());
4433 
4434     // parse attributes
4435     const QString reference = readQNameAttribute(QString::fromLatin1("ref"), "attributeGroup");
4436     QXmlName referenceName;
4437     convertName(reference, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
4438     attributeReference->setReferenceName(referenceName);
4439 
4440     validateIdAttribute("attributeGroup");
4441 
4442     TagValidationHandler tagValidator(XsdTagScope::ReferredAttributeGroup, this, m_namePool);
4443 
4444     while (!atEnd()) {
4445         readNext();
4446 
4447         if (isEndElement())
4448             break;
4449 
4450         if (isStartElement()) {
4451             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4452             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4453 
4454             tagValidator.validate(token);
4455 
4456             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
4457                 const XsdAnnotation::Ptr annotation = parseAnnotation();
4458                 attributeReference->addAnnotation(annotation);
4459             } else {
4460                 parseUnknown();
4461             }
4462         }
4463     }
4464 
4465     tagValidator.finalize();
4466 
4467     return attributeReference;
4468 }
4469 
parseGlobalElement()4470 XsdElement::Ptr XsdSchemaParser::parseGlobalElement()
4471 {
4472     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this);
4473 
4474     validateElement(XsdTagScope::GlobalElement);
4475 
4476     const XsdElement::Ptr element(new XsdElement());
4477     element->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope()));
4478     element->scope()->setVariety(XsdElement::Scope::Global);
4479 
4480     bool hasTypeAttribute = false;
4481     bool hasTypeSpecified = false;
4482     bool hasSubstitutionGroup = false;
4483 
4484     // parse attributes
4485     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("element"));
4486     element->setName(objectName);
4487 
4488     if (hasAttribute(QString::fromLatin1("abstract"))) {
4489         const QString abstract = readAttribute(QString::fromLatin1("abstract"));
4490 
4491         const Boolean::Ptr value = Boolean::fromLexical(abstract);
4492         if (value->hasError()) {
4493             attributeContentError("abstract", "element", abstract, BuiltinTypes::xsBoolean);
4494             return element;
4495         }
4496 
4497         element->setIsAbstract(value->as<Boolean>()->value());
4498     } else {
4499         element->setIsAbstract(false); // the default value
4500     }
4501 
4502     if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
4503         error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4504                                .arg(formatElement("element"))
4505                                .arg(formatAttribute("default"))
4506                                .arg(formatAttribute("fixed")));
4507         return element;
4508     }
4509 
4510     if (hasAttribute(QString::fromLatin1("default"))) {
4511         const QString value = readAttribute(QString::fromLatin1("default"));
4512         element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
4513         element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default);
4514         element->valueConstraint()->setValue(value);
4515     } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4516         const QString value = readAttribute(QString::fromLatin1("fixed"));
4517         element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
4518         element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed);
4519         element->valueConstraint()->setValue(value);
4520     }
4521 
4522     element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element"));
4523     element->setSubstitutionGroupExclusions(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "element"));
4524 
4525     if (hasAttribute(QString::fromLatin1("nillable"))) {
4526         const QString nillable = readAttribute(QString::fromLatin1("nillable"));
4527 
4528         const Boolean::Ptr value = Boolean::fromLexical(nillable);
4529         if (value->hasError()) {
4530             attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean);
4531             return element;
4532         }
4533 
4534         element->setIsNillable(value->as<Boolean>()->value());
4535     } else {
4536         element->setIsNillable(false); // the default value
4537     }
4538 
4539     if (hasAttribute(QString::fromLatin1("type"))) {
4540         const QString type = readQNameAttribute(QString::fromLatin1("type"), "element");
4541         QXmlName typeName;
4542         convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
4543         m_schemaResolver->addElementType(element, typeName, currentSourceLocation()); // add to resolver
4544 
4545         hasTypeAttribute = true;
4546         hasTypeSpecified = true;
4547     }
4548 
4549     if (hasAttribute(QString::fromLatin1("substitutionGroup"))) {
4550         QList<QXmlName> elementNames;
4551 
4552         const QString value = readAttribute(QString::fromLatin1("substitutionGroup"));
4553         const QStringList substitutionGroups = value.split(QLatin1Char(' '), Qt::SkipEmptyParts);
4554         if (substitutionGroups.isEmpty()) {
4555             attributeContentError("substitutionGroup", "element", value, BuiltinTypes::xsQName);
4556             return element;
4557         }
4558 
4559         for (int i = 0; i < substitutionGroups.count(); ++i) {
4560             const QString value = substitutionGroups.at(i).simplified();
4561             if (!XPathHelper::isQName(value)) {
4562                 attributeContentError("substitutionGroup", "element", value, BuiltinTypes::xsQName);
4563                 return element;
4564             }
4565 
4566             QXmlName elementName;
4567             convertName(value, NamespaceSupport::ElementName, elementName); // translate qualified name into QXmlName
4568             elementNames.append(elementName);
4569         }
4570 
4571         m_schemaResolver->addSubstitutionGroupAffiliation(element, elementNames, currentSourceLocation()); // add to resolver
4572 
4573         hasSubstitutionGroup = true;
4574     }
4575 
4576     validateIdAttribute("element");
4577 
4578     XsdAlternative::List alternatives;
4579 
4580     TagValidationHandler tagValidator(XsdTagScope::GlobalElement, this, m_namePool);
4581 
4582     while (!atEnd()) {
4583         readNext();
4584 
4585         if (isEndElement())
4586             break;
4587 
4588         if (isStartElement()) {
4589             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4590             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4591 
4592             tagValidator.validate(token);
4593 
4594             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
4595                 const XsdAnnotation::Ptr annotation = parseAnnotation();
4596                 element->addAnnotation(annotation);
4597             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
4598                 if (hasTypeAttribute) {
4599                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4600                                            .arg(formatElement("element"))
4601                                            .arg(formatElement("simpleType"))
4602                                            .arg(formatAttribute("type")));
4603                     return element;
4604                 }
4605 
4606                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
4607                 type->setContext(element);
4608                 element->setType(type);
4609 
4610                 // add it to list of anonymous types as well
4611                 addAnonymousType(type);
4612 
4613                 hasTypeSpecified = true;
4614             } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
4615                 if (hasTypeAttribute) {
4616                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4617                                            .arg(formatElement("element"))
4618                                            .arg(formatElement("complexType"))
4619                                            .arg(formatAttribute("type")));
4620                     return element;
4621                 }
4622 
4623                 const XsdComplexType::Ptr type = parseLocalComplexType();
4624                 type->setContext(element);
4625                 element->setType(type);
4626 
4627                 // add it to list of anonymous types as well
4628                 addAnonymousType(type);
4629 
4630                 hasTypeSpecified = true;
4631             } else if (isSchemaTag(XsdSchemaToken::Alternative, token, namespaceToken)) {
4632                 const XsdAlternative::Ptr alternative = parseAlternative();
4633                 alternatives.append(alternative);
4634             } else if (isSchemaTag(XsdSchemaToken::Unique, token, namespaceToken)) {
4635                 const XsdIdentityConstraint::Ptr constraint = parseUnique();
4636                 element->addIdentityConstraint(constraint);
4637             } else if (isSchemaTag(XsdSchemaToken::Key, token, namespaceToken)) {
4638                 const XsdIdentityConstraint::Ptr constraint = parseKey();
4639                 element->addIdentityConstraint(constraint);
4640             } else if (isSchemaTag(XsdSchemaToken::Keyref, token, namespaceToken)) {
4641                 const XsdIdentityConstraint::Ptr constraint = parseKeyRef(element);
4642                 element->addIdentityConstraint(constraint);
4643             } else {
4644                 parseUnknown();
4645             }
4646         }
4647     }
4648 
4649     tagValidator.finalize();
4650 
4651     if (!hasTypeSpecified) {
4652         if (hasSubstitutionGroup)
4653             m_schemaResolver->addSubstitutionGroupType(element);
4654         else
4655             element->setType(BuiltinTypes::xsAnyType);
4656     }
4657 
4658     if (!alternatives.isEmpty()) {
4659         element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
4660 
4661         for (int i = 0; i < alternatives.count(); ++i) {
4662             if (alternatives.at(i)->test())
4663                 element->typeTable()->addAlternative(alternatives.at(i));
4664 
4665             if (i == (alternatives.count() - 1)) { // the final one
4666                 if (!alternatives.at(i)->test()) {
4667                     element->typeTable()->setDefaultTypeDefinition(alternatives.at(i));
4668                 } else {
4669                     const XsdAlternative::Ptr alternative(new XsdAlternative());
4670                     if (element->type())
4671                         alternative->setType(element->type());
4672                     else
4673                         m_schemaResolver->addAlternativeType(alternative, element); // add to resolver
4674 
4675                     element->typeTable()->setDefaultTypeDefinition(alternative);
4676                 }
4677             }
4678         }
4679     }
4680 
4681     return element;
4682 }
4683 
parseLocalElement(const XsdParticle::Ptr & particle,const NamedSchemaComponent::Ptr & parent)4684 XsdTerm::Ptr XsdSchemaParser::parseLocalElement(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
4685 {
4686     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this);
4687 
4688     validateElement(XsdTagScope::LocalElement);
4689 
4690     bool hasRefAttribute = false;
4691     bool hasTypeAttribute = false;
4692     bool hasTypeSpecified = false;
4693 
4694     XsdTerm::Ptr term;
4695     XsdElement::Ptr element;
4696     if (hasAttribute(QString::fromLatin1("ref"))) {
4697         term = XsdReference::Ptr(new XsdReference());
4698         hasRefAttribute = true;
4699     } else {
4700         term = XsdElement::Ptr(new XsdElement());
4701         element = term;
4702     }
4703 
4704     if (hasRefAttribute) {
4705         if (hasAttribute(QString::fromLatin1("name"))) {
4706             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4707                                    .arg(formatElement("element"))
4708                                    .arg(formatAttribute("ref"))
4709                                    .arg(formatAttribute("name")));
4710             return term;
4711         } else if (hasAttribute(QString::fromLatin1("block"))) {
4712             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4713                                    .arg(formatElement("element"))
4714                                    .arg(formatAttribute("ref"))
4715                                    .arg(formatAttribute("block")));
4716             return term;
4717         } else if (hasAttribute(QString::fromLatin1("nillable"))) {
4718             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4719                                    .arg(formatElement("element"))
4720                                    .arg(formatAttribute("ref"))
4721                                    .arg(formatAttribute("nillable")));
4722             return term;
4723         } else if (hasAttribute(QString::fromLatin1("default"))) {
4724             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4725                                    .arg(formatElement("element"))
4726                                    .arg(formatAttribute("ref"))
4727                                    .arg(formatAttribute("default")));
4728             return term;
4729         } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4730             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4731                                    .arg(formatElement("element"))
4732                                    .arg(formatAttribute("ref"))
4733                                    .arg(formatAttribute("fixed")));
4734             return term;
4735         } else if (hasAttribute(QString::fromLatin1("form"))) {
4736             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4737                                    .arg(formatElement("element"))
4738                                    .arg(formatAttribute("ref"))
4739                                    .arg(formatAttribute("form")));
4740             return term;
4741         } else if (hasAttribute(QString::fromLatin1("type"))) {
4742             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4743                                    .arg(formatElement("element"))
4744                                    .arg(formatAttribute("ref"))
4745                                    .arg(formatAttribute("type")));
4746             return term;
4747         }
4748     }
4749 
4750     // parse attributes
4751     if (!parseMinMaxConstraint(particle, "element")) {
4752         return element;
4753     }
4754 
4755     if (!hasAttribute(QString::fromLatin1("name")) && !hasAttribute(QString::fromLatin1("ref"))) {
4756         error(QtXmlPatterns::tr("%1 element must have either %2 or %3 attribute.")
4757                                .arg(formatElement("element"))
4758                                .arg(formatAttribute("name"))
4759                                .arg(formatAttribute("ref")));
4760         return element;
4761     }
4762 
4763     if (hasRefAttribute) {
4764         const QString ref = readQNameAttribute(QString::fromLatin1("ref"), "element");
4765         QXmlName referenceName;
4766         convertName(ref, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
4767 
4768         const XsdReference::Ptr reference = term;
4769         reference->setReferenceName(referenceName);
4770         reference->setType(XsdReference::Element);
4771         reference->setSourceLocation(currentSourceLocation());
4772     } else {
4773         element->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope()));
4774         element->scope()->setVariety(XsdElement::Scope::Local);
4775         element->scope()->setParent(parent.data());
4776 
4777         if (hasAttribute(QString::fromLatin1("name"))) {
4778             const QString elementName = readNameAttribute("element");
4779 
4780             QXmlName objectName;
4781             if (hasAttribute(QString::fromLatin1("form"))) {
4782                 const QString value = readAttribute(QString::fromLatin1("form"));
4783                 if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
4784                     attributeContentError("form", "element", value);
4785                     return element;
4786                 }
4787 
4788                 if (value == QString::fromLatin1("qualified")) {
4789                     objectName = m_namePool->allocateQName(m_targetNamespace, elementName);
4790                 } else {
4791                     objectName = m_namePool->allocateQName(QString(), elementName);
4792                 }
4793             } else {
4794                 if (m_elementFormDefault == QString::fromLatin1("qualified")) {
4795                     objectName = m_namePool->allocateQName(m_targetNamespace, elementName);
4796                 } else {
4797                     objectName = m_namePool->allocateQName(QString(), elementName);
4798                 }
4799             }
4800 
4801             element->setName(objectName);
4802         }
4803 
4804         if (hasAttribute(QString::fromLatin1("nillable"))) {
4805             const QString nillable = readAttribute(QString::fromLatin1("nillable"));
4806 
4807             const Boolean::Ptr value = Boolean::fromLexical(nillable);
4808             if (value->hasError()) {
4809                 attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean);
4810                 return term;
4811             }
4812 
4813             element->setIsNillable(value->as<Boolean>()->value());
4814         } else {
4815             element->setIsNillable(false); // the default value
4816         }
4817 
4818         if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
4819             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4820                                    .arg(formatElement("element"))
4821                                    .arg(formatAttribute("default"))
4822                                    .arg(formatAttribute("fixed")));
4823             return element;
4824         }
4825 
4826         if (hasAttribute(QString::fromLatin1("default"))) {
4827             const QString value = readAttribute(QString::fromLatin1("default"));
4828             element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
4829             element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default);
4830             element->valueConstraint()->setValue(value);
4831         } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4832             const QString value = readAttribute(QString::fromLatin1("fixed"));
4833             element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
4834             element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed);
4835             element->valueConstraint()->setValue(value);
4836         }
4837 
4838         if (hasAttribute(QString::fromLatin1("type"))) {
4839             const QString type = readQNameAttribute(QString::fromLatin1("type"), "element");
4840             QXmlName typeName;
4841             convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
4842             m_schemaResolver->addElementType(element, typeName, currentSourceLocation()); // add to resolver
4843 
4844             hasTypeAttribute = true;
4845             hasTypeSpecified = true;
4846         }
4847 
4848         element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element"));
4849     }
4850 
4851     validateIdAttribute("element");
4852 
4853     XsdAlternative::List alternatives;
4854 
4855     TagValidationHandler tagValidator(XsdTagScope::LocalElement, this, m_namePool);
4856 
4857     while (!atEnd()) {
4858         readNext();
4859 
4860         if (isEndElement())
4861             break;
4862 
4863         if (isStartElement()) {
4864             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4865             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4866 
4867             tagValidator.validate(token);
4868 
4869             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
4870                 const XsdAnnotation::Ptr annotation = parseAnnotation();
4871                 term->addAnnotation(annotation);
4872             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
4873                 if (hasRefAttribute) {
4874                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4875                                            .arg(formatElement("element"))
4876                                            .arg(formatElement("simpleType"))
4877                                            .arg(formatAttribute("ref")));
4878                     return term;
4879                 } else if (hasTypeAttribute) {
4880                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4881                                            .arg(formatElement("element"))
4882                                            .arg(formatElement("simpleType"))
4883                                            .arg(formatAttribute("type")));
4884                     return term;
4885                 }
4886 
4887                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
4888                 type->setContext(element);
4889                 element->setType(type);
4890 
4891                 // add it to list of anonymous types as well
4892                 addAnonymousType(type);
4893 
4894                 hasTypeSpecified = true;
4895             } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
4896                 if (hasRefAttribute) {
4897                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4898                                            .arg(formatElement("element"))
4899                                            .arg(formatElement("complexType"))
4900                                            .arg(formatAttribute("ref")));
4901                     return term;
4902                 } else if (hasTypeAttribute) {
4903                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4904                                            .arg(formatElement("element"))
4905                                            .arg(formatElement("complexType"))
4906                                            .arg(formatAttribute("type")));
4907                     return term;
4908                 }
4909 
4910                 const XsdComplexType::Ptr type = parseLocalComplexType();
4911                 type->setContext(element);
4912                 element->setType(type);
4913 
4914                 // add it to list of anonymous types as well
4915                 addAnonymousType(type);
4916 
4917                 hasTypeSpecified = true;
4918             } else if (isSchemaTag(XsdSchemaToken::Alternative, token, namespaceToken)) {
4919                 if (hasRefAttribute) {
4920                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4921                                            .arg(formatElement("element"))
4922                                            .arg(formatElement("alternative"))
4923                                            .arg(formatAttribute("ref")));
4924                     return term;
4925                 }
4926 
4927                 const XsdAlternative::Ptr alternative = parseAlternative();
4928                 alternatives.append(alternative);
4929             } else if (isSchemaTag(XsdSchemaToken::Unique, token, namespaceToken)) {
4930                 if (hasRefAttribute) {
4931                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4932                                            .arg(formatElement("element"))
4933                                            .arg(formatElement("unique"))
4934                                            .arg(formatAttribute("ref")));
4935                     return term;
4936                 }
4937 
4938                 const XsdIdentityConstraint::Ptr constraint = parseUnique();
4939                 element->addIdentityConstraint(constraint);
4940             } else if (isSchemaTag(XsdSchemaToken::Key, token, namespaceToken)) {
4941                 if (hasRefAttribute) {
4942                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4943                                            .arg(formatElement("element"))
4944                                            .arg(formatElement("key"))
4945                                            .arg(formatAttribute("ref")));
4946                     return term;
4947                 }
4948 
4949                 const XsdIdentityConstraint::Ptr constraint = parseKey();
4950                 element->addIdentityConstraint(constraint);
4951             } else if (isSchemaTag(XsdSchemaToken::Keyref, token, namespaceToken)) {
4952                 if (hasRefAttribute) {
4953                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4954                                            .arg(formatElement("element"))
4955                                            .arg(formatElement("keyref"))
4956                                            .arg(formatAttribute("ref")));
4957                     return term;
4958                 }
4959 
4960                 const XsdIdentityConstraint::Ptr constraint = parseKeyRef(element);
4961                 element->addIdentityConstraint(constraint);
4962             } else {
4963                 parseUnknown();
4964             }
4965         }
4966     }
4967 
4968     tagValidator.finalize();
4969 
4970     if (!hasTypeSpecified && !hasRefAttribute)
4971         element->setType(BuiltinTypes::xsAnyType);
4972 
4973     if (!hasRefAttribute && !alternatives.isEmpty()) {
4974         element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
4975 
4976         for (int i = 0; i < alternatives.count(); ++i) {
4977             if (alternatives.at(i)->test())
4978                 element->typeTable()->addAlternative(alternatives.at(i));
4979 
4980             if (i == (alternatives.count() - 1)) { // the final one
4981                 if (!alternatives.at(i)->test()) {
4982                     element->typeTable()->setDefaultTypeDefinition(alternatives.at(i));
4983                 } else {
4984                     const XsdAlternative::Ptr alternative(new XsdAlternative());
4985                     if (element->type())
4986                         alternative->setType(element->type());
4987                     else
4988                         m_schemaResolver->addAlternativeType(alternative, element); // add to resolver
4989 
4990                     element->typeTable()->setDefaultTypeDefinition(alternative);
4991                 }
4992             }
4993         }
4994     }
4995 
4996     return term;
4997 }
4998 
parseUnique()4999 XsdIdentityConstraint::Ptr XsdSchemaParser::parseUnique()
5000 {
5001     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Unique, this);
5002 
5003     validateElement(XsdTagScope::Unique);
5004 
5005     const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
5006     constraint->setCategory(XsdIdentityConstraint::Unique);
5007 
5008     // parse attributes
5009     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("unique"));
5010     constraint->setName(objectName);
5011 
5012     validateIdAttribute("unique");
5013 
5014     TagValidationHandler tagValidator(XsdTagScope::Unique, this, m_namePool);
5015 
5016     while (!atEnd()) {
5017         readNext();
5018 
5019         if (isEndElement())
5020             break;
5021 
5022         if (isStartElement()) {
5023             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5024             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5025 
5026             tagValidator.validate(token);
5027 
5028             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5029                 const XsdAnnotation::Ptr annotation = parseAnnotation();
5030                 constraint->addAnnotation(annotation);
5031             } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) {
5032                 parseSelector(constraint);
5033             } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) {
5034                 parseField(constraint);
5035             } else {
5036                 parseUnknown();
5037             }
5038         }
5039     }
5040 
5041     // add constraint to schema for further checking
5042     addIdentityConstraint(constraint);
5043 
5044     tagValidator.finalize();
5045 
5046     return constraint;
5047 }
5048 
parseKey()5049 XsdIdentityConstraint::Ptr XsdSchemaParser::parseKey()
5050 {
5051     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Key, this);
5052 
5053     validateElement(XsdTagScope::Key);
5054 
5055     const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
5056     constraint->setCategory(XsdIdentityConstraint::Key);
5057 
5058     // parse attributes
5059     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("key"));
5060     constraint->setName(objectName);
5061 
5062     validateIdAttribute("key");
5063 
5064     TagValidationHandler tagValidator(XsdTagScope::Key, this, m_namePool);
5065 
5066     while (!atEnd()) {
5067         readNext();
5068 
5069         if (isEndElement())
5070             break;
5071 
5072         if (isStartElement()) {
5073             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5074             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5075 
5076             tagValidator.validate(token);
5077 
5078             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5079                 const XsdAnnotation::Ptr annotation = parseAnnotation();
5080                 constraint->addAnnotation(annotation);
5081             } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) {
5082                 parseSelector(constraint);
5083             } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) {
5084                 parseField(constraint);
5085             } else {
5086                 parseUnknown();
5087             }
5088         }
5089     }
5090 
5091     // add constraint to schema for further checking
5092     addIdentityConstraint(constraint);
5093 
5094     tagValidator.finalize();
5095 
5096     return constraint;
5097 }
5098 
parseKeyRef(const XsdElement::Ptr & element)5099 XsdIdentityConstraint::Ptr XsdSchemaParser::parseKeyRef(const XsdElement::Ptr &element)
5100 {
5101     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Keyref, this);
5102 
5103     validateElement(XsdTagScope::KeyRef);
5104 
5105     const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
5106     constraint->setCategory(XsdIdentityConstraint::KeyReference);
5107 
5108     // parse attributes
5109     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("keyref"));
5110     constraint->setName(objectName);
5111 
5112     const QString refer = readQNameAttribute(QString::fromLatin1("refer"), "keyref");
5113     QXmlName referenceName;
5114     convertName(refer, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
5115     m_schemaResolver->addKeyReference(element, constraint, referenceName, currentSourceLocation()); // add to resolver
5116 
5117     validateIdAttribute("keyref");
5118 
5119     TagValidationHandler tagValidator(XsdTagScope::KeyRef, this, m_namePool);
5120 
5121     while (!atEnd()) {
5122         readNext();
5123 
5124         if (isEndElement())
5125             break;
5126 
5127         if (isStartElement()) {
5128             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5129             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5130 
5131             tagValidator.validate(token);
5132 
5133             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5134                 const XsdAnnotation::Ptr annotation = parseAnnotation();
5135                 constraint->addAnnotation(annotation);
5136             } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) {
5137                 parseSelector(constraint);
5138             } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) {
5139                 parseField(constraint);
5140             } else {
5141                 parseUnknown();
5142             }
5143         }
5144     }
5145 
5146     // add constraint to schema for further checking
5147     addIdentityConstraint(constraint);
5148 
5149     tagValidator.finalize();
5150 
5151     return constraint;
5152 }
5153 
parseSelector(const XsdIdentityConstraint::Ptr & ptr)5154 void XsdSchemaParser::parseSelector(const XsdIdentityConstraint::Ptr &ptr)
5155 {
5156     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Selector, this);
5157 
5158     validateElement(XsdTagScope::Selector);
5159 
5160     // parse attributes
5161     const XsdXPathExpression::Ptr expression = readXPathExpression("selector");
5162 
5163     const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathSelector, "selector");
5164     expression->setExpression(xpath);
5165 
5166     ptr->setSelector(expression);
5167 
5168     validateIdAttribute("selector");
5169 
5170     TagValidationHandler tagValidator(XsdTagScope::Selector, this, m_namePool);
5171 
5172     while (!atEnd()) {
5173         readNext();
5174 
5175         if (isEndElement())
5176             break;
5177 
5178         if (isStartElement()) {
5179             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5180             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5181 
5182             tagValidator.validate(token);
5183 
5184             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5185                 const XsdAnnotation::Ptr annotation = parseAnnotation();
5186                 expression->addAnnotation(annotation);
5187             } else {
5188                 parseUnknown();
5189             }
5190         }
5191     }
5192 
5193     tagValidator.finalize();
5194 }
5195 
parseField(const XsdIdentityConstraint::Ptr & ptr)5196 void XsdSchemaParser::parseField(const XsdIdentityConstraint::Ptr &ptr)
5197 {
5198     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Field, this);
5199 
5200     validateElement(XsdTagScope::Field);
5201 
5202     // parse attributes
5203     const XsdXPathExpression::Ptr expression = readXPathExpression("field");
5204 
5205     const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathField, "field");
5206     expression->setExpression(xpath);
5207 
5208     ptr->addField(expression);
5209 
5210     validateIdAttribute("field");
5211 
5212     TagValidationHandler tagValidator(XsdTagScope::Field, this, m_namePool);
5213 
5214     while (!atEnd()) {
5215         readNext();
5216 
5217         if (isEndElement())
5218             break;
5219 
5220         if (isStartElement()) {
5221             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5222             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5223 
5224             tagValidator.validate(token);
5225 
5226             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5227                 const XsdAnnotation::Ptr annotation = parseAnnotation();
5228                 expression->addAnnotation(annotation);
5229             } else {
5230                 parseUnknown();
5231             }
5232         }
5233     }
5234 
5235     tagValidator.finalize();
5236 }
5237 
parseAlternative()5238 XsdAlternative::Ptr XsdSchemaParser::parseAlternative()
5239 {
5240     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Alternative, this);
5241 
5242     validateElement(XsdTagScope::Alternative);
5243 
5244     const XsdAlternative::Ptr alternative(new XsdAlternative());
5245 
5246     bool hasTypeSpecified = false;
5247 
5248     if (hasAttribute(QString::fromLatin1("test"))) {
5249         const XsdXPathExpression::Ptr expression = readXPathExpression("alternative");
5250 
5251         const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "alternative");
5252         expression->setExpression(test);
5253 
5254         alternative->setTest(expression);
5255     }
5256 
5257     if (hasAttribute(QString::fromLatin1("type"))) {
5258         const QString type = readQNameAttribute(QString::fromLatin1("type"), "alternative");
5259         QXmlName typeName;
5260         convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
5261         m_schemaResolver->addAlternativeType(alternative, typeName, currentSourceLocation()); // add to resolver
5262 
5263         hasTypeSpecified = true;
5264     }
5265 
5266     validateIdAttribute("alternative");
5267 
5268     TagValidationHandler tagValidator(XsdTagScope::Alternative, this, m_namePool);
5269 
5270     while (!atEnd()) {
5271         readNext();
5272 
5273         if (isEndElement())
5274             break;
5275 
5276         if (isStartElement()) {
5277             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5278             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5279 
5280             tagValidator.validate(token);
5281 
5282             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5283                 const XsdAnnotation::Ptr annotation = parseAnnotation();
5284                 alternative->addAnnotation(annotation);
5285             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
5286                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
5287                 alternative->setType(type);
5288 
5289                 // add it to list of anonymous types as well
5290                 addAnonymousType(type);
5291 
5292                 hasTypeSpecified = true;
5293             } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
5294                 const XsdComplexType::Ptr type = parseLocalComplexType();
5295                 alternative->setType(type);
5296 
5297                 // add it to list of anonymous types as well
5298                 addAnonymousType(type);
5299 
5300                 hasTypeSpecified = true;
5301             } else {
5302                 parseUnknown();
5303             }
5304         }
5305     }
5306 
5307     tagValidator.finalize();
5308 
5309     if (!hasTypeSpecified) {
5310         error(QtXmlPatterns::tr("%1 element must have either %2 attribute or %3 or %4 as child element.")
5311                                .arg(formatElement("alternative"))
5312                                .arg(formatAttribute("type"))
5313                                .arg(formatElement("simpleType"))
5314                                .arg(formatElement("complexType")));
5315         return alternative;
5316     }
5317 
5318     return alternative;
5319 }
5320 
parseNotation()5321 XsdNotation::Ptr XsdSchemaParser::parseNotation()
5322 {
5323     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Notation, this);
5324 
5325     validateElement(XsdTagScope::Notation);
5326 
5327     const XsdNotation::Ptr notation(new XsdNotation());
5328 
5329     // parse attributes
5330     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("notation"));
5331     notation->setName(objectName);
5332 
5333     bool hasOptionalAttribute = false;
5334 
5335     if (hasAttribute(QString::fromLatin1("public"))) {
5336         const QString value = readAttribute(QString::fromLatin1("public"));
5337         if (!value.isEmpty()) {
5338             const DerivedString<TypeToken>::Ptr publicId = DerivedString<TypeToken>::fromLexical(m_namePool, value);
5339             if (publicId->hasError()) {
5340                 attributeContentError("public", "notation", value, BuiltinTypes::xsToken);
5341                 return notation;
5342             }
5343             notation->setPublicId(publicId);
5344         }
5345 
5346         hasOptionalAttribute = true;
5347     }
5348 
5349     if (hasAttribute(QString::fromLatin1("system"))) {
5350         const QString value = readAttribute(QString::fromLatin1("system"));
5351         if (!isValidUri(value)) {
5352             attributeContentError("system", "notation", value, BuiltinTypes::xsAnyURI);
5353             return notation;
5354         }
5355 
5356         if (!value.isEmpty()) {
5357             const AnyURI::Ptr systemId = AnyURI::fromLexical(value);
5358             notation->setSystemId(systemId);
5359         }
5360 
5361         hasOptionalAttribute = true;
5362     }
5363 
5364     if (!hasOptionalAttribute) {
5365         error(QtXmlPatterns::tr("%1 element requires either %2 or %3 attribute.")
5366                                .arg(formatElement("notation"))
5367                                .arg(formatAttribute("public"))
5368                                .arg(formatAttribute("system")));
5369         return notation;
5370     }
5371 
5372     validateIdAttribute("notation");
5373 
5374     TagValidationHandler tagValidator(XsdTagScope::Notation, this, m_namePool);
5375 
5376     while (!atEnd()) {
5377         readNext();
5378 
5379         if (isEndElement())
5380             break;
5381 
5382         if (isCharacters() || isEntityReference()) {
5383             if (!text().toString().trimmed().isEmpty()) {
5384                 error(QtXmlPatterns::tr("Text or entity references not allowed inside %1 element").arg(formatElement("notation.")));
5385                 return notation;
5386             }
5387         }
5388 
5389         if (isStartElement()) {
5390             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5391             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5392 
5393             tagValidator.validate(token);
5394 
5395             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5396                 const XsdAnnotation::Ptr annotation = parseAnnotation();
5397                 notation->addAnnotation(annotation);
5398             } else {
5399                 parseUnknown();
5400             }
5401         }
5402     }
5403 
5404     tagValidator.finalize();
5405 
5406     return notation;
5407 }
5408 
parseAny(const XsdParticle::Ptr & particle)5409 XsdWildcard::Ptr XsdSchemaParser::parseAny(const XsdParticle::Ptr &particle)
5410 {
5411     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Any, this);
5412 
5413     validateElement(XsdTagScope::Any);
5414 
5415     const XsdWildcard::Ptr wildcard(new XsdWildcard());
5416 
5417     // parse attributes
5418     if (!parseMinMaxConstraint(particle, "any")) {
5419         return wildcard;
5420     }
5421 
5422     if (hasAttribute(QString::fromLatin1("namespace"))) {
5423         const auto valueList = readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), Qt::SkipEmptyParts);
5424         const QSet<QString> values(valueList.cbegin(), valueList.cend());
5425         if ((values.contains(QString::fromLatin1("##any")) || values.contains(QString::fromLatin1("##other"))) && values.count() != 1) {
5426             error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs.")
5427                                    .arg(formatAttribute("namespace"))
5428                                    .arg(formatElement("any"))
5429                                    .arg(formatData("##any"))
5430                                    .arg(formatData("##other")));
5431             return wildcard;
5432         }
5433 
5434         if (values.contains(QString::fromLatin1("##any"))) {
5435             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
5436         } else if (values.contains(QString::fromLatin1("##other"))) {
5437             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
5438             if (!m_targetNamespace.isEmpty())
5439                 wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << m_targetNamespace);
5440             else
5441                 wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
5442         } else {
5443             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
5444             QStringList newValues = values.values();
5445 
5446             // replace the ##targetNamespace entry
5447             for (int i = 0; i < newValues.count(); ++i) {
5448                 if (newValues.at(i) == QString::fromLatin1("##targetNamespace")) {
5449                     if (!m_targetNamespace.isEmpty())
5450                         newValues[i] = m_targetNamespace;
5451                     else
5452                         newValues[i] = XsdWildcard::absentNamespace();
5453                 } else if (newValues.at(i) == QString::fromLatin1("##local")) {
5454                     newValues[i] = XsdWildcard::absentNamespace();
5455                 }
5456             }
5457 
5458             // check for invalid URIs
5459             for (int i = 0; i < newValues.count(); ++i) {
5460                 const QString stringValue = newValues.at(i);
5461                 if (stringValue == XsdWildcard::absentNamespace())
5462                     continue;
5463 
5464                 if (!isValidUri(stringValue)) {
5465                     attributeContentError("namespace", "any", stringValue, BuiltinTypes::xsAnyURI);
5466                     return wildcard;
5467                 }
5468             }
5469 
5470             wildcard->namespaceConstraint()->setNamespaces(QSet<QString>(newValues.cbegin(), newValues.cend()));
5471         }
5472     } else {
5473         wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
5474     }
5475 
5476     if (hasAttribute(QString::fromLatin1("processContents"))) {
5477         const QString value = readAttribute(QString::fromLatin1("processContents"));
5478         if (value != QString::fromLatin1("lax") &&
5479             value != QString::fromLatin1("skip") &&
5480             value != QString::fromLatin1("strict")) {
5481             attributeContentError("processContents", "any", value);
5482             return wildcard;
5483         }
5484 
5485         if (value == QString::fromLatin1("lax")) {
5486             wildcard->setProcessContents(XsdWildcard::Lax);
5487         } else if (value == QString::fromLatin1("skip")) {
5488             wildcard->setProcessContents(XsdWildcard::Skip);
5489         } else if (value == QString::fromLatin1("strict")) {
5490             wildcard->setProcessContents(XsdWildcard::Strict);
5491         }
5492     } else {
5493         wildcard->setProcessContents(XsdWildcard::Strict);
5494     }
5495 
5496     validateIdAttribute("any");
5497 
5498     TagValidationHandler tagValidator(XsdTagScope::Any, this, m_namePool);
5499 
5500     while (!atEnd()) {
5501         readNext();
5502 
5503         if (isEndElement())
5504             break;
5505 
5506         if (isStartElement()) {
5507             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5508             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5509 
5510             tagValidator.validate(token);
5511 
5512             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5513                 const XsdAnnotation::Ptr annotation = parseAnnotation();
5514                 wildcard->addAnnotation(annotation);
5515             } else {
5516                 parseUnknown();
5517             }
5518         }
5519     }
5520 
5521     tagValidator.finalize();
5522 
5523     return wildcard;
5524 }
5525 
parseAnyAttribute()5526 XsdWildcard::Ptr XsdSchemaParser::parseAnyAttribute()
5527 {
5528     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AnyAttribute, this);
5529 
5530     validateElement(XsdTagScope::AnyAttribute);
5531 
5532     const XsdWildcard::Ptr wildcard(new XsdWildcard());
5533 
5534     // parse attributes
5535     if (hasAttribute(QString::fromLatin1("namespace"))) {
5536         const auto valueList = readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), Qt::SkipEmptyParts);
5537         const QSet<QString> values(valueList.cbegin(), valueList.cend());
5538         if ((values.contains(QString::fromLatin1("##any")) || values.contains(QString::fromLatin1("##other"))) && values.count() != 1) {
5539             error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs.")
5540                                    .arg(formatAttribute("namespace"))
5541                                    .arg(formatElement("anyAttribute"))
5542                                    .arg(formatData("##any"))
5543                                    .arg(formatData("##other")));
5544             return wildcard;
5545         }
5546 
5547         if (values.contains(QString::fromLatin1("##any"))) {
5548             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
5549         } else if (values.contains(QString::fromLatin1("##other"))) {
5550             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
5551             if (!m_targetNamespace.isEmpty())
5552                 wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << m_targetNamespace);
5553             else
5554                 wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
5555         } else {
5556             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
5557             QStringList newValues = values.values();
5558 
5559             // replace the ##targetNamespace entry
5560             for (int i = 0; i < newValues.count(); ++i) {
5561                 if (newValues.at(i) == QString::fromLatin1("##targetNamespace")) {
5562                     if (!m_targetNamespace.isEmpty())
5563                         newValues[i] = m_targetNamespace;
5564                     else
5565                         newValues[i] = XsdWildcard::absentNamespace();
5566                 } else if (newValues.at(i) == QString::fromLatin1("##local")) {
5567                     newValues[i] = XsdWildcard::absentNamespace();
5568                 }
5569             }
5570 
5571             // check for invalid URIs
5572             for (int i = 0; i < newValues.count(); ++i) {
5573                 const QString stringValue = newValues.at(i);
5574                 if (stringValue == XsdWildcard::absentNamespace())
5575                     continue;
5576 
5577                 if (!isValidUri(stringValue)) {
5578                     attributeContentError("namespace", "anyAttribute", stringValue, BuiltinTypes::xsAnyURI);
5579                     return wildcard;
5580                 }
5581             }
5582 
5583             wildcard->namespaceConstraint()->setNamespaces(QSet<QString>(newValues.cbegin(), newValues.cend()));
5584         }
5585     } else {
5586         wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
5587     }
5588 
5589     if (hasAttribute(QString::fromLatin1("processContents"))) {
5590         const QString value = readAttribute(QString::fromLatin1("processContents"));
5591         if (value != QString::fromLatin1("lax") &&
5592             value != QString::fromLatin1("skip") &&
5593             value != QString::fromLatin1("strict")) {
5594             attributeContentError("processContents", "anyAttribute", value);
5595             return wildcard;
5596         }
5597 
5598         if (value == QString::fromLatin1("lax")) {
5599             wildcard->setProcessContents(XsdWildcard::Lax);
5600         } else if (value == QString::fromLatin1("skip")) {
5601             wildcard->setProcessContents(XsdWildcard::Skip);
5602         } else if (value == QString::fromLatin1("strict")) {
5603             wildcard->setProcessContents(XsdWildcard::Strict);
5604         }
5605     } else {
5606         wildcard->setProcessContents(XsdWildcard::Strict);
5607     }
5608 
5609     validateIdAttribute("anyAttribute");
5610 
5611     TagValidationHandler tagValidator(XsdTagScope::AnyAttribute, this, m_namePool);
5612 
5613     while (!atEnd()) {
5614         readNext();
5615 
5616         if (isEndElement())
5617             break;
5618 
5619         if (isStartElement()) {
5620             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5621             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5622 
5623             tagValidator.validate(token);
5624 
5625             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5626                 const XsdAnnotation::Ptr annotation = parseAnnotation();
5627                 wildcard->addAnnotation(annotation);
5628             } else {
5629                 parseUnknown();
5630             }
5631         }
5632     }
5633 
5634     tagValidator.finalize();
5635 
5636     return wildcard;
5637 }
5638 
5639 
parseUnknownDocumentation()5640 void XsdSchemaParser::parseUnknownDocumentation()
5641 {
5642     Q_ASSERT(isStartElement());
5643     m_namespaceSupport.pushContext();
5644     m_namespaceSupport.setPrefixes(namespaceDeclarations());
5645 
5646     while (!atEnd()) {
5647         readNext();
5648 
5649         if (isEndElement())
5650             break;
5651 
5652         if (isStartElement())
5653             parseUnknownDocumentation();
5654     }
5655 
5656     m_namespaceSupport.popContext();
5657 }
5658 
parseUnknown()5659 void XsdSchemaParser::parseUnknown()
5660 {
5661     Q_ASSERT(isStartElement());
5662     m_namespaceSupport.pushContext();
5663     m_namespaceSupport.setPrefixes(namespaceDeclarations());
5664 
5665     error(QtXmlPatterns::tr("%1 element is not allowed in this context.").arg(formatElement(name().toString())));
5666 
5667     while (!atEnd()) {
5668         readNext();
5669 
5670         if (isEndElement())
5671             break;
5672 
5673         if (isStartElement())
5674             parseUnknown();
5675     }
5676 
5677     m_namespaceSupport.popContext();
5678 }
5679 
parseMinMaxConstraint(const XsdParticle::Ptr & particle,const char * elementName)5680 bool XsdSchemaParser::parseMinMaxConstraint(const XsdParticle::Ptr &particle, const char *elementName)
5681 {
5682     if (hasAttribute(QString::fromLatin1("minOccurs"))) {
5683         const QString value = readAttribute(QString::fromLatin1("minOccurs"));
5684 
5685         DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
5686         if (integer->hasError()) {
5687             attributeContentError("minOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger);
5688             return false;
5689         } else {
5690             particle->setMinimumOccurs(integer->as< DerivedInteger<TypeNonNegativeInteger> >()->storedValue());
5691         }
5692     } else {
5693         particle->setMinimumOccurs(1);
5694     }
5695 
5696     if (hasAttribute(QString::fromLatin1("maxOccurs"))) {
5697         const QString value = readAttribute(QString::fromLatin1("maxOccurs"));
5698 
5699         if (value == QString::fromLatin1("unbounded")) {
5700             particle->setMaximumOccursUnbounded(true);
5701         } else {
5702             particle->setMaximumOccursUnbounded(false);
5703             DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
5704             if (integer->hasError()) {
5705                 attributeContentError("maxOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger);
5706                 return false;
5707             } else {
5708                 particle->setMaximumOccurs(integer->as< DerivedInteger<TypeNonNegativeInteger> >()->storedValue());
5709             }
5710         }
5711     } else {
5712         particle->setMaximumOccursUnbounded(false);
5713         particle->setMaximumOccurs(1);
5714     }
5715 
5716     if (!particle->maximumOccursUnbounded()) {
5717         if (particle->maximumOccurs() < particle->minimumOccurs()) {
5718             error(QtXmlPatterns::tr("%1 attribute of %2 element has larger value than %3 attribute.")
5719                                    .arg(formatAttribute("minOccurs"))
5720                                    .arg(formatElement(elementName))
5721                                    .arg(formatAttribute("maxOccurs")));
5722             return false;
5723         }
5724     }
5725 
5726     return true;
5727 }
5728 
currentSourceLocation() const5729 QSourceLocation XsdSchemaParser::currentSourceLocation() const
5730 {
5731     QSourceLocation location;
5732     location.setLine(lineNumber());
5733     location.setColumn(columnNumber());
5734     location.setUri(m_documentURI);
5735 
5736     return location;
5737 }
5738 
convertName(const QString & qualifiedName,NamespaceSupport::NameType type,QXmlName & name)5739 void XsdSchemaParser::convertName(const QString &qualifiedName, NamespaceSupport::NameType type, QXmlName &name)
5740 {
5741     bool result = m_namespaceSupport.processName(qualifiedName, type, name);
5742     if (!result) {
5743         error(QtXmlPatterns::tr("Prefix of qualified name %1 is not defined.").arg(formatKeyword(qualifiedName)));
5744     }
5745 }
5746 
readNameAttribute(const char * elementName)5747 QString XsdSchemaParser::readNameAttribute(const char *elementName)
5748 {
5749     const QString value = readAttribute(QString::fromLatin1("name")).simplified();
5750     if (!QXmlUtils::isNCName(value)) {
5751         attributeContentError("name", elementName, value, BuiltinTypes::xsNCName);
5752         return QString();
5753     } else {
5754         return value;
5755     }
5756 }
5757 
readQNameAttribute(const QString & typeAttribute,const char * elementName)5758 QString XsdSchemaParser::readQNameAttribute(const QString &typeAttribute, const char *elementName)
5759 {
5760     const QString value = readAttribute(typeAttribute).simplified();
5761     if (!XPathHelper::isQName(value)) {
5762         attributeContentError(typeAttribute.toLatin1(), elementName, value, BuiltinTypes::xsQName);
5763         return QString();
5764     } else {
5765         return value;
5766     }
5767 }
5768 
readNamespaceAttribute(const QString & attributeName,const char * elementName)5769 QString XsdSchemaParser::readNamespaceAttribute(const QString &attributeName, const char *elementName)
5770 {
5771     const QString value = readAttribute(attributeName);
5772     if (value.isEmpty()) {
5773         attributeContentError(attributeName.toLatin1(), elementName, value, BuiltinTypes::xsAnyURI);
5774         return QString();
5775     }
5776 
5777     return value;
5778 }
5779 
readDerivationConstraintAttribute(const SchemaType::DerivationConstraints & allowedConstraints,const char * elementName)5780 SchemaType::DerivationConstraints XsdSchemaParser::readDerivationConstraintAttribute(const SchemaType::DerivationConstraints &allowedConstraints, const char *elementName)
5781 {
5782     // first convert the flags into strings for easier comparison
5783     QSet<QString> allowedContent;
5784     if (allowedConstraints & SchemaType::RestrictionConstraint)
5785         allowedContent.insert(QString::fromLatin1("restriction"));
5786     if (allowedConstraints & SchemaType::ExtensionConstraint)
5787         allowedContent.insert(QString::fromLatin1("extension"));
5788     if (allowedConstraints & SchemaType::ListConstraint)
5789         allowedContent.insert(QString::fromLatin1("list"));
5790     if (allowedConstraints & SchemaType::UnionConstraint)
5791         allowedContent.insert(QString::fromLatin1("union"));
5792 
5793     // read content from the attribute if available, otherwise use the default definitions from the schema tag
5794     QString content;
5795     if (hasAttribute(QString::fromLatin1("final"))) {
5796         content = readAttribute(QString::fromLatin1("final"));
5797 
5798         // split string into list to validate the content of the attribute
5799         const QStringList values = content.split(QLatin1Char(' '), Qt::SkipEmptyParts);
5800         for (int i = 0; i < values.count(); i++) {
5801             const QString value = values.at(i);
5802             if (!allowedContent.contains(value) && (value != QString::fromLatin1("#all"))) {
5803                 attributeContentError("final", elementName, value);
5804                 return SchemaType::DerivationConstraints();
5805             }
5806 
5807             if ((value == QString::fromLatin1("#all")) && values.count() != 1) {
5808                 error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values.")
5809                                        .arg(formatAttribute("final"))
5810                                        .arg(formatElement(elementName))
5811                                        .arg(formatData("#all")));
5812                 return SchemaType::DerivationConstraints();
5813             }
5814         }
5815     } else {
5816         // content of the default value has been validated in parseSchema already
5817         content = m_finalDefault;
5818     }
5819 
5820     const auto &contentList = content.split(QLatin1Char(' '), Qt::SkipEmptyParts);
5821     QSet<QString> contentSet(contentList.cbegin(), contentList.cend());
5822 
5823     // if the '#all' tag is defined, we return all allowed values
5824     if (contentSet.contains(QString::fromLatin1("#all"))) {
5825         return allowedConstraints;
5826     } else { // return the values from content set that intersects with the allowed values
5827         contentSet.intersect(allowedContent);
5828 
5829         SchemaType::DerivationConstraints constraints;
5830 
5831         if (contentSet.contains(QString::fromLatin1("restriction")))
5832             constraints |= SchemaType::RestrictionConstraint;
5833         if (contentSet.contains(QString::fromLatin1("extension")))
5834             constraints |= SchemaType::ExtensionConstraint;
5835         if (contentSet.contains(QString::fromLatin1("list")))
5836             constraints |= SchemaType::ListConstraint;
5837         if (contentSet.contains(QString::fromLatin1("union")))
5838             constraints |= SchemaType::UnionConstraint;
5839 
5840         return constraints;
5841     }
5842 }
5843 
readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints & allowedConstraints,const char * elementName)5844 NamedSchemaComponent::BlockingConstraints XsdSchemaParser::readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints &allowedConstraints, const char *elementName)
5845 {
5846     // first convert the flags into strings for easier comparison
5847     QSet<QString> allowedContent;
5848     if (allowedConstraints & NamedSchemaComponent::RestrictionConstraint)
5849         allowedContent.insert(QString::fromLatin1("restriction"));
5850     if (allowedConstraints & NamedSchemaComponent::ExtensionConstraint)
5851         allowedContent.insert(QString::fromLatin1("extension"));
5852     if (allowedConstraints & NamedSchemaComponent::SubstitutionConstraint)
5853         allowedContent.insert(QString::fromLatin1("substitution"));
5854 
5855     // read content from the attribute if available, otherwise use the default definitions from the schema tag
5856     QString content;
5857     if (hasAttribute(QString::fromLatin1("block"))) {
5858         content = readAttribute(QString::fromLatin1("block"));
5859 
5860         // split string into list to validate the content of the attribute
5861         const QStringList values = content.split(QLatin1Char(' '), Qt::SkipEmptyParts);
5862         for (int i = 0; i < values.count(); i++) {
5863             const QString value = values.at(i);
5864             if (!allowedContent.contains(value) && (value != QString::fromLatin1("#all"))) {
5865                 attributeContentError("block", elementName, value);
5866                 return NamedSchemaComponent::BlockingConstraints();
5867             }
5868 
5869             if ((value == QString::fromLatin1("#all")) && values.count() != 1) {
5870                 error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values.")
5871                                        .arg(formatAttribute("block"))
5872                                        .arg(formatElement(elementName))
5873                                        .arg(formatData("#all")));
5874                 return NamedSchemaComponent::BlockingConstraints();
5875             }
5876         }
5877     } else {
5878         // content of the default value has been validated in parseSchema already
5879         content = m_blockDefault;
5880     }
5881 
5882     const auto &contentList = content.split(QLatin1Char(' '), Qt::SkipEmptyParts);
5883     QSet<QString> contentSet(contentList.cbegin(), contentList.cend());
5884 
5885     // if the '#all' tag is defined, we return all allowed values
5886     if (contentSet.contains(QString::fromLatin1("#all"))) {
5887         return allowedConstraints;
5888     } else { // return the values from content set that intersects with the allowed values
5889         contentSet.intersect(allowedContent);
5890 
5891         NamedSchemaComponent::BlockingConstraints constraints;
5892 
5893         if (contentSet.contains(QString::fromLatin1("restriction")))
5894             constraints |= NamedSchemaComponent::RestrictionConstraint;
5895         if (contentSet.contains(QString::fromLatin1("extension")))
5896             constraints |= NamedSchemaComponent::ExtensionConstraint;
5897         if (contentSet.contains(QString::fromLatin1("substitution")))
5898             constraints |= NamedSchemaComponent::SubstitutionConstraint;
5899 
5900         return constraints;
5901     }
5902 }
5903 
readXPathExpression(const char * elementName)5904 XsdXPathExpression::Ptr XsdSchemaParser::readXPathExpression(const char *elementName)
5905 {
5906     const XsdXPathExpression::Ptr expression(new XsdXPathExpression());
5907 
5908     const QList<QXmlName> namespaceBindings = m_namespaceSupport.namespaceBindings();
5909     QXmlName emptyName;
5910     for (int i = 0; i < namespaceBindings.count(); ++i) {
5911         if (namespaceBindings.at(i).prefix() == StandardPrefixes::empty)
5912             emptyName = namespaceBindings.at(i);
5913     }
5914 
5915     expression->setNamespaceBindings(namespaceBindings);
5916 
5917     QString xpathDefaultNamespace;
5918     if (hasAttribute(QString::fromLatin1("xpathDefaultNamespace"))) {
5919         xpathDefaultNamespace = readAttribute(QString::fromLatin1("xpathDefaultNamespace"));
5920         if (xpathDefaultNamespace != QString::fromLatin1("##defaultNamespace") &&
5921             xpathDefaultNamespace != QString::fromLatin1("##targetNamespace") &&
5922             xpathDefaultNamespace != QString::fromLatin1("##local")) {
5923             if (!isValidUri(xpathDefaultNamespace)) {
5924                 attributeContentError("xpathDefaultNamespace", elementName, xpathDefaultNamespace, BuiltinTypes::xsAnyURI);
5925                 return expression;
5926             }
5927         }
5928     } else {
5929         xpathDefaultNamespace = m_xpathDefaultNamespace;
5930     }
5931 
5932     AnyURI::Ptr namespaceURI;
5933     if (xpathDefaultNamespace == QString::fromLatin1("##defaultNamespace")) {
5934         if (!emptyName.isNull())
5935             namespaceURI = AnyURI::fromLexical(m_namePool->stringForNamespace(emptyName.namespaceURI()));
5936     } else if (xpathDefaultNamespace == QString::fromLatin1("##targetNamespace")) {
5937         if (!m_targetNamespace.isEmpty())
5938             namespaceURI = AnyURI::fromLexical(m_targetNamespace);
5939     } else if (xpathDefaultNamespace == QString::fromLatin1("##local")) {
5940         // it is absent
5941     } else {
5942         namespaceURI = AnyURI::fromLexical(xpathDefaultNamespace);
5943     }
5944     if (namespaceURI) {
5945         if (namespaceURI->hasError()) {
5946             attributeContentError("xpathDefaultNamespace", elementName, xpathDefaultNamespace, BuiltinTypes::xsAnyURI);
5947             return expression;
5948         }
5949 
5950         expression->setDefaultNamespace(namespaceURI);
5951     }
5952 
5953     //TODO: read the base uri if qmaintaining reader support it
5954 
5955     return expression;
5956 }
5957 
readXPathAttribute(const QString & attributeName,XPathType type,const char * elementName)5958 QString XsdSchemaParser::readXPathAttribute(const QString &attributeName, XPathType type,  const char *elementName)
5959 {
5960     const QString value = readAttribute(attributeName);
5961     if (value.isEmpty() || value.startsWith(QLatin1Char('/'))) {
5962         attributeContentError(attributeName.toLatin1(), elementName, value);
5963         return QString();
5964     }
5965 
5966     QXmlNamePool namePool(m_namePool.data());
5967 
5968     QXmlQuery::QueryLanguage language = QXmlQuery::XPath20;
5969     switch (type) {
5970         case XPath20: language = QXmlQuery::XPath20; break;
5971         case XPathSelector: language = QXmlQuery::XmlSchema11IdentityConstraintSelector; break;
5972         case XPathField: language = QXmlQuery::XmlSchema11IdentityConstraintField; break;
5973     };
5974 
5975     QXmlQuery query(language, namePool);
5976     QXmlQueryPrivate *queryPrivate = query.d;
5977 
5978     const QList<QXmlName> namespaceBindings = m_namespaceSupport.namespaceBindings();
5979     for (int i = 0; i < namespaceBindings.count(); ++i) {
5980         if (namespaceBindings.at(i).prefix() != StandardPrefixes::empty)
5981             queryPrivate->addAdditionalNamespaceBinding(namespaceBindings.at(i));
5982     }
5983 
5984     query.setQuery(value, m_documentURI);
5985     if (!query.isValid()) {
5986         attributeContentError(attributeName.toLatin1(), elementName, value);
5987         return QString();
5988     }
5989 
5990     return value;
5991 }
5992 
validateIdAttribute(const char * elementName)5993 void XsdSchemaParser::validateIdAttribute(const char *elementName)
5994 {
5995     if (hasAttribute(QString::fromLatin1("id"))) {
5996         const QString value = readAttribute(QString::fromLatin1("id"));
5997         DerivedString<TypeID>::Ptr id = DerivedString<TypeID>::fromLexical(m_namePool, value);
5998         if (id->hasError()) {
5999             attributeContentError("id", elementName, value, BuiltinTypes::xsID);
6000         } else {
6001             if (m_idCache->hasId(value)) {
6002                 error(QtXmlPatterns::tr("Component with ID %1 has been defined previously.").arg(formatData(value)));
6003             } else {
6004                 m_idCache->addId(value);
6005             }
6006         }
6007     }
6008 }
6009 
isSchemaTag(XsdSchemaToken::NodeName tag,XsdSchemaToken::NodeName token,XsdSchemaToken::NodeName namespaceToken) const6010 bool XsdSchemaParser::isSchemaTag(XsdSchemaToken::NodeName tag, XsdSchemaToken::NodeName token, XsdSchemaToken::NodeName namespaceToken) const
6011 {
6012     return ((tag == token) && (namespaceToken == XsdSchemaToken::XML_NS_SCHEMA_URI));
6013 }
6014 
addElement(const XsdElement::Ptr & element)6015 void XsdSchemaParser::addElement(const XsdElement::Ptr &element)
6016 {
6017     const QXmlName objectName = element->name(m_namePool);
6018     if (m_schema->element(objectName)) {
6019         error(QtXmlPatterns::tr("Element %1 already defined.").arg(formatElement(m_namePool->displayName(objectName))));
6020     } else {
6021         m_schema->addElement(element);
6022         m_componentLocationHash.insert(element, currentSourceLocation());
6023     }
6024 }
6025 
addAttribute(const XsdAttribute::Ptr & attribute)6026 void XsdSchemaParser::addAttribute(const XsdAttribute::Ptr &attribute)
6027 {
6028     const QXmlName objectName = attribute->name(m_namePool);
6029     if (m_schema->attribute(objectName)) {
6030         error(QtXmlPatterns::tr("Attribute %1 already defined.").arg(formatAttribute(m_namePool->displayName(objectName))));
6031     } else {
6032         m_schema->addAttribute(attribute);
6033         m_componentLocationHash.insert(attribute, currentSourceLocation());
6034     }
6035 }
6036 
addType(const SchemaType::Ptr & type)6037 void XsdSchemaParser::addType(const SchemaType::Ptr &type)
6038 {
6039     // we don't import redefinitions of builtin types, that just causes problems
6040     if (m_builtinTypeNames.contains(type->name(m_namePool)))
6041         return;
6042 
6043     const QXmlName objectName = type->name(m_namePool);
6044     if (m_schema->type(objectName)) {
6045         error(QtXmlPatterns::tr("Type %1 already defined.").arg(formatType(m_namePool, objectName)));
6046     } else {
6047         m_schema->addType(type);
6048         if (type->isSimpleType())
6049             m_componentLocationHash.insert(XsdSimpleType::Ptr(type), currentSourceLocation());
6050         else
6051             m_componentLocationHash.insert(XsdComplexType::Ptr(type), currentSourceLocation());
6052     }
6053 }
6054 
addAnonymousType(const SchemaType::Ptr & type)6055 void XsdSchemaParser::addAnonymousType(const SchemaType::Ptr &type)
6056 {
6057     m_schema->addAnonymousType(type);
6058     if (type->isSimpleType())
6059         m_componentLocationHash.insert(XsdSimpleType::Ptr(type), currentSourceLocation());
6060     else
6061         m_componentLocationHash.insert(XsdComplexType::Ptr(type), currentSourceLocation());
6062 }
6063 
addAttributeGroup(const XsdAttributeGroup::Ptr & group)6064 void XsdSchemaParser::addAttributeGroup(const XsdAttributeGroup::Ptr &group)
6065 {
6066     const QXmlName objectName = group->name(m_namePool);
6067     if (m_schema->attributeGroup(objectName)) {
6068         error(QtXmlPatterns::tr("Attribute group %1 already defined.").arg(formatKeyword(m_namePool, objectName)));
6069     } else {
6070         m_schema->addAttributeGroup(group);
6071         m_componentLocationHash.insert(group, currentSourceLocation());
6072     }
6073 }
6074 
addElementGroup(const XsdModelGroup::Ptr & group)6075 void XsdSchemaParser::addElementGroup(const XsdModelGroup::Ptr &group)
6076 {
6077     const QXmlName objectName = group->name(m_namePool);
6078     if (m_schema->elementGroup(objectName)) {
6079         error(QtXmlPatterns::tr("Element group %1 already defined.").arg(formatKeyword(m_namePool, objectName)));
6080     } else {
6081         m_schema->addElementGroup(group);
6082         m_componentLocationHash.insert(group, currentSourceLocation());
6083     }
6084 }
6085 
addNotation(const XsdNotation::Ptr & notation)6086 void XsdSchemaParser::addNotation(const XsdNotation::Ptr &notation)
6087 {
6088     const QXmlName objectName = notation->name(m_namePool);
6089     if (m_schema->notation(objectName)) {
6090         error(QtXmlPatterns::tr("Notation %1 already defined.").arg(formatKeyword(m_namePool, objectName)));
6091     } else {
6092         m_schema->addNotation(notation);
6093         m_componentLocationHash.insert(notation, currentSourceLocation());
6094     }
6095 }
6096 
addIdentityConstraint(const XsdIdentityConstraint::Ptr & constraint)6097 void XsdSchemaParser::addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint)
6098 {
6099     const QXmlName objectName = constraint->name(m_namePool);
6100     if (m_schema->identityConstraint(objectName)) {
6101         error(QtXmlPatterns::tr("Identity constraint %1 already defined.").arg(formatKeyword(m_namePool, objectName)));
6102     } else {
6103         m_schema->addIdentityConstraint(constraint);
6104         m_componentLocationHash.insert(constraint, currentSourceLocation());
6105     }
6106 }
6107 
addFacet(const XsdFacet::Ptr & facet,XsdFacet::Hash & facets,const SchemaType::Ptr & type)6108 void XsdSchemaParser::addFacet(const XsdFacet::Ptr &facet, XsdFacet::Hash &facets, const SchemaType::Ptr &type)
6109 {
6110     // @see http://www.w3.org/TR/xmlschema-2/#src-single-facet-value
6111     if (facets.contains(facet->type())) {
6112         error(QtXmlPatterns::tr("Duplicated facets in simple type %1.").arg(formatType(m_namePool, type)));
6113         return;
6114     }
6115 
6116     facets.insert(facet->type(), facet);
6117 }
6118 
6119 QT_END_NAMESPACE
6120