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