util/src/xmlpatterns/schema/qxsdschemaparser.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    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          */
       
   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          */
       
   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:
       
   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 
       
   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 
       
   190         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  */
       
   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  */
       
   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 
       
   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)
       
   255     , m_parserContext(parserContext)
       
   256     , m_namePool(m_parserContext->namePool())
       
   257     , m_namespaceSupport(m_namePool)
       
   258 {
       
   259     m_schema = m_parserContext->schema();
       
   260     m_schemaResolver = m_parserContext->resolver();
       
   261     m_idCache = XsdIdCache::Ptr(new XsdIdCache());
       
   262 
       
   263     setupStateMachines();
       
   264     setupBuiltinTypeNames();
       
   265 }
       
   266 
       
   267 void XsdSchemaParser::addIncludedSchemas(const NamespaceSet &schemas)
       
   268 {
       
   269     m_includedSchemas += schemas;
       
   270 }
       
   271 
       
   272 void XsdSchemaParser::setIncludedSchemas(const NamespaceSet &schemas)
       
   273 {
       
   274     m_includedSchemas = schemas;
       
   275 }
       
   276 
       
   277 void XsdSchemaParser::addImportedSchemas(const NamespaceSet &schemas)
       
   278 {
       
   279     m_importedSchemas += schemas;
       
   280 }
       
   281 
       
   282 void XsdSchemaParser::setImportedSchemas(const NamespaceSet &schemas)
       
   283 {
       
   284     m_importedSchemas = schemas;
       
   285 }
       
   286 
       
   287 void XsdSchemaParser::addRedefinedSchemas(const NamespaceSet &schemas)
       
   288 {
       
   289     m_redefinedSchemas += schemas;
       
   290 }
       
   291 
       
   292 void XsdSchemaParser::setRedefinedSchemas(const NamespaceSet &schemas)
       
   293 {
       
   294     m_redefinedSchemas = schemas;
       
   295 }
       
   296 
       
   297 void XsdSchemaParser::setTargetNamespace(const QString &targetNamespace)
       
   298 {
       
   299     m_targetNamespace = targetNamespace;
       
   300 }
       
   301 
       
   302 void XsdSchemaParser::setTargetNamespaceExtended(const QString &targetNamespace)
       
   303 {
       
   304     m_targetNamespace = targetNamespace;
       
   305     m_namespaceSupport.setTargetNamespace(m_namePool->allocateNamespace(m_targetNamespace));
       
   306 }
       
   307 
       
   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 
       
   318 QUrl XsdSchemaParser::documentURI() const
       
   319 {
       
   320     return m_documentURI;
       
   321 }
       
   322 
       
   323 bool XsdSchemaParser::isAnyAttributeAllowed() const
       
   324 {
       
   325     return false;
       
   326 }
       
   327 
       
   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 
       
   356 void XsdSchemaParser::error(const QString &msg)
       
   357 {
       
   358     MaintainingReader<XsdSchemaToken, XsdTagScope::Type>::error(msg, XsdSchemaContext::XSDError);
       
   359 }
       
   360 
       
   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(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 
       
   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, 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 
       
   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                                                                          m_context, AccelTreeResourceLoader::ContinueOnError));
       
   605         if (reply) {
       
   606             // parse the included schema by a different parser but with the same context
       
   607             XsdSchemaParser parser(m_context, 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, 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 
       
   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                                                                        m_context, AccelTreeResourceLoader::ContinueOnError));
       
   701             if (reply) {
       
   702                 // parse the included schema by a different parser but with the same context
       
   703                 XsdSchemaParser parser(m_context, 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(m_context, 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, 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 
       
   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, 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(m_namePool)) {
       
   816                     error(QString::fromLatin1("redefined simple type %1 must have itself as base type").arg(formatType(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(m_namePool)) {
       
   828                     error(QString::fromLatin1("redefined complex type %1 must have itself as base type").arg(formatType(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(m_namePool, 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                                                              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(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(m_namePool) == contextType->name(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 explicitely
       
   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(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(m_namePool) == contextType->name(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 explicitely
       
   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(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(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(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(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(m_namePool) == contextGroups.at(j)->name(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(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(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(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(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(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(m_namePool) == contextGroup->name(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(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(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(m_namePool) == reference->referenceName()) {
       
  1118                             reference->setReferenceName(baseGroup->name(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(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 
       
  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, 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 
       
  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 
       
  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 
       
  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, 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 
       
  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, 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 
       
  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, 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 
       
  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, 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 
       
  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, 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(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse)));
       
  1717     XsdFacet::Hash facets;
       
  1718     facets.insert(defaultFacet->type(), defaultFacet);
       
  1719     ptr->setFacets(facets);
       
  1720 }
       
  1721 
       
  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 hasMemberTypesAttribute = false;
       
  1735     bool hasMemberTypesSpecified = false;
       
  1736 
       
  1737     if (hasAttribute(QString::fromLatin1("memberTypes"))) {
       
  1738         hasMemberTypesAttribute = true;
       
  1739 
       
  1740         const QStringList memberTypes = readAttribute(QString::fromLatin1("memberTypes")).split(QLatin1Char(' '), QString::SkipEmptyParts);
       
  1741         QList<QXmlName> typeNames;
       
  1742 
       
  1743         for (int i = 0; i < memberTypes.count(); ++i) {
       
  1744             QXmlName typeName;
       
  1745             convertName(memberTypes.at(i), NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  1746             typeNames.append(typeName);
       
  1747         }
       
  1748 
       
  1749         if (!typeNames.isEmpty()) {
       
  1750             m_schemaResolver->addSimpleUnionTypes(ptr, typeNames, currentSourceLocation()); // add to resolver
       
  1751             hasMemberTypesSpecified = true;
       
  1752         }
       
  1753     }
       
  1754 
       
  1755     validateIdAttribute("union");
       
  1756 
       
  1757     AnySimpleType::List memberTypes;
       
  1758 
       
  1759     TagValidationHandler tagValidator(XsdTagScope::Union, this, m_namePool);
       
  1760 
       
  1761     while (!atEnd()) {
       
  1762         readNext();
       
  1763 
       
  1764         if (isEndElement())
       
  1765             break;
       
  1766 
       
  1767         if (isStartElement()) {
       
  1768             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  1769             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  1770 
       
  1771             tagValidator.validate(token);
       
  1772 
       
  1773             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  1774                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  1775                 ptr->addAnnotation(annotation);
       
  1776             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
       
  1777                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
       
  1778                 type->setContext(ptr);
       
  1779                 memberTypes.append(type);
       
  1780 
       
  1781                 // add it to list of anonymous types as well
       
  1782                 addAnonymousType(type);
       
  1783             } else {
       
  1784                 parseUnknown();
       
  1785             }
       
  1786         }
       
  1787     }
       
  1788 
       
  1789     if (!memberTypes.isEmpty()) {
       
  1790         ptr->setMemberTypes(memberTypes);
       
  1791         hasMemberTypesSpecified = true;
       
  1792     }
       
  1793 
       
  1794     if (!hasMemberTypesSpecified) {
       
  1795         error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element.")
       
  1796                                .arg(formatElement("union"))
       
  1797                                .arg(formatAttribute("memberTypes"))
       
  1798                                .arg(formatElement("simpleType")));
       
  1799         return;
       
  1800     }
       
  1801 
       
  1802     tagValidator.finalize();
       
  1803 }
       
  1804 
       
  1805 XsdFacet::Ptr XsdSchemaParser::parseMinExclusiveFacet()
       
  1806 {
       
  1807     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinExclusive, this);
       
  1808 
       
  1809     validateElement(XsdTagScope::MinExclusiveFacet);
       
  1810 
       
  1811     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  1812     facet->setType(XsdFacet::MinimumExclusive);
       
  1813 
       
  1814     // parse attributes
       
  1815     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  1816         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  1817         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  1818         if (fixed->hasError()) {
       
  1819             attributeContentError("fixed", "minExclusive", value, BuiltinTypes::xsBoolean);
       
  1820             return facet;
       
  1821         }
       
  1822 
       
  1823         facet->setFixed(fixed->as<Boolean>()->value());
       
  1824     } else {
       
  1825         facet->setFixed(false); // the default value
       
  1826     }
       
  1827 
       
  1828     // as minExclusive can have a value of type anySimpleType, we just read
       
  1829     // the string here and store it for later intepretation
       
  1830     const QString value = readAttribute(QString::fromLatin1("value"));
       
  1831     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
       
  1832     if (string->hasError()) {
       
  1833         attributeContentError("value", "minExclusive", value, BuiltinTypes::xsAnySimpleType);
       
  1834         return facet;
       
  1835     } else {
       
  1836         facet->setValue(string);
       
  1837     }
       
  1838 
       
  1839     validateIdAttribute("minExclusive");
       
  1840 
       
  1841     TagValidationHandler tagValidator(XsdTagScope::MinExclusiveFacet, this, m_namePool);
       
  1842 
       
  1843     while (!atEnd()) {
       
  1844         readNext();
       
  1845 
       
  1846         if (isEndElement())
       
  1847             break;
       
  1848 
       
  1849         if (isStartElement()) {
       
  1850             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  1851             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  1852 
       
  1853             tagValidator.validate(token);
       
  1854 
       
  1855             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  1856                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  1857                 facet->addAnnotation(annotation);
       
  1858             } else {
       
  1859                 parseUnknown();
       
  1860             }
       
  1861         }
       
  1862     }
       
  1863 
       
  1864     tagValidator.finalize();
       
  1865 
       
  1866     return facet;
       
  1867 }
       
  1868 
       
  1869 XsdFacet::Ptr XsdSchemaParser::parseMinInclusiveFacet()
       
  1870 {
       
  1871     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinInclusive, this);
       
  1872 
       
  1873     validateElement(XsdTagScope::MinInclusiveFacet);
       
  1874 
       
  1875     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  1876     facet->setType(XsdFacet::MinimumInclusive);
       
  1877 
       
  1878     // parse attributes
       
  1879     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  1880         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  1881         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  1882         if (fixed->hasError()) {
       
  1883             attributeContentError("fixed", "minInclusive", value, BuiltinTypes::xsBoolean);
       
  1884             return facet;
       
  1885         }
       
  1886 
       
  1887         facet->setFixed(fixed->as<Boolean>()->value());
       
  1888     } else {
       
  1889         facet->setFixed(false); // the default value
       
  1890     }
       
  1891 
       
  1892     // as minInclusive can have a value of type anySimpleType, we just read
       
  1893     // the string here and store it for later intepretation
       
  1894     const QString value = readAttribute(QString::fromLatin1("value"));
       
  1895     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
       
  1896     if (string->hasError()) {
       
  1897         attributeContentError("value", "minInclusive", value, BuiltinTypes::xsAnySimpleType);
       
  1898         return facet;
       
  1899     } else {
       
  1900         facet->setValue(string);
       
  1901     }
       
  1902 
       
  1903     validateIdAttribute("minInclusive");
       
  1904 
       
  1905     TagValidationHandler tagValidator(XsdTagScope::MinInclusiveFacet, this, m_namePool);
       
  1906 
       
  1907     while (!atEnd()) {
       
  1908         readNext();
       
  1909 
       
  1910         if (isEndElement())
       
  1911             break;
       
  1912 
       
  1913         if (isStartElement()) {
       
  1914             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  1915             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  1916 
       
  1917             tagValidator.validate(token);
       
  1918 
       
  1919             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  1920                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  1921                 facet->addAnnotation(annotation);
       
  1922             } else {
       
  1923                 parseUnknown();
       
  1924             }
       
  1925         }
       
  1926     }
       
  1927 
       
  1928     tagValidator.finalize();
       
  1929 
       
  1930     return facet;
       
  1931 }
       
  1932 
       
  1933 XsdFacet::Ptr XsdSchemaParser::parseMaxExclusiveFacet()
       
  1934 {
       
  1935     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxExclusive, this);
       
  1936 
       
  1937     validateElement(XsdTagScope::MaxExclusiveFacet);
       
  1938 
       
  1939     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  1940     facet->setType(XsdFacet::MaximumExclusive);
       
  1941 
       
  1942     // parse attributes
       
  1943     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  1944         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  1945         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  1946         if (fixed->hasError()) {
       
  1947             attributeContentError("fixed", "maxExclusive", value, BuiltinTypes::xsBoolean);
       
  1948             return facet;
       
  1949         }
       
  1950 
       
  1951         facet->setFixed(fixed->as<Boolean>()->value());
       
  1952     } else {
       
  1953         facet->setFixed(false); // the default value
       
  1954     }
       
  1955 
       
  1956     // as maxExclusive can have a value of type anySimpleType, we just read
       
  1957     // the string here and store it for later intepretation
       
  1958     const QString value = readAttribute(QString::fromLatin1("value"));
       
  1959     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
       
  1960     if (string->hasError()) {
       
  1961         attributeContentError("value", "maxExclusive", value, BuiltinTypes::xsAnySimpleType);
       
  1962         return facet;
       
  1963     } else {
       
  1964         facet->setValue(string);
       
  1965     }
       
  1966 
       
  1967     validateIdAttribute("maxExclusive");
       
  1968 
       
  1969     TagValidationHandler tagValidator(XsdTagScope::MaxExclusiveFacet, this, m_namePool);
       
  1970 
       
  1971     while (!atEnd()) {
       
  1972         readNext();
       
  1973 
       
  1974         if (isEndElement())
       
  1975             break;
       
  1976 
       
  1977         if (isStartElement()) {
       
  1978             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  1979             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  1980 
       
  1981             tagValidator.validate(token);
       
  1982 
       
  1983             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  1984                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  1985                 facet->addAnnotation(annotation);
       
  1986             } else {
       
  1987                 parseUnknown();
       
  1988             }
       
  1989         }
       
  1990     }
       
  1991 
       
  1992     tagValidator.finalize();
       
  1993 
       
  1994     return facet;
       
  1995 }
       
  1996 
       
  1997 XsdFacet::Ptr XsdSchemaParser::parseMaxInclusiveFacet()
       
  1998 {
       
  1999     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxInclusive, this);
       
  2000 
       
  2001     validateElement(XsdTagScope::MaxInclusiveFacet);
       
  2002 
       
  2003     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2004     facet->setType(XsdFacet::MaximumInclusive);
       
  2005 
       
  2006     // parse attributes
       
  2007     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  2008         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  2009         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  2010         if (fixed->hasError()) {
       
  2011             attributeContentError("fixed", "maxInclusive", value, BuiltinTypes::xsBoolean);
       
  2012             return facet;
       
  2013         }
       
  2014 
       
  2015         facet->setFixed(fixed->as<Boolean>()->value());
       
  2016     } else {
       
  2017         facet->setFixed(false); // the default value
       
  2018     }
       
  2019 
       
  2020     // as maxInclusive can have a value of type anySimpleType, we just read
       
  2021     // the string here and store it for later intepretation
       
  2022     const QString value = readAttribute(QString::fromLatin1("value"));
       
  2023     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
       
  2024     if (string->hasError()) {
       
  2025         attributeContentError("value", "maxInclusive", value, BuiltinTypes::xsAnySimpleType);
       
  2026         return facet;
       
  2027     } else {
       
  2028         facet->setValue(string);
       
  2029     }
       
  2030 
       
  2031     validateIdAttribute("maxInclusive");
       
  2032 
       
  2033     TagValidationHandler tagValidator(XsdTagScope::MaxInclusiveFacet, this, m_namePool);
       
  2034 
       
  2035     while (!atEnd()) {
       
  2036         readNext();
       
  2037 
       
  2038         if (isEndElement())
       
  2039             break;
       
  2040 
       
  2041         if (isStartElement()) {
       
  2042             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2043             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2044 
       
  2045             tagValidator.validate(token);
       
  2046 
       
  2047             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2048                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2049                 facet->addAnnotation(annotation);
       
  2050             } else {
       
  2051                 parseUnknown();
       
  2052             }
       
  2053         }
       
  2054     }
       
  2055 
       
  2056     tagValidator.finalize();
       
  2057 
       
  2058     return facet;
       
  2059 }
       
  2060 
       
  2061 XsdFacet::Ptr XsdSchemaParser::parseTotalDigitsFacet()
       
  2062 {
       
  2063     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::TotalDigits, this);
       
  2064 
       
  2065     validateElement(XsdTagScope::TotalDigitsFacet);
       
  2066 
       
  2067     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2068     facet->setType(XsdFacet::TotalDigits);
       
  2069 
       
  2070     // parse attributes
       
  2071     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  2072         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  2073         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  2074         if (fixed->hasError()) {
       
  2075             attributeContentError("fixed", "totalDigits", value, BuiltinTypes::xsBoolean);
       
  2076             return facet;
       
  2077         }
       
  2078 
       
  2079         facet->setFixed(fixed->as<Boolean>()->value());
       
  2080     } else {
       
  2081         facet->setFixed(false); // the default value
       
  2082     }
       
  2083 
       
  2084     const QString value = readAttribute(QString::fromLatin1("value"));
       
  2085     DerivedInteger<TypePositiveInteger>::Ptr integer = DerivedInteger<TypePositiveInteger>::fromLexical(m_namePool, value);
       
  2086     if (integer->hasError()) {
       
  2087         attributeContentError("value", "totalDigits", value, BuiltinTypes::xsPositiveInteger);
       
  2088         return facet;
       
  2089     } else {
       
  2090         facet->setValue(integer);
       
  2091     }
       
  2092 
       
  2093     validateIdAttribute("totalDigits");
       
  2094 
       
  2095     TagValidationHandler tagValidator(XsdTagScope::TotalDigitsFacet, this, m_namePool);
       
  2096 
       
  2097     while (!atEnd()) {
       
  2098         readNext();
       
  2099 
       
  2100         if (isEndElement())
       
  2101             break;
       
  2102 
       
  2103         if (isStartElement()) {
       
  2104             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2105             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2106 
       
  2107             tagValidator.validate(token);
       
  2108 
       
  2109             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2110                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2111                 facet->addAnnotation(annotation);
       
  2112             } else {
       
  2113                 parseUnknown();
       
  2114             }
       
  2115         }
       
  2116     }
       
  2117 
       
  2118     tagValidator.finalize();
       
  2119 
       
  2120     return facet;
       
  2121 }
       
  2122 
       
  2123 XsdFacet::Ptr XsdSchemaParser::parseFractionDigitsFacet()
       
  2124 {
       
  2125     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::FractionDigits, this);
       
  2126 
       
  2127     validateElement(XsdTagScope::FractionDigitsFacet);
       
  2128 
       
  2129     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2130     facet->setType(XsdFacet::FractionDigits);
       
  2131 
       
  2132     // parse attributes
       
  2133     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  2134         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  2135         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  2136         if (fixed->hasError()) {
       
  2137             attributeContentError("fixed", "fractionDigits", value, BuiltinTypes::xsBoolean);
       
  2138             return facet;
       
  2139         }
       
  2140 
       
  2141         facet->setFixed(fixed->as<Boolean>()->value());
       
  2142     } else {
       
  2143         facet->setFixed(false); // the default value
       
  2144     }
       
  2145 
       
  2146     const QString value = readAttribute(QString::fromLatin1("value"));
       
  2147     DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
       
  2148     if (integer->hasError()) {
       
  2149         attributeContentError("value", "fractionDigits", value, BuiltinTypes::xsNonNegativeInteger);
       
  2150         return facet;
       
  2151     } else {
       
  2152         facet->setValue(integer);
       
  2153     }
       
  2154 
       
  2155     validateIdAttribute("fractionDigits");
       
  2156 
       
  2157     TagValidationHandler tagValidator(XsdTagScope::FractionDigitsFacet, this, m_namePool);
       
  2158 
       
  2159     while (!atEnd()) {
       
  2160         readNext();
       
  2161 
       
  2162         if (isEndElement())
       
  2163             break;
       
  2164 
       
  2165         if (isStartElement()) {
       
  2166             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2167             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2168 
       
  2169             tagValidator.validate(token);
       
  2170 
       
  2171             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2172                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2173                 facet->addAnnotation(annotation);
       
  2174             } else {
       
  2175                 parseUnknown();
       
  2176             }
       
  2177         }
       
  2178     }
       
  2179 
       
  2180     tagValidator.finalize();
       
  2181 
       
  2182     return facet;
       
  2183 }
       
  2184 
       
  2185 XsdFacet::Ptr XsdSchemaParser::parseLengthFacet()
       
  2186 {
       
  2187     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Length, this);
       
  2188 
       
  2189     validateElement(XsdTagScope::LengthFacet);
       
  2190 
       
  2191     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2192     facet->setType(XsdFacet::Length);
       
  2193 
       
  2194     // parse attributes
       
  2195     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  2196         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  2197         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  2198         if (fixed->hasError()) {
       
  2199             attributeContentError("fixed", "length", value, BuiltinTypes::xsBoolean);
       
  2200             return facet;
       
  2201         }
       
  2202 
       
  2203         facet->setFixed(fixed->as<Boolean>()->value());
       
  2204     } else {
       
  2205         facet->setFixed(false); // the default value
       
  2206     }
       
  2207 
       
  2208     const QString value = readAttribute(QString::fromLatin1("value"));
       
  2209     DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
       
  2210     if (integer->hasError()) {
       
  2211         attributeContentError("value", "length", value, BuiltinTypes::xsNonNegativeInteger);
       
  2212         return facet;
       
  2213     } else {
       
  2214         facet->setValue(integer);
       
  2215     }
       
  2216 
       
  2217     validateIdAttribute("length");
       
  2218 
       
  2219     TagValidationHandler tagValidator(XsdTagScope::LengthFacet, this, m_namePool);
       
  2220 
       
  2221     while (!atEnd()) {
       
  2222         readNext();
       
  2223 
       
  2224         if (isEndElement())
       
  2225             break;
       
  2226 
       
  2227         if (isStartElement()) {
       
  2228             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2229             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2230 
       
  2231             tagValidator.validate(token);
       
  2232 
       
  2233             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2234                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2235                 facet->addAnnotation(annotation);
       
  2236             } else {
       
  2237                 parseUnknown();
       
  2238             }
       
  2239         }
       
  2240     }
       
  2241 
       
  2242     tagValidator.finalize();
       
  2243 
       
  2244     return facet;
       
  2245 }
       
  2246 
       
  2247 XsdFacet::Ptr XsdSchemaParser::parseMinLengthFacet()
       
  2248 {
       
  2249     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinLength, this);
       
  2250 
       
  2251     validateElement(XsdTagScope::MinLengthFacet);
       
  2252 
       
  2253     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2254     facet->setType(XsdFacet::MinimumLength);
       
  2255 
       
  2256     // parse attributes
       
  2257     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  2258         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  2259         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  2260         if (fixed->hasError()) {
       
  2261             attributeContentError("fixed", "minLength", value, BuiltinTypes::xsBoolean);
       
  2262             return facet;
       
  2263         }
       
  2264 
       
  2265         facet->setFixed(fixed->as<Boolean>()->value());
       
  2266     } else {
       
  2267         facet->setFixed(false); // the default value
       
  2268     }
       
  2269 
       
  2270     const QString value = readAttribute(QString::fromLatin1("value"));
       
  2271     DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
       
  2272     if (integer->hasError()) {
       
  2273         attributeContentError("value", "minLength", value, BuiltinTypes::xsNonNegativeInteger);
       
  2274         return facet;
       
  2275     } else {
       
  2276         facet->setValue(integer);
       
  2277     }
       
  2278 
       
  2279     validateIdAttribute("minLength");
       
  2280 
       
  2281     TagValidationHandler tagValidator(XsdTagScope::MinLengthFacet, this, m_namePool);
       
  2282 
       
  2283     while (!atEnd()) {
       
  2284         readNext();
       
  2285 
       
  2286         if (isEndElement())
       
  2287             break;
       
  2288 
       
  2289         if (isStartElement()) {
       
  2290             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2291             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2292 
       
  2293             tagValidator.validate(token);
       
  2294 
       
  2295             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2296                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2297                 facet->addAnnotation(annotation);
       
  2298             } else {
       
  2299                 parseUnknown();
       
  2300             }
       
  2301         }
       
  2302     }
       
  2303 
       
  2304     tagValidator.finalize();
       
  2305 
       
  2306     return facet;
       
  2307 }
       
  2308 
       
  2309 XsdFacet::Ptr XsdSchemaParser::parseMaxLengthFacet()
       
  2310 {
       
  2311     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxLength, this);
       
  2312 
       
  2313     validateElement(XsdTagScope::MaxLengthFacet);
       
  2314 
       
  2315     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2316     facet->setType(XsdFacet::MaximumLength);
       
  2317 
       
  2318     // parse attributes
       
  2319     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  2320         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  2321         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  2322         if (fixed->hasError()) {
       
  2323             attributeContentError("fixed", "maxLength", value, BuiltinTypes::xsBoolean);
       
  2324             return facet;
       
  2325         }
       
  2326 
       
  2327         facet->setFixed(fixed->as<Boolean>()->value());
       
  2328     } else {
       
  2329         facet->setFixed(false); // the default value
       
  2330     }
       
  2331 
       
  2332     const QString value = readAttribute(QString::fromLatin1("value"));
       
  2333     DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
       
  2334     if (integer->hasError()) {
       
  2335         attributeContentError("value", "maxLength", value, BuiltinTypes::xsNonNegativeInteger);
       
  2336         return facet;
       
  2337     } else {
       
  2338         facet->setValue(integer);
       
  2339     }
       
  2340 
       
  2341     validateIdAttribute("maxLength");
       
  2342 
       
  2343     TagValidationHandler tagValidator(XsdTagScope::MaxLengthFacet, this, m_namePool);
       
  2344 
       
  2345     while (!atEnd()) {
       
  2346         readNext();
       
  2347 
       
  2348         if (isEndElement())
       
  2349             break;
       
  2350 
       
  2351         if (isStartElement()) {
       
  2352             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2353             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2354 
       
  2355             tagValidator.validate(token);
       
  2356 
       
  2357             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2358                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2359                 facet->addAnnotation(annotation);
       
  2360             } else {
       
  2361                 parseUnknown();
       
  2362             }
       
  2363         }
       
  2364     }
       
  2365 
       
  2366     tagValidator.finalize();
       
  2367 
       
  2368     return facet;
       
  2369 }
       
  2370 
       
  2371 XsdFacet::Ptr XsdSchemaParser::parseEnumerationFacet()
       
  2372 {
       
  2373     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Enumeration, this);
       
  2374 
       
  2375     validateElement(XsdTagScope::EnumerationFacet);
       
  2376 
       
  2377     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2378     facet->setType(XsdFacet::Enumeration);
       
  2379 
       
  2380     // parse attributes
       
  2381     facet->setFixed(false); // not defined in schema, but can't hurt
       
  2382 
       
  2383     const QString value = readAttribute(QString::fromLatin1("value"));
       
  2384 
       
  2385     // as enumeration can have a value of type anySimpleType, we just read
       
  2386     // the string here and store it for later intepretation
       
  2387     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
       
  2388     if (string->hasError()) {
       
  2389         attributeContentError("value", "enumeration", value);
       
  2390         return facet;
       
  2391     } else {
       
  2392         AtomicValue::List multiValue;
       
  2393         multiValue << string;
       
  2394         facet->setMultiValue(multiValue);
       
  2395     }
       
  2396     m_schemaResolver->addEnumerationFacetValue(string, m_namespaceSupport);
       
  2397 
       
  2398     validateIdAttribute("enumeration");
       
  2399 
       
  2400     TagValidationHandler tagValidator(XsdTagScope::EnumerationFacet, this, m_namePool);
       
  2401 
       
  2402     while (!atEnd()) {
       
  2403         readNext();
       
  2404 
       
  2405         if (isEndElement())
       
  2406             break;
       
  2407 
       
  2408         if (isStartElement()) {
       
  2409             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2410             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2411 
       
  2412             tagValidator.validate(token);
       
  2413 
       
  2414             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2415                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2416                 facet->addAnnotation(annotation);
       
  2417             } else {
       
  2418                 parseUnknown();
       
  2419             }
       
  2420         }
       
  2421     }
       
  2422 
       
  2423     tagValidator.finalize();
       
  2424 
       
  2425     return facet;
       
  2426 }
       
  2427 
       
  2428 XsdFacet::Ptr XsdSchemaParser::parseWhiteSpaceFacet()
       
  2429 {
       
  2430     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::WhiteSpace, this);
       
  2431 
       
  2432     validateElement(XsdTagScope::WhiteSpaceFacet);
       
  2433 
       
  2434     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2435     facet->setType(XsdFacet::WhiteSpace);
       
  2436 
       
  2437     // parse attributes
       
  2438     if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  2439         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  2440         const Boolean::Ptr fixed = Boolean::fromLexical(value);
       
  2441         if (fixed->hasError()) {
       
  2442             attributeContentError("fixed", "whiteSpace", value, BuiltinTypes::xsBoolean);
       
  2443             return facet;
       
  2444         }
       
  2445 
       
  2446         facet->setFixed(fixed->as<Boolean>()->value());
       
  2447     } else {
       
  2448         facet->setFixed(false); // the default value
       
  2449     }
       
  2450 
       
  2451     const QString value = readAttribute(QString::fromLatin1("value"));
       
  2452     if (value != XsdSchemaToken::toString(XsdSchemaToken::Collapse) &&
       
  2453         value != XsdSchemaToken::toString(XsdSchemaToken::Preserve) &&
       
  2454         value != XsdSchemaToken::toString(XsdSchemaToken::Replace)) {
       
  2455         attributeContentError("value", "whiteSpace", value);
       
  2456         return facet;
       
  2457     } else {
       
  2458         DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
       
  2459         if (string->hasError()) {
       
  2460             attributeContentError("value", "whiteSpace", value);
       
  2461             return facet;
       
  2462         } else {
       
  2463             facet->setValue(string);
       
  2464         }
       
  2465     }
       
  2466 
       
  2467     validateIdAttribute("whiteSpace");
       
  2468 
       
  2469     TagValidationHandler tagValidator(XsdTagScope::WhiteSpaceFacet, this, m_namePool);
       
  2470 
       
  2471     while (!atEnd()) {
       
  2472         readNext();
       
  2473 
       
  2474         if (isEndElement())
       
  2475             break;
       
  2476 
       
  2477         if (isStartElement()) {
       
  2478             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2479             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2480 
       
  2481             tagValidator.validate(token);
       
  2482 
       
  2483             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2484                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2485                 facet->addAnnotation(annotation);
       
  2486             } else {
       
  2487                 parseUnknown();
       
  2488             }
       
  2489         }
       
  2490     }
       
  2491 
       
  2492     tagValidator.finalize();
       
  2493 
       
  2494     return facet;
       
  2495 }
       
  2496 
       
  2497 XsdFacet::Ptr XsdSchemaParser::parsePatternFacet()
       
  2498 {
       
  2499     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Pattern, this);
       
  2500 
       
  2501     validateElement(XsdTagScope::PatternFacet);
       
  2502 
       
  2503     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2504     facet->setType(XsdFacet::Pattern);
       
  2505 
       
  2506     // parse attributes
       
  2507 
       
  2508     // as pattern can have a value of type anySimpleType, we just read
       
  2509     // the string here and store it for later intepretation
       
  2510     const QString value = readAttribute(QString::fromLatin1("value"));
       
  2511     DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
       
  2512     if (string->hasError()) {
       
  2513         attributeContentError("value", "pattern", value);
       
  2514         return facet;
       
  2515     } else {
       
  2516         AtomicValue::List multiValue;
       
  2517         multiValue << string;
       
  2518         facet->setMultiValue(multiValue);
       
  2519     }
       
  2520 
       
  2521     validateIdAttribute("pattern");
       
  2522 
       
  2523     TagValidationHandler tagValidator(XsdTagScope::PatternFacet, this, m_namePool);
       
  2524 
       
  2525     while (!atEnd()) {
       
  2526         readNext();
       
  2527 
       
  2528         if (isEndElement())
       
  2529             break;
       
  2530 
       
  2531         if (isStartElement()) {
       
  2532             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2533             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2534 
       
  2535             tagValidator.validate(token);
       
  2536 
       
  2537             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2538                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2539                 facet->addAnnotation(annotation);
       
  2540             } else {
       
  2541                 parseUnknown();
       
  2542             }
       
  2543         }
       
  2544     }
       
  2545 
       
  2546     tagValidator.finalize();
       
  2547 
       
  2548     return facet;
       
  2549 }
       
  2550 
       
  2551 XsdFacet::Ptr XsdSchemaParser::parseAssertionFacet()
       
  2552 {
       
  2553     // this is just a wrapper function around the parseAssertion() method
       
  2554 
       
  2555     const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assertion, XsdTagScope::Assertion);
       
  2556 
       
  2557     const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
       
  2558     facet->setType(XsdFacet::Assertion);
       
  2559     facet->setAssertions(XsdAssertion::List() << assertion);
       
  2560 
       
  2561     return facet;
       
  2562 }
       
  2563 
       
  2564 XsdComplexType::Ptr XsdSchemaParser::parseGlobalComplexType()
       
  2565 {
       
  2566     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this);
       
  2567 
       
  2568     validateElement(XsdTagScope::GlobalComplexType);
       
  2569 
       
  2570     bool hasTypeSpecified = false;
       
  2571     bool hasComplexContent = false;
       
  2572 
       
  2573     const XsdComplexType::Ptr complexType(new XsdComplexType());
       
  2574 
       
  2575     // parse attributes
       
  2576     if (hasAttribute(QString::fromLatin1("abstract"))) {
       
  2577         const QString abstract = readAttribute(QString::fromLatin1("abstract"));
       
  2578 
       
  2579         const Boolean::Ptr value = Boolean::fromLexical(abstract);
       
  2580         if (value->hasError()) {
       
  2581             attributeContentError("abstract", "complexType", abstract, BuiltinTypes::xsBoolean);
       
  2582             return complexType;
       
  2583         }
       
  2584 
       
  2585         complexType->setIsAbstract(value->as<Boolean>()->value());
       
  2586     } else {
       
  2587         complexType->setIsAbstract(false);  // default value
       
  2588     }
       
  2589 
       
  2590     complexType->setProhibitedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint, "complexType"));
       
  2591     complexType->setDerivationConstraints(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "complexType"));
       
  2592 
       
  2593     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("complexType"));
       
  2594     complexType->setName(objectName);
       
  2595 
       
  2596     bool effectiveMixed = false;
       
  2597     if (hasAttribute(QString::fromLatin1("mixed"))) {
       
  2598         const QString mixed = readAttribute(QString::fromLatin1("mixed"));
       
  2599 
       
  2600         const Boolean::Ptr value = Boolean::fromLexical(mixed);
       
  2601         if (value->hasError()) {
       
  2602             attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean);
       
  2603             return complexType;
       
  2604         }
       
  2605 
       
  2606         effectiveMixed = value->as<Boolean>()->value();
       
  2607     }
       
  2608 
       
  2609     validateIdAttribute("complexType");
       
  2610 
       
  2611     TagValidationHandler tagValidator(XsdTagScope::GlobalComplexType, this, m_namePool);
       
  2612 
       
  2613     while (!atEnd()) {
       
  2614         readNext();
       
  2615 
       
  2616         if (isEndElement())
       
  2617             break;
       
  2618 
       
  2619         if (isStartElement()) {
       
  2620             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2621             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2622 
       
  2623             tagValidator.validate(token);
       
  2624 
       
  2625             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2626                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2627                 complexType->addAnnotation(annotation);
       
  2628             } else if (isSchemaTag(XsdSchemaToken::SimpleContent, token, namespaceToken)) {
       
  2629                 if (effectiveMixed) {
       
  2630                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  2631                                             .arg(formatElement("complexType"))
       
  2632                                             .arg(formatElement("simpleContent"))
       
  2633                                             .arg(formatAttribute("mixed")));
       
  2634                     return complexType;
       
  2635                 }
       
  2636 
       
  2637                 parseSimpleContent(complexType);
       
  2638                 hasTypeSpecified = true;
       
  2639             } else if (isSchemaTag(XsdSchemaToken::ComplexContent, token, namespaceToken)) {
       
  2640                 bool mixed;
       
  2641                 parseComplexContent(complexType, &mixed);
       
  2642                 hasTypeSpecified = true;
       
  2643 
       
  2644                 effectiveMixed = (effectiveMixed || mixed);
       
  2645                 hasComplexContent = true;
       
  2646             } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
       
  2647                 const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
       
  2648                 complexType->contentType()->setOpenContent(openContent);
       
  2649                 hasComplexContent = true;
       
  2650             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
       
  2651                 const XsdParticle::Ptr particle(new XsdParticle());
       
  2652                 const XsdTerm::Ptr term = parseReferredGroup(particle);
       
  2653                 particle->setTerm(term);
       
  2654                 complexType->contentType()->setParticle(particle);
       
  2655 
       
  2656                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2657                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2658                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2659                 hasComplexContent = true;
       
  2660             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
       
  2661                 const XsdParticle::Ptr particle(new XsdParticle());
       
  2662                 const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
       
  2663                 particle->setTerm(term);
       
  2664                 complexType->contentType()->setParticle(particle);
       
  2665 
       
  2666                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2667                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2668                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2669                 hasComplexContent = true;
       
  2670             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
       
  2671                 const XsdParticle::Ptr particle(new XsdParticle());
       
  2672                 const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
       
  2673                 particle->setTerm(term);
       
  2674                 complexType->contentType()->setParticle(particle);
       
  2675 
       
  2676                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2677                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2678                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2679                 hasComplexContent = true;
       
  2680             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
       
  2681                 const XsdParticle::Ptr particle(new XsdParticle());
       
  2682                 const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
       
  2683                 particle->setTerm(term);
       
  2684                 complexType->contentType()->setParticle(particle);
       
  2685 
       
  2686                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2687                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2688                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2689                 hasComplexContent = true;
       
  2690             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
       
  2691                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
       
  2692                 complexType->addAttributeUse(attributeUse);
       
  2693 
       
  2694                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2695                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2696                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2697                 hasComplexContent = true;
       
  2698             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
       
  2699                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
       
  2700                 complexType->addAttributeUse(attributeUse);
       
  2701 
       
  2702                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2703                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2704                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2705                 hasComplexContent = true;
       
  2706             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
       
  2707                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
       
  2708                 complexType->setAttributeWildcard(wildcard);
       
  2709 
       
  2710                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2711                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2712                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2713                 hasComplexContent = true;
       
  2714             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
       
  2715                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
       
  2716                 complexType->addAssertion(assertion);
       
  2717             } else {
       
  2718                 parseUnknown();
       
  2719             }
       
  2720         }
       
  2721     }
       
  2722 
       
  2723     tagValidator.finalize();
       
  2724 
       
  2725     if (!hasTypeSpecified) {
       
  2726         complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2727         complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2728         hasComplexContent = true;
       
  2729     }
       
  2730 
       
  2731     if (hasComplexContent == true) {
       
  2732         resolveComplexContentType(complexType, effectiveMixed);
       
  2733     }
       
  2734 
       
  2735     return complexType;
       
  2736 }
       
  2737 
       
  2738 XsdComplexType::Ptr XsdSchemaParser::parseLocalComplexType()
       
  2739 {
       
  2740     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this);
       
  2741 
       
  2742     validateElement(XsdTagScope::LocalComplexType);
       
  2743 
       
  2744     bool hasTypeSpecified = false;
       
  2745     bool hasComplexContent = true;
       
  2746 
       
  2747     const XsdComplexType::Ptr complexType(new XsdComplexType());
       
  2748     complexType->setName(m_parserContext->createAnonymousName(m_targetNamespace));
       
  2749 
       
  2750     // parse attributes
       
  2751     bool effectiveMixed = false;
       
  2752     if (hasAttribute(QString::fromLatin1("mixed"))) {
       
  2753         const QString mixed = readAttribute(QString::fromLatin1("mixed"));
       
  2754 
       
  2755         const Boolean::Ptr value = Boolean::fromLexical(mixed);
       
  2756         if (value->hasError()) {
       
  2757             attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean);
       
  2758             return complexType;
       
  2759         }
       
  2760 
       
  2761         effectiveMixed = value->as<Boolean>()->value();
       
  2762     }
       
  2763 
       
  2764     validateIdAttribute("complexType");
       
  2765 
       
  2766     TagValidationHandler tagValidator(XsdTagScope::LocalComplexType, this, m_namePool);
       
  2767 
       
  2768     while (!atEnd()) {
       
  2769         readNext();
       
  2770 
       
  2771         if (isEndElement())
       
  2772             break;
       
  2773 
       
  2774         if (isStartElement()) {
       
  2775             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2776             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2777 
       
  2778             tagValidator.validate(token);
       
  2779 
       
  2780             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2781                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2782                 complexType->addAnnotation(annotation);
       
  2783             } else if (isSchemaTag(XsdSchemaToken::SimpleContent, token, namespaceToken)) {
       
  2784                 parseSimpleContent(complexType);
       
  2785                 hasTypeSpecified = true;
       
  2786             } else if (isSchemaTag(XsdSchemaToken::ComplexContent, token, namespaceToken)) {
       
  2787                 bool mixed;
       
  2788                 parseComplexContent(complexType, &mixed);
       
  2789                 hasTypeSpecified = true;
       
  2790 
       
  2791                 effectiveMixed = (effectiveMixed || mixed);
       
  2792                 hasComplexContent = true;
       
  2793             } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
       
  2794                 const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
       
  2795                 complexType->contentType()->setOpenContent(openContent);
       
  2796                 hasComplexContent = true;
       
  2797             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
       
  2798                 const XsdParticle::Ptr particle(new XsdParticle());
       
  2799                 const XsdTerm::Ptr term = parseReferredGroup(particle);
       
  2800                 particle->setTerm(term);
       
  2801                 complexType->contentType()->setParticle(particle);
       
  2802 
       
  2803                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2804                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2805                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2806                 hasComplexContent = true;
       
  2807             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
       
  2808                 const XsdParticle::Ptr particle(new XsdParticle());
       
  2809                 const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
       
  2810                 particle->setTerm(term);
       
  2811                 complexType->contentType()->setParticle(particle);
       
  2812 
       
  2813                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2814                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2815                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2816                 hasComplexContent = true;
       
  2817             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
       
  2818                 const XsdParticle::Ptr particle(new XsdParticle());
       
  2819                 const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
       
  2820                 particle->setTerm(term);
       
  2821                 complexType->contentType()->setParticle(particle);
       
  2822 
       
  2823                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2824                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2825                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2826                 hasComplexContent = true;
       
  2827             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
       
  2828                 const XsdParticle::Ptr particle(new XsdParticle());
       
  2829                 const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
       
  2830                 particle->setTerm(term);
       
  2831                 complexType->contentType()->setParticle(particle);
       
  2832 
       
  2833                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2834                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2835                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2836                 hasComplexContent = true;
       
  2837             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
       
  2838                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
       
  2839                 complexType->addAttributeUse(attributeUse);
       
  2840 
       
  2841                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2842                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2843                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2844                 hasComplexContent = true;
       
  2845             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
       
  2846                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
       
  2847                 complexType->addAttributeUse(attributeUse);
       
  2848 
       
  2849                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2850                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2851                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2852                 hasComplexContent = true;
       
  2853             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
       
  2854                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
       
  2855                 complexType->setAttributeWildcard(wildcard);
       
  2856 
       
  2857                 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2858                 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  2859                 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2860                 hasComplexContent = true;
       
  2861             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
       
  2862                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
       
  2863                 complexType->addAssertion(assertion);
       
  2864             } else {
       
  2865                 parseUnknown();
       
  2866             }
       
  2867         }
       
  2868     }
       
  2869 
       
  2870     tagValidator.finalize();
       
  2871 
       
  2872     if (!hasTypeSpecified) {
       
  2873         complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
       
  2874         complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2875         hasComplexContent = true;
       
  2876     }
       
  2877 
       
  2878     if (hasComplexContent == true) {
       
  2879         resolveComplexContentType(complexType, effectiveMixed);
       
  2880     }
       
  2881 
       
  2882     return complexType;
       
  2883 }
       
  2884 
       
  2885 void XsdSchemaParser::resolveComplexContentType(const XsdComplexType::Ptr &complexType, bool effectiveMixed)
       
  2886 {
       
  2887     // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctcc.common
       
  2888 
       
  2889     // 1
       
  2890     // the effectiveMixed contains the effective mixed value
       
  2891 
       
  2892     // 2
       
  2893     bool hasEmptyContent = false;
       
  2894     if (!complexType->contentType()->particle()) {
       
  2895         hasEmptyContent = true; // 2.1.1
       
  2896     } else {
       
  2897         if (complexType->contentType()->particle()->term()->isModelGroup()) {
       
  2898             const XsdModelGroup::Ptr group = complexType->contentType()->particle()->term();
       
  2899             if (group->compositor() == XsdModelGroup::SequenceCompositor || group->compositor() == XsdModelGroup::AllCompositor) {
       
  2900                 if (group->particles().isEmpty())
       
  2901                     hasEmptyContent = true; // 2.1.2
       
  2902             } else if (group->compositor() == XsdModelGroup::ChoiceCompositor) {
       
  2903                 if ((complexType->contentType()->particle()->minimumOccurs() == 0) && group->particles().isEmpty())
       
  2904                     hasEmptyContent = true; // 2.1.3
       
  2905             }
       
  2906 
       
  2907             if ((complexType->contentType()->particle()->maximumOccursUnbounded() == false) && (complexType->contentType()->particle()->maximumOccurs() == 0))
       
  2908                 hasEmptyContent = true; // 2.1.4
       
  2909         }
       
  2910     }
       
  2911 
       
  2912     const XsdParticle::Ptr explicitContent = (hasEmptyContent ? XsdParticle::Ptr() : complexType->contentType()->particle());
       
  2913 
       
  2914     // do all the other work (3, 4, 5 and 6) in the resolver, as they need access to the base type object
       
  2915     m_schemaResolver->addComplexContentType(complexType, explicitContent, effectiveMixed);
       
  2916 }
       
  2917 
       
  2918 void XsdSchemaParser::parseSimpleContent(const XsdComplexType::Ptr &complexType)
       
  2919 {
       
  2920     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleContent, this);
       
  2921 
       
  2922     validateElement(XsdTagScope::SimpleContent);
       
  2923 
       
  2924     complexType->contentType()->setVariety(XsdComplexType::ContentType::Simple);
       
  2925 
       
  2926     // parse attributes
       
  2927     validateIdAttribute("simpleContent");
       
  2928 
       
  2929     TagValidationHandler tagValidator(XsdTagScope::SimpleContent, this, m_namePool);
       
  2930 
       
  2931     while (!atEnd()) {
       
  2932         readNext();
       
  2933 
       
  2934         if (isEndElement())
       
  2935             break;
       
  2936 
       
  2937         if (isStartElement()) {
       
  2938             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2939             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2940 
       
  2941             tagValidator.validate(token);
       
  2942 
       
  2943             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2944                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2945                 complexType->addAnnotation(annotation);
       
  2946             } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
       
  2947                 parseSimpleContentRestriction(complexType);
       
  2948             } else if (isSchemaTag(XsdSchemaToken::Extension, token, namespaceToken)) {
       
  2949                 parseSimpleContentExtension(complexType);
       
  2950             } else {
       
  2951                 parseUnknown();
       
  2952             }
       
  2953         }
       
  2954     }
       
  2955 
       
  2956     tagValidator.finalize();
       
  2957 }
       
  2958 
       
  2959 void XsdSchemaParser::parseSimpleContentRestriction(const XsdComplexType::Ptr &complexType)
       
  2960 {
       
  2961     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
       
  2962 
       
  2963     validateElement(XsdTagScope::SimpleContentRestriction);
       
  2964 
       
  2965     complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  2966 
       
  2967     // parse attributes
       
  2968     const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "restriction");
       
  2969     QXmlName typeName;
       
  2970     convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  2971 
       
  2972     validateIdAttribute("restriction");
       
  2973 
       
  2974     XsdFacet::Hash facets;
       
  2975     QList<XsdFacet::Ptr> patternFacets;
       
  2976     QList<XsdFacet::Ptr> enumerationFacets;
       
  2977     QList<XsdFacet::Ptr> assertionFacets;
       
  2978 
       
  2979     TagValidationHandler tagValidator(XsdTagScope::SimpleContentRestriction, this, m_namePool);
       
  2980 
       
  2981     while (!atEnd()) {
       
  2982         readNext();
       
  2983 
       
  2984         if (isEndElement())
       
  2985             break;
       
  2986 
       
  2987         if (isStartElement()) {
       
  2988             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  2989             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  2990 
       
  2991             tagValidator.validate(token);
       
  2992 
       
  2993             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  2994                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  2995                 complexType->addAnnotation(annotation);
       
  2996             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
       
  2997                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
       
  2998                 type->setContext(complexType); //TODO: investigate what the schema spec really wants here?!?
       
  2999                 complexType->contentType()->setSimpleType(type);
       
  3000 
       
  3001                 // add it to list of anonymous types as well
       
  3002                 addAnonymousType(type);
       
  3003             } else if (isSchemaTag(XsdSchemaToken::MinExclusive, token, namespaceToken)) {
       
  3004                 const XsdFacet::Ptr facet = parseMinExclusiveFacet();
       
  3005                 addFacet(facet, facets, complexType);
       
  3006             } else if (isSchemaTag(XsdSchemaToken::MinInclusive, token, namespaceToken)) {
       
  3007                 const XsdFacet::Ptr facet = parseMinInclusiveFacet();
       
  3008                 addFacet(facet, facets, complexType);
       
  3009             } else if (isSchemaTag(XsdSchemaToken::MaxExclusive, token, namespaceToken)) {
       
  3010                 const XsdFacet::Ptr facet = parseMaxExclusiveFacet();
       
  3011                 addFacet(facet, facets, complexType);
       
  3012             } else if (isSchemaTag(XsdSchemaToken::MaxInclusive, token, namespaceToken)) {
       
  3013                 const XsdFacet::Ptr facet = parseMaxInclusiveFacet();
       
  3014                 addFacet(facet, facets, complexType);
       
  3015             } else if (isSchemaTag(XsdSchemaToken::TotalDigits, token, namespaceToken)) {
       
  3016                 const XsdFacet::Ptr facet = parseTotalDigitsFacet();
       
  3017                 addFacet(facet, facets, complexType);
       
  3018             } else if (isSchemaTag(XsdSchemaToken::FractionDigits, token, namespaceToken)) {
       
  3019                 const XsdFacet::Ptr facet = parseFractionDigitsFacet();
       
  3020                 addFacet(facet, facets, complexType);
       
  3021             } else if (isSchemaTag(XsdSchemaToken::Length, token, namespaceToken)) {
       
  3022                 const XsdFacet::Ptr facet = parseLengthFacet();
       
  3023                 addFacet(facet, facets, complexType);
       
  3024             } else if (isSchemaTag(XsdSchemaToken::MinLength, token, namespaceToken)) {
       
  3025                 const XsdFacet::Ptr facet = parseMinLengthFacet();
       
  3026                 addFacet(facet, facets, complexType);
       
  3027             } else if (isSchemaTag(XsdSchemaToken::MaxLength, token, namespaceToken)) {
       
  3028                 const XsdFacet::Ptr facet = parseMaxLengthFacet();
       
  3029                 addFacet(facet, facets, complexType);
       
  3030             } else if (isSchemaTag(XsdSchemaToken::Enumeration, token, namespaceToken)) {
       
  3031                 const XsdFacet::Ptr facet = parseEnumerationFacet();
       
  3032                 enumerationFacets.append(facet);
       
  3033             } else if (isSchemaTag(XsdSchemaToken::WhiteSpace, token, namespaceToken)) {
       
  3034                 const XsdFacet::Ptr facet = parseWhiteSpaceFacet();
       
  3035                 addFacet(facet, facets, complexType);
       
  3036             } else if (isSchemaTag(XsdSchemaToken::Pattern, token, namespaceToken)) {
       
  3037                 const XsdFacet::Ptr facet = parsePatternFacet();
       
  3038                 patternFacets.append(facet);
       
  3039             } else if (isSchemaTag(XsdSchemaToken::Assertion, token, namespaceToken)) {
       
  3040                 const XsdFacet::Ptr facet = parseAssertionFacet();
       
  3041                 assertionFacets.append(facet);
       
  3042             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
       
  3043                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
       
  3044                 complexType->addAttributeUse(attributeUse);
       
  3045             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
       
  3046                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
       
  3047                 complexType->addAttributeUse(attributeUse);
       
  3048             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
       
  3049                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
       
  3050                 complexType->setAttributeWildcard(wildcard);
       
  3051             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
       
  3052                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
       
  3053                 complexType->addAssertion(assertion);
       
  3054             } else {
       
  3055                 parseUnknown();
       
  3056             }
       
  3057         }
       
  3058     }
       
  3059 
       
  3060     tagValidator.finalize();
       
  3061 
       
  3062     // merge all pattern facets into one multi value facet
       
  3063     if (!patternFacets.isEmpty()) {
       
  3064         const XsdFacet::Ptr patternFacet(new XsdFacet());
       
  3065         patternFacet->setType(XsdFacet::Pattern);
       
  3066 
       
  3067         AtomicValue::List multiValue;
       
  3068         for (int i = 0; i < patternFacets.count(); ++i)
       
  3069             multiValue << patternFacets.at(i)->multiValue();
       
  3070 
       
  3071         patternFacet->setMultiValue(multiValue);
       
  3072         addFacet(patternFacet, facets, complexType);
       
  3073     }
       
  3074 
       
  3075     // merge all enumeration facets into one multi value facet
       
  3076     if (!enumerationFacets.isEmpty()) {
       
  3077         const XsdFacet::Ptr enumerationFacet(new XsdFacet());
       
  3078         enumerationFacet->setType(XsdFacet::Enumeration);
       
  3079 
       
  3080         AtomicValue::List multiValue;
       
  3081         for (int i = 0; i < enumerationFacets.count(); ++i)
       
  3082             multiValue << enumerationFacets.at(i)->multiValue();
       
  3083 
       
  3084         enumerationFacet->setMultiValue(multiValue);
       
  3085         addFacet(enumerationFacet, facets, complexType);
       
  3086     }
       
  3087 
       
  3088     // merge all assertion facets into one facet
       
  3089     if (!assertionFacets.isEmpty()) {
       
  3090         const XsdFacet::Ptr assertionFacet(new XsdFacet());
       
  3091         assertionFacet->setType(XsdFacet::Assertion);
       
  3092 
       
  3093         XsdAssertion::List assertions;
       
  3094         for (int i = 0; i < assertionFacets.count(); ++i)
       
  3095             assertions << assertionFacets.at(i)->assertions();
       
  3096 
       
  3097         assertionFacet->setAssertions(assertions);
       
  3098         addFacet(assertionFacet, facets, complexType);
       
  3099     }
       
  3100 
       
  3101     m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation(), facets); // add to resolver
       
  3102 }
       
  3103 
       
  3104 void XsdSchemaParser::parseSimpleContentExtension(const XsdComplexType::Ptr &complexType)
       
  3105 {
       
  3106     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this);
       
  3107 
       
  3108     validateElement(XsdTagScope::SimpleContentExtension);
       
  3109 
       
  3110     complexType->setDerivationMethod(XsdComplexType::DerivationExtension);
       
  3111 
       
  3112     // parse attributes
       
  3113     const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "extension");
       
  3114     QXmlName typeName;
       
  3115     convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  3116     m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver
       
  3117 
       
  3118     validateIdAttribute("extension");
       
  3119 
       
  3120     TagValidationHandler tagValidator(XsdTagScope::SimpleContentExtension, this, m_namePool);
       
  3121 
       
  3122     while (!atEnd()) {
       
  3123         readNext();
       
  3124 
       
  3125         if (isEndElement())
       
  3126             break;
       
  3127 
       
  3128         if (isStartElement()) {
       
  3129             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3130             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3131 
       
  3132             tagValidator.validate(token);
       
  3133 
       
  3134             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3135                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3136                 complexType->addAnnotation(annotation);
       
  3137             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
       
  3138                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
       
  3139                 complexType->addAttributeUse(attributeUse);
       
  3140             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
       
  3141                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
       
  3142                 complexType->addAttributeUse(attributeUse);
       
  3143             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
       
  3144                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
       
  3145                 complexType->setAttributeWildcard(wildcard);
       
  3146             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
       
  3147                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
       
  3148                 complexType->addAssertion(assertion);
       
  3149             } else {
       
  3150                 parseUnknown();
       
  3151             }
       
  3152         }
       
  3153     }
       
  3154 
       
  3155     tagValidator.finalize();
       
  3156 }
       
  3157 
       
  3158 void XsdSchemaParser::parseComplexContent(const XsdComplexType::Ptr &complexType, bool *mixed)
       
  3159 {
       
  3160     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexContent, this);
       
  3161 
       
  3162     validateElement(XsdTagScope::ComplexContent);
       
  3163 
       
  3164     complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
       
  3165 
       
  3166     // parse attributes
       
  3167     if (hasAttribute(QString::fromLatin1("mixed"))) {
       
  3168         const QString mixedStr = readAttribute(QString::fromLatin1("mixed"));
       
  3169 
       
  3170         const Boolean::Ptr value = Boolean::fromLexical(mixedStr);
       
  3171         if (value->hasError()) {
       
  3172             attributeContentError("mixed", "complexType", mixedStr, BuiltinTypes::xsBoolean);
       
  3173             return;
       
  3174         }
       
  3175 
       
  3176         *mixed = value->as<Boolean>()->value();
       
  3177     } else {
       
  3178         *mixed = false;
       
  3179     }
       
  3180 
       
  3181     validateIdAttribute("complexContent");
       
  3182 
       
  3183     TagValidationHandler tagValidator(XsdTagScope::ComplexContent, this, m_namePool);
       
  3184 
       
  3185     while (!atEnd()) {
       
  3186         readNext();
       
  3187 
       
  3188         if (isEndElement())
       
  3189             break;
       
  3190 
       
  3191         if (isStartElement()) {
       
  3192             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3193             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3194 
       
  3195             tagValidator.validate(token);
       
  3196 
       
  3197             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3198                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3199                 complexType->addAnnotation(annotation);
       
  3200             } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
       
  3201                 parseComplexContentRestriction(complexType);
       
  3202             } else if (isSchemaTag(XsdSchemaToken::Extension, token, namespaceToken)) {
       
  3203                 parseComplexContentExtension(complexType);
       
  3204             } else {
       
  3205                 parseUnknown();
       
  3206             }
       
  3207         }
       
  3208     }
       
  3209 
       
  3210     tagValidator.finalize();
       
  3211 }
       
  3212 
       
  3213 void XsdSchemaParser::parseComplexContentRestriction(const XsdComplexType::Ptr &complexType)
       
  3214 {
       
  3215     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
       
  3216 
       
  3217     validateElement(XsdTagScope::ComplexContentRestriction);
       
  3218 
       
  3219     complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
       
  3220 
       
  3221     // parse attributes
       
  3222     const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "restriction");
       
  3223     QXmlName typeName;
       
  3224     convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  3225     m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver
       
  3226 
       
  3227     validateIdAttribute("restriction");
       
  3228 
       
  3229     TagValidationHandler tagValidator(XsdTagScope::ComplexContentRestriction, this, m_namePool);
       
  3230 
       
  3231     bool hasContent = false;
       
  3232     while (!atEnd()) {
       
  3233         readNext();
       
  3234 
       
  3235         if (isEndElement())
       
  3236             break;
       
  3237 
       
  3238         if (isStartElement()) {
       
  3239             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3240             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3241 
       
  3242             tagValidator.validate(token);
       
  3243 
       
  3244             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3245                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3246                 complexType->addAnnotation(annotation);
       
  3247             } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
       
  3248                 const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
       
  3249                 complexType->contentType()->setOpenContent(openContent);
       
  3250                 hasContent = true;
       
  3251             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
       
  3252                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3253                 const XsdTerm::Ptr term = parseReferredGroup(particle);
       
  3254                 particle->setTerm(term);
       
  3255                 complexType->contentType()->setParticle(particle);
       
  3256                 hasContent = true;
       
  3257             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
       
  3258                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3259                 const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
       
  3260                 particle->setTerm(term);
       
  3261                 complexType->contentType()->setParticle(particle);
       
  3262                 hasContent = true;
       
  3263             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
       
  3264                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3265                 const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
       
  3266                 particle->setTerm(term);
       
  3267                 complexType->contentType()->setParticle(particle);
       
  3268                 hasContent = true;
       
  3269             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
       
  3270                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3271                 const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
       
  3272                 particle->setTerm(term);
       
  3273                 complexType->contentType()->setParticle(particle);
       
  3274                 hasContent = true;
       
  3275             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
       
  3276                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
       
  3277                 complexType->addAttributeUse(attributeUse);
       
  3278             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
       
  3279                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
       
  3280                 complexType->addAttributeUse(attributeUse);
       
  3281             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
       
  3282                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
       
  3283                 complexType->setAttributeWildcard(wildcard);
       
  3284             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
       
  3285                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
       
  3286                 complexType->addAssertion(assertion);
       
  3287             } else {
       
  3288                 parseUnknown();
       
  3289             }
       
  3290         }
       
  3291     }
       
  3292 
       
  3293     if (!hasContent)
       
  3294         complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty);
       
  3295 
       
  3296     tagValidator.finalize();
       
  3297 }
       
  3298 
       
  3299 void XsdSchemaParser::parseComplexContentExtension(const XsdComplexType::Ptr &complexType)
       
  3300 {
       
  3301     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this);
       
  3302 
       
  3303     validateElement(XsdTagScope::ComplexContentExtension);
       
  3304 
       
  3305     complexType->setDerivationMethod(XsdComplexType::DerivationExtension);
       
  3306 
       
  3307     // parse attributes
       
  3308     const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "extension");
       
  3309     QXmlName typeName;
       
  3310     convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  3311     m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver
       
  3312 
       
  3313     validateIdAttribute("extension");
       
  3314 
       
  3315     TagValidationHandler tagValidator(XsdTagScope::ComplexContentExtension, this, m_namePool);
       
  3316 
       
  3317     bool hasContent = false;
       
  3318     while (!atEnd()) {
       
  3319         readNext();
       
  3320 
       
  3321         if (isEndElement())
       
  3322             break;
       
  3323 
       
  3324         if (isStartElement()) {
       
  3325             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3326             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3327 
       
  3328             tagValidator.validate(token);
       
  3329 
       
  3330             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3331                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3332                 complexType->addAnnotation(annotation);
       
  3333             } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
       
  3334                 const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
       
  3335                 complexType->contentType()->setOpenContent(openContent);
       
  3336                 hasContent = true;
       
  3337             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
       
  3338                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3339                 const XsdTerm::Ptr term = parseReferredGroup(particle);
       
  3340                 particle->setTerm(term);
       
  3341                 complexType->contentType()->setParticle(particle);
       
  3342                 hasContent = true;
       
  3343             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
       
  3344                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3345                 const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
       
  3346                 particle->setTerm(term);
       
  3347                 complexType->contentType()->setParticle(particle);
       
  3348                 hasContent = true;
       
  3349             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
       
  3350                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3351                 const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
       
  3352                 particle->setTerm(term);
       
  3353                 complexType->contentType()->setParticle(particle);
       
  3354                 hasContent = true;
       
  3355             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
       
  3356                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3357                 const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
       
  3358                 particle->setTerm(term);
       
  3359                 complexType->contentType()->setParticle(particle);
       
  3360                 hasContent = true;
       
  3361             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
       
  3362                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
       
  3363                 complexType->addAttributeUse(attributeUse);
       
  3364             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
       
  3365                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
       
  3366                 complexType->addAttributeUse(attributeUse);
       
  3367             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
       
  3368                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
       
  3369                 complexType->setAttributeWildcard(wildcard);
       
  3370             } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
       
  3371                 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
       
  3372                 complexType->addAssertion(assertion);
       
  3373             } else {
       
  3374                 parseUnknown();
       
  3375             }
       
  3376         }
       
  3377     }
       
  3378 
       
  3379     if (!hasContent)
       
  3380         complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty);
       
  3381 
       
  3382     tagValidator.finalize();
       
  3383 }
       
  3384 
       
  3385 
       
  3386 XsdAssertion::Ptr XsdSchemaParser::parseAssertion(const XsdSchemaToken::NodeName &nodeName, const XsdTagScope::Type &tag)
       
  3387 {
       
  3388     const ElementNamespaceHandler namespaceHandler(nodeName, this);
       
  3389 
       
  3390     validateElement(tag);
       
  3391 
       
  3392     const XsdAssertion::Ptr assertion(new XsdAssertion());
       
  3393 
       
  3394     // parse attributes
       
  3395 
       
  3396     const XsdXPathExpression::Ptr expression = readXPathExpression("assertion");
       
  3397     assertion->setTest(expression);
       
  3398 
       
  3399     const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "assertion");
       
  3400     expression->setExpression(test);
       
  3401 
       
  3402     validateIdAttribute("assertion");
       
  3403 
       
  3404     TagValidationHandler tagValidator(tag, this, m_namePool);
       
  3405 
       
  3406     while (!atEnd()) {
       
  3407         readNext();
       
  3408 
       
  3409         if (isEndElement())
       
  3410             break;
       
  3411 
       
  3412         if (isStartElement()) {
       
  3413             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3414             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3415 
       
  3416             tagValidator.validate(token);
       
  3417 
       
  3418             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3419                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3420                 assertion->addAnnotation(annotation);
       
  3421             } else {
       
  3422                 parseUnknown();
       
  3423             }
       
  3424         }
       
  3425     }
       
  3426 
       
  3427     tagValidator.finalize();
       
  3428 
       
  3429     return assertion;
       
  3430 }
       
  3431 
       
  3432 XsdComplexType::OpenContent::Ptr XsdSchemaParser::parseOpenContent()
       
  3433 {
       
  3434     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::OpenContent, this);
       
  3435 
       
  3436     validateElement(XsdTagScope::OpenContent);
       
  3437 
       
  3438     const XsdComplexType::OpenContent::Ptr openContent(new XsdComplexType::OpenContent());
       
  3439 
       
  3440     if (hasAttribute(QString::fromLatin1("mode"))) {
       
  3441         const QString mode = readAttribute(QString::fromLatin1("mode"));
       
  3442 
       
  3443         if (mode == QString::fromLatin1("none")) {
       
  3444             m_defaultOpenContent->setMode(XsdComplexType::OpenContent::None);
       
  3445         } else if (mode == QString::fromLatin1("interleave")) {
       
  3446             m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave);
       
  3447         } else if (mode == QString::fromLatin1("suffix")) {
       
  3448             m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Suffix);
       
  3449         } else {
       
  3450             attributeContentError("mode", "openContent", mode);
       
  3451             return openContent;
       
  3452         }
       
  3453     } else {
       
  3454         openContent->setMode(XsdComplexType::OpenContent::Interleave);
       
  3455     }
       
  3456 
       
  3457     validateIdAttribute("openContent");
       
  3458 
       
  3459     TagValidationHandler tagValidator(XsdTagScope::OpenContent, this, m_namePool);
       
  3460 
       
  3461     while (!atEnd()) {
       
  3462         readNext();
       
  3463 
       
  3464         if (isEndElement())
       
  3465             break;
       
  3466 
       
  3467         if (isStartElement()) {
       
  3468             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3469             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3470 
       
  3471             tagValidator.validate(token);
       
  3472 
       
  3473             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3474                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3475                 openContent->addAnnotation(annotation);
       
  3476             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
       
  3477                 const XsdParticle::Ptr particle;
       
  3478                 const XsdWildcard::Ptr wildcard = parseAny(particle);
       
  3479                 openContent->setWildcard(wildcard);
       
  3480             } else {
       
  3481                 parseUnknown();
       
  3482             }
       
  3483         }
       
  3484     }
       
  3485 
       
  3486     tagValidator.finalize();
       
  3487 
       
  3488     return openContent;
       
  3489 }
       
  3490 
       
  3491 XsdModelGroup::Ptr XsdSchemaParser::parseNamedGroup()
       
  3492 {
       
  3493     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this);
       
  3494 
       
  3495     validateElement(XsdTagScope::NamedGroup);
       
  3496 
       
  3497     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
       
  3498     XsdModelGroup::Ptr group;
       
  3499 
       
  3500     QXmlName objectName;
       
  3501     if (hasAttribute(QString::fromLatin1("name"))) {
       
  3502         objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("group"));
       
  3503     }
       
  3504 
       
  3505     validateIdAttribute("group");
       
  3506 
       
  3507     TagValidationHandler tagValidator(XsdTagScope::NamedGroup, this, m_namePool);
       
  3508 
       
  3509     XsdAnnotation::Ptr annotation;
       
  3510 
       
  3511     while (!atEnd()) {
       
  3512         readNext();
       
  3513 
       
  3514         if (isEndElement())
       
  3515             break;
       
  3516 
       
  3517         if (isStartElement()) {
       
  3518             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3519             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3520 
       
  3521             tagValidator.validate(token);
       
  3522 
       
  3523             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3524                 annotation = parseAnnotation();
       
  3525             } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
       
  3526                 group = parseAll(modelGroup);
       
  3527             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
       
  3528                 group = parseChoice(modelGroup);
       
  3529             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
       
  3530                 group = parseSequence(modelGroup);
       
  3531             } else {
       
  3532                 parseUnknown();
       
  3533             }
       
  3534         }
       
  3535     }
       
  3536 
       
  3537     tagValidator.finalize();
       
  3538 
       
  3539     group->setName(objectName);
       
  3540 
       
  3541     if (annotation)
       
  3542         group->addAnnotation(annotation);
       
  3543 
       
  3544     return group;
       
  3545 }
       
  3546 
       
  3547 XsdTerm::Ptr XsdSchemaParser::parseReferredGroup(const XsdParticle::Ptr &particle)
       
  3548 {
       
  3549     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this);
       
  3550 
       
  3551     validateElement(XsdTagScope::ReferredGroup);
       
  3552 
       
  3553     const XsdReference::Ptr reference(new XsdReference());
       
  3554     reference->setType(XsdReference::ModelGroup);
       
  3555     reference->setSourceLocation(currentSourceLocation());
       
  3556 
       
  3557     // parse attributes
       
  3558     if (!parseMinMaxConstraint(particle, "group")) {
       
  3559         return reference;
       
  3560     }
       
  3561 
       
  3562     const QString value = readQNameAttribute(QString::fromLatin1("ref"), "group");
       
  3563     QXmlName referenceName;
       
  3564     convertName(value, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
       
  3565     reference->setReferenceName(referenceName);
       
  3566 
       
  3567     validateIdAttribute("group");
       
  3568 
       
  3569     TagValidationHandler tagValidator(XsdTagScope::ReferredGroup, this, m_namePool);
       
  3570 
       
  3571     while (!atEnd()) {
       
  3572         readNext();
       
  3573 
       
  3574         if (isEndElement())
       
  3575             break;
       
  3576 
       
  3577         if (isStartElement()) {
       
  3578             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3579             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3580 
       
  3581             tagValidator.validate(token);
       
  3582 
       
  3583             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3584                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3585                 reference->addAnnotation(annotation);
       
  3586             } else {
       
  3587                 parseUnknown();
       
  3588             }
       
  3589         }
       
  3590     }
       
  3591 
       
  3592     tagValidator.finalize();
       
  3593 
       
  3594     return reference;
       
  3595 }
       
  3596 
       
  3597 XsdModelGroup::Ptr XsdSchemaParser::parseAll(const NamedSchemaComponent::Ptr &parent)
       
  3598 {
       
  3599     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this);
       
  3600 
       
  3601     validateElement(XsdTagScope::All);
       
  3602 
       
  3603     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
       
  3604     modelGroup->setCompositor(XsdModelGroup::AllCompositor);
       
  3605 
       
  3606     validateIdAttribute("all");
       
  3607 
       
  3608     TagValidationHandler tagValidator(XsdTagScope::All, this, m_namePool);
       
  3609 
       
  3610     XsdParticle::List particles;
       
  3611     while (!atEnd()) {
       
  3612         readNext();
       
  3613 
       
  3614         if (isEndElement())
       
  3615             break;
       
  3616 
       
  3617         if (isStartElement()) {
       
  3618             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3619             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3620 
       
  3621             tagValidator.validate(token);
       
  3622 
       
  3623             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3624                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3625                 modelGroup->addAnnotation(annotation);
       
  3626             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
       
  3627                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3628                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
       
  3629                 particle->setTerm(term);
       
  3630 
       
  3631                 if (particle->maximumOccursUnbounded() || particle->maximumOccurs() > 1) {
       
  3632                     error(QtXmlPatterns::tr("%1 attribute of %2 element must be %3 or %4.")
       
  3633                                            .arg(formatAttribute("maxOccurs"))
       
  3634                                            .arg(formatElement("all"))
       
  3635                                            .arg(formatData("0"))
       
  3636                                            .arg(formatData("1")));
       
  3637                     return modelGroup;
       
  3638                 }
       
  3639 
       
  3640                 particles.append(particle);
       
  3641             } else {
       
  3642                 parseUnknown();
       
  3643             }
       
  3644         }
       
  3645     }
       
  3646 
       
  3647     modelGroup->setParticles(particles);
       
  3648 
       
  3649     tagValidator.finalize();
       
  3650 
       
  3651     return modelGroup;
       
  3652 }
       
  3653 
       
  3654 XsdModelGroup::Ptr XsdSchemaParser::parseLocalAll(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
       
  3655 {
       
  3656     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this);
       
  3657 
       
  3658     validateElement(XsdTagScope::LocalAll);
       
  3659 
       
  3660     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
       
  3661     modelGroup->setCompositor(XsdModelGroup::AllCompositor);
       
  3662 
       
  3663     // parse attributes
       
  3664     if (!parseMinMaxConstraint(particle, "all")) {
       
  3665         return modelGroup;
       
  3666     }
       
  3667     if (particle->maximumOccursUnbounded() || particle->maximumOccurs() != 1) {
       
  3668         error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3.")
       
  3669                                .arg(formatAttribute("maxOccurs"))
       
  3670                                .arg(formatElement("all"))
       
  3671                                .arg(formatData("1")));
       
  3672         return modelGroup;
       
  3673     }
       
  3674     if (particle->minimumOccurs() != 0 && particle->minimumOccurs() != 1) {
       
  3675         error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4.")
       
  3676                                .arg(formatAttribute("minOccurs"))
       
  3677                                .arg(formatElement("all"))
       
  3678                                .arg(formatData("0"))
       
  3679                                .arg(formatData("1")));
       
  3680         return modelGroup;
       
  3681     }
       
  3682 
       
  3683     validateIdAttribute("all");
       
  3684 
       
  3685     TagValidationHandler tagValidator(XsdTagScope::LocalAll, this, m_namePool);
       
  3686 
       
  3687     XsdParticle::List particles;
       
  3688     while (!atEnd()) {
       
  3689         readNext();
       
  3690 
       
  3691         if (isEndElement())
       
  3692             break;
       
  3693 
       
  3694         if (isStartElement()) {
       
  3695             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3696             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3697 
       
  3698             tagValidator.validate(token);
       
  3699 
       
  3700             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3701                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3702                 modelGroup->addAnnotation(annotation);
       
  3703             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
       
  3704                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3705                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
       
  3706                 particle->setTerm(term);
       
  3707 
       
  3708                 if (particle->maximumOccursUnbounded() || particle->maximumOccurs() > 1) {
       
  3709                     error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4.")
       
  3710                                            .arg(formatAttribute("maxOccurs"))
       
  3711                                            .arg(formatElement("all"))
       
  3712                                            .arg(formatData("0"))
       
  3713                                            .arg(formatData("1")));
       
  3714                     return modelGroup;
       
  3715                 }
       
  3716 
       
  3717                 particles.append(particle);
       
  3718             } else {
       
  3719                 parseUnknown();
       
  3720             }
       
  3721         }
       
  3722     }
       
  3723 
       
  3724     modelGroup->setParticles(particles);
       
  3725 
       
  3726     tagValidator.finalize();
       
  3727 
       
  3728     return modelGroup;
       
  3729 }
       
  3730 
       
  3731 XsdModelGroup::Ptr XsdSchemaParser::parseChoice(const NamedSchemaComponent::Ptr &parent)
       
  3732 {
       
  3733     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this);
       
  3734 
       
  3735     validateElement(XsdTagScope::Choice);
       
  3736 
       
  3737     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
       
  3738     modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor);
       
  3739 
       
  3740     validateIdAttribute("choice");
       
  3741 
       
  3742     XsdParticle::List particles;
       
  3743 
       
  3744     TagValidationHandler tagValidator(XsdTagScope::Choice, this, m_namePool);
       
  3745 
       
  3746     while (!atEnd()) {
       
  3747         readNext();
       
  3748 
       
  3749         if (isEndElement())
       
  3750             break;
       
  3751 
       
  3752         if (isStartElement()) {
       
  3753             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3754             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3755 
       
  3756             tagValidator.validate(token);
       
  3757 
       
  3758             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3759                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3760                 modelGroup->addAnnotation(annotation);
       
  3761             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
       
  3762                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3763                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
       
  3764                 particle->setTerm(term);
       
  3765                 particles.append(particle);
       
  3766             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
       
  3767                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3768                 const XsdTerm::Ptr term = parseReferredGroup(particle);
       
  3769                 m_schemaResolver->addAllGroupCheck(term);
       
  3770                 particle->setTerm(term);
       
  3771                 particles.append(particle);
       
  3772             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
       
  3773                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3774                 const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
       
  3775                 particle->setTerm(term);
       
  3776                 particles.append(particle);
       
  3777             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
       
  3778                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3779                 const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
       
  3780                 particle->setTerm(term);
       
  3781                 particles.append(particle);
       
  3782             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
       
  3783                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3784                 const XsdTerm::Ptr term = parseAny(particle);
       
  3785                 particle->setTerm(term);
       
  3786                 particles.append(particle);
       
  3787             } else {
       
  3788                 parseUnknown();
       
  3789             }
       
  3790         }
       
  3791     }
       
  3792 
       
  3793     modelGroup->setParticles(particles);
       
  3794 
       
  3795     tagValidator.finalize();
       
  3796 
       
  3797     return modelGroup;
       
  3798 }
       
  3799 
       
  3800 XsdModelGroup::Ptr XsdSchemaParser::parseLocalChoice(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
       
  3801 {
       
  3802     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this);
       
  3803 
       
  3804     validateElement(XsdTagScope::LocalChoice);
       
  3805 
       
  3806     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
       
  3807     modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor);
       
  3808 
       
  3809     // parse attributes
       
  3810     if (!parseMinMaxConstraint(particle, "choice")) {
       
  3811         return modelGroup;
       
  3812     }
       
  3813 
       
  3814     validateIdAttribute("choice");
       
  3815 
       
  3816     XsdParticle::List particles;
       
  3817 
       
  3818     TagValidationHandler tagValidator(XsdTagScope::LocalChoice, this, m_namePool);
       
  3819 
       
  3820     while (!atEnd()) {
       
  3821         readNext();
       
  3822 
       
  3823         if (isEndElement())
       
  3824             break;
       
  3825 
       
  3826         if (isStartElement()) {
       
  3827             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3828             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3829 
       
  3830             tagValidator.validate(token);
       
  3831 
       
  3832             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3833                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3834                 modelGroup->addAnnotation(annotation);
       
  3835             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
       
  3836                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3837                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
       
  3838                 particle->setTerm(term);
       
  3839                 particles.append(particle);
       
  3840             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
       
  3841                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3842                 const XsdTerm::Ptr term = parseReferredGroup(particle);
       
  3843                 m_schemaResolver->addAllGroupCheck(term);
       
  3844                 particle->setTerm(term);
       
  3845                 particles.append(particle);
       
  3846             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
       
  3847                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3848                 const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
       
  3849                 particle->setTerm(term);
       
  3850                 particles.append(particle);
       
  3851             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
       
  3852                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3853                 const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
       
  3854                 particle->setTerm(term);
       
  3855                 particles.append(particle);
       
  3856             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
       
  3857                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3858                 const XsdTerm::Ptr term = parseAny(particle);
       
  3859                 particle->setTerm(term);
       
  3860                 particles.append(particle);
       
  3861             } else {
       
  3862                 parseUnknown();
       
  3863             }
       
  3864         }
       
  3865     }
       
  3866 
       
  3867     modelGroup->setParticles(particles);
       
  3868 
       
  3869     tagValidator.finalize();
       
  3870 
       
  3871     return modelGroup;
       
  3872 }
       
  3873 
       
  3874 XsdModelGroup::Ptr XsdSchemaParser::parseSequence(const NamedSchemaComponent::Ptr &parent)
       
  3875 {
       
  3876     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this);
       
  3877 
       
  3878     validateElement(XsdTagScope::Sequence);
       
  3879 
       
  3880     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
       
  3881     modelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
       
  3882 
       
  3883     validateIdAttribute("sequence");
       
  3884 
       
  3885     XsdParticle::List particles;
       
  3886 
       
  3887     TagValidationHandler tagValidator(XsdTagScope::Sequence, this, m_namePool);
       
  3888 
       
  3889     while (!atEnd()) {
       
  3890         readNext();
       
  3891 
       
  3892         if (isEndElement())
       
  3893             break;
       
  3894 
       
  3895         if (isStartElement()) {
       
  3896             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3897             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3898 
       
  3899             tagValidator.validate(token);
       
  3900 
       
  3901             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3902                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3903                 modelGroup->addAnnotation(annotation);
       
  3904             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
       
  3905                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3906                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
       
  3907                 particle->setTerm(term);
       
  3908                 particles.append(particle);
       
  3909             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
       
  3910                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3911                 const XsdTerm::Ptr term = parseReferredGroup(particle);
       
  3912                 m_schemaResolver->addAllGroupCheck(term);
       
  3913                 particle->setTerm(term);
       
  3914                 particles.append(particle);
       
  3915             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
       
  3916                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3917                 const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
       
  3918                 particle->setTerm(term);
       
  3919                 particles.append(particle);
       
  3920             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
       
  3921                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3922                 const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
       
  3923                 particle->setTerm(term);
       
  3924                 particles.append(particle);
       
  3925             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
       
  3926                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3927                 const XsdTerm::Ptr term = parseAny(particle);
       
  3928                 particle->setTerm(term);
       
  3929                 particles.append(particle);
       
  3930             } else {
       
  3931                 parseUnknown();
       
  3932             }
       
  3933         }
       
  3934     }
       
  3935 
       
  3936     modelGroup->setParticles(particles);
       
  3937 
       
  3938     tagValidator.finalize();
       
  3939 
       
  3940     return modelGroup;
       
  3941 }
       
  3942 
       
  3943 XsdModelGroup::Ptr XsdSchemaParser::parseLocalSequence(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
       
  3944 {
       
  3945     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this);
       
  3946 
       
  3947     validateElement(XsdTagScope::LocalSequence);
       
  3948 
       
  3949     const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
       
  3950     modelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
       
  3951 
       
  3952     // parse attributes
       
  3953     if (!parseMinMaxConstraint(particle, "sequence")) {
       
  3954         return modelGroup;
       
  3955     }
       
  3956 
       
  3957     validateIdAttribute("sequence");
       
  3958 
       
  3959     XsdParticle::List particles;
       
  3960 
       
  3961     TagValidationHandler tagValidator(XsdTagScope::LocalSequence, this, m_namePool);
       
  3962 
       
  3963     while (!atEnd()) {
       
  3964         readNext();
       
  3965 
       
  3966         if (isEndElement())
       
  3967             break;
       
  3968 
       
  3969         if (isStartElement()) {
       
  3970             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  3971             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  3972 
       
  3973             tagValidator.validate(token);
       
  3974 
       
  3975             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  3976                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  3977                 modelGroup->addAnnotation(annotation);
       
  3978             } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
       
  3979                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3980                 const XsdTerm::Ptr term = parseLocalElement(particle, parent);
       
  3981                 particle->setTerm(term);
       
  3982                 particles.append(particle);
       
  3983             } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
       
  3984                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3985                 const XsdTerm::Ptr term = parseReferredGroup(particle);
       
  3986                 m_schemaResolver->addAllGroupCheck(term);
       
  3987                 particle->setTerm(term);
       
  3988                 particles.append(particle);
       
  3989             } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
       
  3990                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3991                 const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
       
  3992                 particle->setTerm(term);
       
  3993                 particles.append(particle);
       
  3994             } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
       
  3995                 const XsdParticle::Ptr particle(new XsdParticle());
       
  3996                 const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
       
  3997                 particle->setTerm(term);
       
  3998                 particles.append(particle);
       
  3999             } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
       
  4000                 const XsdParticle::Ptr particle(new XsdParticle());
       
  4001                 const XsdTerm::Ptr term = parseAny(particle);
       
  4002                 particle->setTerm(term);
       
  4003                 particles.append(particle);
       
  4004             } else {
       
  4005                 parseUnknown();
       
  4006             }
       
  4007         }
       
  4008     }
       
  4009 
       
  4010     modelGroup->setParticles(particles);
       
  4011 
       
  4012     tagValidator.finalize();
       
  4013 
       
  4014     return modelGroup;
       
  4015 }
       
  4016 
       
  4017 XsdAttribute::Ptr XsdSchemaParser::parseGlobalAttribute()
       
  4018 {
       
  4019     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this);
       
  4020 
       
  4021     validateElement(XsdTagScope::GlobalAttribute);
       
  4022 
       
  4023     const XsdAttribute::Ptr attribute(new XsdAttribute());
       
  4024     attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
       
  4025     attribute->scope()->setVariety(XsdAttribute::Scope::Global);
       
  4026 
       
  4027     if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
       
  4028         error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4029                                .arg(formatElement("attribute"))
       
  4030                                .arg(formatAttribute("default"))
       
  4031                                .arg(formatAttribute("fixed")));
       
  4032         return attribute;
       
  4033     }
       
  4034 
       
  4035     // parse attributes
       
  4036     if (hasAttribute(QString::fromLatin1("default"))) {
       
  4037         const QString value = readAttribute(QString::fromLatin1("default"));
       
  4038         attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
       
  4039         attribute->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Default);
       
  4040         attribute->valueConstraint()->setValue(value);
       
  4041     } else if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  4042         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  4043         attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
       
  4044         attribute->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Fixed);
       
  4045         attribute->valueConstraint()->setValue(value);
       
  4046     }
       
  4047 
       
  4048     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("attribute"));
       
  4049     if ((objectName.namespaceURI() == StandardNamespaces::xsi) &&
       
  4050         (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("type")) &&
       
  4051         (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("nil")) &&
       
  4052         (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("schemaLocation")) &&
       
  4053         (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) {
       
  4054 
       
  4055         error(QtXmlPatterns::tr("Content of %1 attribute of %2 element must not be from namespace %3.")
       
  4056                                .arg(formatAttribute("name"))
       
  4057                                .arg(formatElement("attribute"))
       
  4058                                .arg(formatURI(CommonNamespaces::XSI)));
       
  4059         return attribute;
       
  4060     }
       
  4061     if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) {
       
  4062         error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3.")
       
  4063                                .arg(formatAttribute("name"))
       
  4064                                .arg(formatElement("attribute"))
       
  4065                                .arg(formatData("xmlns")));
       
  4066         return attribute;
       
  4067     }
       
  4068     attribute->setName(objectName);
       
  4069 
       
  4070     bool hasTypeAttribute = false;
       
  4071     bool hasTypeSpecified = false;
       
  4072 
       
  4073     if (hasAttribute(QString::fromLatin1("type"))) {
       
  4074         hasTypeAttribute = true;
       
  4075 
       
  4076         const QString type = readQNameAttribute(QString::fromLatin1("type"), "attribute");
       
  4077         QXmlName typeName;
       
  4078         convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  4079         m_schemaResolver->addAttributeType(attribute, typeName, currentSourceLocation()); // add to resolver
       
  4080         hasTypeSpecified = true;
       
  4081     }
       
  4082 
       
  4083     validateIdAttribute("attribute");
       
  4084 
       
  4085     TagValidationHandler tagValidator(XsdTagScope::GlobalAttribute, this, m_namePool);
       
  4086 
       
  4087     while (!atEnd()) {
       
  4088         readNext();
       
  4089 
       
  4090         if (isEndElement())
       
  4091             break;
       
  4092 
       
  4093         if (isStartElement()) {
       
  4094             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  4095             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  4096 
       
  4097             tagValidator.validate(token);
       
  4098 
       
  4099             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  4100                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  4101                 attribute->addAnnotation(annotation);
       
  4102             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
       
  4103                 if (hasTypeAttribute) {
       
  4104                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4105                                            .arg(formatElement("attribute"))
       
  4106                                            .arg(formatElement("simpleType"))
       
  4107                                            .arg(formatAttribute("type")));
       
  4108                     break;
       
  4109                 }
       
  4110 
       
  4111                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
       
  4112                 type->setContext(attribute);
       
  4113                 attribute->setType(type);
       
  4114                 hasTypeSpecified = true;
       
  4115 
       
  4116                 // add it to list of anonymous types as well
       
  4117                 addAnonymousType(type);
       
  4118             } else {
       
  4119                 parseUnknown();
       
  4120             }
       
  4121         }
       
  4122     }
       
  4123 
       
  4124     if (!hasTypeSpecified) {
       
  4125         attribute->setType(BuiltinTypes::xsAnySimpleType); // default value
       
  4126         return attribute;
       
  4127     }
       
  4128 
       
  4129     tagValidator.finalize();
       
  4130 
       
  4131     return attribute;
       
  4132 }
       
  4133 
       
  4134 XsdAttributeUse::Ptr XsdSchemaParser::parseLocalAttribute(const NamedSchemaComponent::Ptr &parent)
       
  4135 {
       
  4136     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this);
       
  4137 
       
  4138     validateElement(XsdTagScope::LocalAttribute);
       
  4139 
       
  4140     bool hasRefAttribute = false;
       
  4141     bool hasTypeAttribute = false;
       
  4142     bool hasTypeSpecified = false;
       
  4143 
       
  4144     XsdAttributeUse::Ptr attributeUse;
       
  4145     if (hasAttribute(QString::fromLatin1("ref"))) {
       
  4146         const XsdAttributeReference::Ptr reference = XsdAttributeReference::Ptr(new XsdAttributeReference());
       
  4147         reference->setType(XsdAttributeReference::AttributeUse);
       
  4148         reference->setSourceLocation(currentSourceLocation());
       
  4149 
       
  4150         attributeUse = reference;
       
  4151         hasRefAttribute = true;
       
  4152     } else {
       
  4153         attributeUse = XsdAttributeUse::Ptr(new XsdAttributeUse());
       
  4154     }
       
  4155 
       
  4156     if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
       
  4157         error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4158                                .arg(formatElement("attribute"))
       
  4159                                .arg(formatAttribute("default"))
       
  4160                                .arg(formatAttribute("fixed")));
       
  4161         return attributeUse;
       
  4162     }
       
  4163 
       
  4164     if (hasRefAttribute) {
       
  4165         if (hasAttribute(QString::fromLatin1("form"))) {
       
  4166             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4167                                    .arg(formatElement("attribute"))
       
  4168                                    .arg(formatAttribute("ref"))
       
  4169                                    .arg(formatAttribute("form")));
       
  4170             return attributeUse;
       
  4171         }
       
  4172         if (hasAttribute(QString::fromLatin1("name"))) {
       
  4173             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4174                                    .arg(formatElement("attribute"))
       
  4175                                    .arg(formatAttribute("ref"))
       
  4176                                    .arg(formatAttribute("name")));
       
  4177             return attributeUse;
       
  4178         }
       
  4179         if (hasAttribute(QString::fromLatin1("type"))) {
       
  4180             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4181                                    .arg(formatElement("attribute"))
       
  4182                                    .arg(formatAttribute("ref"))
       
  4183                                    .arg(formatAttribute("type")));
       
  4184             return attributeUse;
       
  4185         }
       
  4186     }
       
  4187 
       
  4188     // parse attributes
       
  4189 
       
  4190     // default, fixed and use are handled by both, attribute use and attribute reference
       
  4191     if (hasAttribute(QString::fromLatin1("default"))) {
       
  4192         const QString value = readAttribute(QString::fromLatin1("default"));
       
  4193         attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint()));
       
  4194         attributeUse->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Default);
       
  4195         attributeUse->valueConstraint()->setValue(value);
       
  4196     } else if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  4197         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  4198         attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint()));
       
  4199         attributeUse->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Fixed);
       
  4200         attributeUse->valueConstraint()->setValue(value);
       
  4201     }
       
  4202 
       
  4203     if (hasAttribute(QString::fromLatin1("use"))) {
       
  4204         const QString value = readAttribute(QString::fromLatin1("use"));
       
  4205         if (value != QString::fromLatin1("optional") &&
       
  4206             value != QString::fromLatin1("prohibited") &&
       
  4207             value != QString::fromLatin1("required")) {
       
  4208             attributeContentError("use", "attribute", value);
       
  4209             return attributeUse;
       
  4210         }
       
  4211 
       
  4212         if (value == QString::fromLatin1("optional"))
       
  4213             attributeUse->setUseType(XsdAttributeUse::OptionalUse);
       
  4214         else if (value == QString::fromLatin1("prohibited"))
       
  4215             attributeUse->setUseType(XsdAttributeUse::ProhibitedUse);
       
  4216         else if (value == QString::fromLatin1("required"))
       
  4217             attributeUse->setUseType(XsdAttributeUse::RequiredUse);
       
  4218 
       
  4219         if (attributeUse->valueConstraint() && attributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Default && value != QString::fromLatin1("optional")) {
       
  4220             error(QtXmlPatterns::tr("%1 attribute of %2 element must have the value %3 because the %4 attribute is set.")
       
  4221                                    .arg(formatAttribute("use"))
       
  4222                                    .arg(formatElement("attribute"))
       
  4223                                    .arg(formatData("optional"))
       
  4224                                    .arg(formatElement("default")));
       
  4225             return attributeUse;
       
  4226         }
       
  4227     }
       
  4228 
       
  4229     const XsdAttribute::Ptr attribute(new XsdAttribute());
       
  4230 
       
  4231     attributeUse->setAttribute(attribute);
       
  4232     m_componentLocationHash.insert(attribute, currentSourceLocation());
       
  4233 
       
  4234     attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
       
  4235     attribute->scope()->setVariety(XsdAttribute::Scope::Local);
       
  4236     attribute->scope()->setParent(parent);
       
  4237 
       
  4238     // now make a difference between attribute reference and attribute use
       
  4239     if (hasRefAttribute) {
       
  4240         const QString reference = readQNameAttribute(QString::fromLatin1("ref"), "attribute");
       
  4241         QXmlName referenceName;
       
  4242         convertName(reference, NamespaceSupport::ElementName, referenceName);   // translate qualified name into QXmlName
       
  4243 
       
  4244         const XsdAttributeReference::Ptr attributeReference = attributeUse;
       
  4245         attributeReference->setReferenceName(referenceName);
       
  4246     } else {
       
  4247         if (hasAttribute(QString::fromLatin1("name"))) {
       
  4248             const QString attributeName = readNameAttribute("attribute");
       
  4249 
       
  4250             QXmlName objectName;
       
  4251             if (hasAttribute(QString::fromLatin1("form"))) {
       
  4252                 const QString value = readAttribute(QString::fromLatin1("form"));
       
  4253                 if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
       
  4254                     attributeContentError("form", "attribute", value);
       
  4255                     return attributeUse;
       
  4256                 }
       
  4257 
       
  4258                 if (value == QString::fromLatin1("qualified")) {
       
  4259                     objectName = m_namePool->allocateQName(m_targetNamespace, attributeName);
       
  4260                 } else {
       
  4261                     objectName = m_namePool->allocateQName(QString(), attributeName);
       
  4262                 }
       
  4263             } else {
       
  4264                 if (m_attributeFormDefault == QString::fromLatin1("qualified")) {
       
  4265                     objectName = m_namePool->allocateQName(m_targetNamespace, attributeName);
       
  4266                 } else {
       
  4267                     objectName = m_namePool->allocateQName(QString(), attributeName);
       
  4268                 }
       
  4269             }
       
  4270 
       
  4271             if ((objectName.namespaceURI() == StandardNamespaces::xsi) &&
       
  4272                 (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("type")) &&
       
  4273                 (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("nil")) &&
       
  4274                 (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("schemaLocation")) &&
       
  4275                 (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) {
       
  4276 
       
  4277                 error(QtXmlPatterns::tr("Content of %1 attribute of %2 element must not be from namespace %3.")
       
  4278                                        .arg(formatAttribute("name"))
       
  4279                                        .arg(formatElement("attribute"))
       
  4280                                        .arg(formatURI(CommonNamespaces::XSI)));
       
  4281                 return attributeUse;
       
  4282             }
       
  4283             if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) {
       
  4284                 error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3.")
       
  4285                                        .arg(formatAttribute("name"))
       
  4286                                        .arg(formatElement("attribute"))
       
  4287                                        .arg(formatData("xmlns")));
       
  4288                 return attributeUse;
       
  4289             }
       
  4290 
       
  4291             attribute->setName(objectName);
       
  4292         }
       
  4293 
       
  4294         if (hasAttribute(QString::fromLatin1("type"))) {
       
  4295             hasTypeAttribute = true;
       
  4296 
       
  4297             const QString type = readQNameAttribute(QString::fromLatin1("type"), "attribute");
       
  4298             QXmlName typeName;
       
  4299             convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  4300             m_schemaResolver->addAttributeType(attribute, typeName, currentSourceLocation()); // add to resolver
       
  4301             hasTypeSpecified = true;
       
  4302         }
       
  4303 
       
  4304         if (attributeUse->valueConstraint()) {
       
  4305             //TODO: check whether assigning the value constraint of the attribute use to the attribute is correct
       
  4306             if (!attribute->valueConstraint())
       
  4307                 attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
       
  4308 
       
  4309             attribute->valueConstraint()->setVariety((XsdAttribute::ValueConstraint::Variety)attributeUse->valueConstraint()->variety());
       
  4310             attribute->valueConstraint()->setValue(attributeUse->valueConstraint()->value());
       
  4311             attribute->valueConstraint()->setLexicalForm(attributeUse->valueConstraint()->lexicalForm());
       
  4312         }
       
  4313     }
       
  4314 
       
  4315     validateIdAttribute("attribute");
       
  4316 
       
  4317     TagValidationHandler tagValidator(XsdTagScope::LocalAttribute, this, m_namePool);
       
  4318 
       
  4319     while (!atEnd()) {
       
  4320         readNext();
       
  4321 
       
  4322         if (isEndElement())
       
  4323             break;
       
  4324 
       
  4325         if (isStartElement()) {
       
  4326             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  4327             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  4328 
       
  4329             tagValidator.validate(token);
       
  4330 
       
  4331             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  4332                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  4333                 attribute->addAnnotation(annotation);
       
  4334             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
       
  4335                 if (hasTypeAttribute) {
       
  4336                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4337                                            .arg(formatElement("attribute"))
       
  4338                                            .arg(formatElement("simpleType"))
       
  4339                                            .arg(formatAttribute("type")));
       
  4340                     break;
       
  4341                 }
       
  4342                 if (hasRefAttribute) {
       
  4343                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4344                                            .arg(formatElement("attribute"))
       
  4345                                            .arg(formatElement("simpleType"))
       
  4346                                            .arg(formatAttribute("ref")));
       
  4347                     break;
       
  4348                 }
       
  4349 
       
  4350                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
       
  4351                 type->setContext(attribute);
       
  4352                 attribute->setType(type);
       
  4353                 hasTypeSpecified = true;
       
  4354 
       
  4355                 // add it to list of anonymous types as well
       
  4356                 addAnonymousType(type);
       
  4357             } else {
       
  4358                 parseUnknown();
       
  4359             }
       
  4360         }
       
  4361     }
       
  4362 
       
  4363     if (!hasTypeSpecified) {
       
  4364         attribute->setType(BuiltinTypes::xsAnySimpleType); // default value
       
  4365     }
       
  4366 
       
  4367     tagValidator.finalize();
       
  4368 
       
  4369     return attributeUse;
       
  4370 }
       
  4371 
       
  4372 XsdAttributeGroup::Ptr XsdSchemaParser::parseNamedAttributeGroup()
       
  4373 {
       
  4374     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this);
       
  4375 
       
  4376     validateElement(XsdTagScope::NamedAttributeGroup);
       
  4377 
       
  4378     const XsdAttributeGroup::Ptr attributeGroup(new XsdAttributeGroup());
       
  4379 
       
  4380     // parse attributes
       
  4381     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("attributeGroup"));
       
  4382     attributeGroup->setName(objectName);
       
  4383 
       
  4384     validateIdAttribute("attributeGroup");
       
  4385 
       
  4386     TagValidationHandler tagValidator(XsdTagScope::NamedAttributeGroup, this, m_namePool);
       
  4387 
       
  4388     while (!atEnd()) {
       
  4389         readNext();
       
  4390 
       
  4391         if (isEndElement())
       
  4392             break;
       
  4393 
       
  4394         if (isStartElement()) {
       
  4395             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  4396             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  4397 
       
  4398             tagValidator.validate(token);
       
  4399 
       
  4400             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  4401                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  4402                 attributeGroup->addAnnotation(annotation);
       
  4403             } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
       
  4404                 const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(attributeGroup);
       
  4405 
       
  4406                 if (attributeUse->useType() == XsdAttributeUse::ProhibitedUse) {
       
  4407                     warning(QtXmlPatterns::tr("Specifying use='prohibited' inside an attribute group has no effect."));
       
  4408                 } else {
       
  4409                     attributeGroup->addAttributeUse(attributeUse);
       
  4410                 }
       
  4411             } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
       
  4412                 const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
       
  4413                 attributeGroup->addAttributeUse(attributeUse);
       
  4414             } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
       
  4415                 const XsdWildcard::Ptr wildcard = parseAnyAttribute();
       
  4416                 attributeGroup->setWildcard(wildcard);
       
  4417             } else {
       
  4418                 parseUnknown();
       
  4419             }
       
  4420         }
       
  4421     }
       
  4422 
       
  4423     tagValidator.finalize();
       
  4424 
       
  4425     return attributeGroup;
       
  4426 }
       
  4427 
       
  4428 XsdAttributeUse::Ptr XsdSchemaParser::parseReferredAttributeGroup()
       
  4429 {
       
  4430     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this);
       
  4431 
       
  4432     validateElement(XsdTagScope::ReferredAttributeGroup);
       
  4433 
       
  4434     const XsdAttributeReference::Ptr attributeReference(new XsdAttributeReference());
       
  4435     attributeReference->setType(XsdAttributeReference::AttributeGroup);
       
  4436     attributeReference->setSourceLocation(currentSourceLocation());
       
  4437 
       
  4438     // parse attributes
       
  4439     const QString reference = readQNameAttribute(QString::fromLatin1("ref"), "attributeGroup");
       
  4440     QXmlName referenceName;
       
  4441     convertName(reference, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
       
  4442     attributeReference->setReferenceName(referenceName);
       
  4443 
       
  4444     validateIdAttribute("attributeGroup");
       
  4445 
       
  4446     TagValidationHandler tagValidator(XsdTagScope::ReferredAttributeGroup, this, m_namePool);
       
  4447 
       
  4448     while (!atEnd()) {
       
  4449         readNext();
       
  4450 
       
  4451         if (isEndElement())
       
  4452             break;
       
  4453 
       
  4454         if (isStartElement()) {
       
  4455             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  4456             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  4457 
       
  4458             tagValidator.validate(token);
       
  4459 
       
  4460             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  4461                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  4462                 attributeReference->addAnnotation(annotation);
       
  4463             } else {
       
  4464                 parseUnknown();
       
  4465             }
       
  4466         }
       
  4467     }
       
  4468 
       
  4469     tagValidator.finalize();
       
  4470 
       
  4471     return attributeReference;
       
  4472 }
       
  4473 
       
  4474 XsdElement::Ptr XsdSchemaParser::parseGlobalElement()
       
  4475 {
       
  4476     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this);
       
  4477 
       
  4478     validateElement(XsdTagScope::GlobalElement);
       
  4479 
       
  4480     const XsdElement::Ptr element(new XsdElement());
       
  4481     element->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope()));
       
  4482     element->scope()->setVariety(XsdElement::Scope::Global);
       
  4483 
       
  4484     bool hasTypeAttribute = false;
       
  4485     bool hasTypeSpecified = false;
       
  4486     bool hasSubstitutionGroup = false;
       
  4487 
       
  4488     // parse attributes
       
  4489     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("element"));
       
  4490     element->setName(objectName);
       
  4491 
       
  4492     if (hasAttribute(QString::fromLatin1("abstract"))) {
       
  4493         const QString abstract = readAttribute(QString::fromLatin1("abstract"));
       
  4494 
       
  4495         const Boolean::Ptr value = Boolean::fromLexical(abstract);
       
  4496         if (value->hasError()) {
       
  4497             attributeContentError("abstract", "element", abstract, BuiltinTypes::xsBoolean);
       
  4498             return element;
       
  4499         }
       
  4500 
       
  4501         element->setIsAbstract(value->as<Boolean>()->value());
       
  4502     } else {
       
  4503         element->setIsAbstract(false); // the default value
       
  4504     }
       
  4505 
       
  4506     if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
       
  4507         error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4508                                .arg(formatElement("element"))
       
  4509                                .arg(formatAttribute("default"))
       
  4510                                .arg(formatAttribute("fixed")));
       
  4511         return element;
       
  4512     }
       
  4513 
       
  4514     if (hasAttribute(QString::fromLatin1("default"))) {
       
  4515         const QString value = readAttribute(QString::fromLatin1("default"));
       
  4516         element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
       
  4517         element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default);
       
  4518         element->valueConstraint()->setValue(value);
       
  4519     } else if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  4520         const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  4521         element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
       
  4522         element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed);
       
  4523         element->valueConstraint()->setValue(value);
       
  4524     }
       
  4525 
       
  4526     element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element"));
       
  4527     element->setSubstitutionGroupExclusions(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "element"));
       
  4528 
       
  4529     if (hasAttribute(QString::fromLatin1("nillable"))) {
       
  4530         const QString nillable = readAttribute(QString::fromLatin1("nillable"));
       
  4531 
       
  4532         const Boolean::Ptr value = Boolean::fromLexical(nillable);
       
  4533         if (value->hasError()) {
       
  4534             attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean);
       
  4535             return element;
       
  4536         }
       
  4537 
       
  4538         element->setIsNillable(value->as<Boolean>()->value());
       
  4539     } else {
       
  4540         element->setIsNillable(false); // the default value
       
  4541     }
       
  4542 
       
  4543     if (hasAttribute(QString::fromLatin1("type"))) {
       
  4544         const QString type = readQNameAttribute(QString::fromLatin1("type"), "element");
       
  4545         QXmlName typeName;
       
  4546         convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  4547         m_schemaResolver->addElementType(element, typeName, currentSourceLocation()); // add to resolver
       
  4548 
       
  4549         hasTypeAttribute = true;
       
  4550         hasTypeSpecified = true;
       
  4551     }
       
  4552 
       
  4553     if (hasAttribute(QString::fromLatin1("substitutionGroup"))) {
       
  4554         QList<QXmlName> elementNames;
       
  4555 
       
  4556         const QString value = readAttribute(QString::fromLatin1("substitutionGroup"));
       
  4557         const QStringList substitutionGroups = value.split(QLatin1Char(' '), QString::SkipEmptyParts);
       
  4558         if (substitutionGroups.isEmpty()) {
       
  4559             attributeContentError("substitutionGroup", "element", value, BuiltinTypes::xsQName);
       
  4560             return element;
       
  4561         }
       
  4562 
       
  4563         for (int i = 0; i < substitutionGroups.count(); ++i) {
       
  4564             const QString value = substitutionGroups.at(i).simplified();
       
  4565             if (!XPathHelper::isQName(value)) {
       
  4566                 attributeContentError("substitutionGroup", "element", value, BuiltinTypes::xsQName);
       
  4567                 return element;
       
  4568             }
       
  4569 
       
  4570             QXmlName elementName;
       
  4571             convertName(value, NamespaceSupport::ElementName, elementName); // translate qualified name into QXmlName
       
  4572             elementNames.append(elementName);
       
  4573         }
       
  4574 
       
  4575         m_schemaResolver->addSubstitutionGroupAffiliation(element, elementNames, currentSourceLocation()); // add to resolver
       
  4576 
       
  4577         hasSubstitutionGroup = true;
       
  4578     }
       
  4579 
       
  4580     validateIdAttribute("element");
       
  4581 
       
  4582     XsdAlternative::List alternatives;
       
  4583 
       
  4584     TagValidationHandler tagValidator(XsdTagScope::GlobalElement, this, m_namePool);
       
  4585 
       
  4586     while (!atEnd()) {
       
  4587         readNext();
       
  4588 
       
  4589         if (isEndElement())
       
  4590             break;
       
  4591 
       
  4592         if (isStartElement()) {
       
  4593             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  4594             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  4595 
       
  4596             tagValidator.validate(token);
       
  4597 
       
  4598             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  4599                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  4600                 element->addAnnotation(annotation);
       
  4601             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
       
  4602                 if (hasTypeAttribute) {
       
  4603                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4604                                            .arg(formatElement("element"))
       
  4605                                            .arg(formatElement("simpleType"))
       
  4606                                            .arg(formatAttribute("type")));
       
  4607                     return element;
       
  4608                 }
       
  4609 
       
  4610                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
       
  4611                 type->setContext(element);
       
  4612                 element->setType(type);
       
  4613 
       
  4614                 // add it to list of anonymous types as well
       
  4615                 addAnonymousType(type);
       
  4616 
       
  4617                 hasTypeSpecified = true;
       
  4618             } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
       
  4619                 if (hasTypeAttribute) {
       
  4620                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4621                                            .arg(formatElement("element"))
       
  4622                                            .arg(formatElement("complexType"))
       
  4623                                            .arg(formatAttribute("type")));
       
  4624                     return element;
       
  4625                 }
       
  4626 
       
  4627                 const XsdComplexType::Ptr type = parseLocalComplexType();
       
  4628                 type->setContext(element);
       
  4629                 element->setType(type);
       
  4630 
       
  4631                 // add it to list of anonymous types as well
       
  4632                 addAnonymousType(type);
       
  4633 
       
  4634                 hasTypeSpecified = true;
       
  4635             } else if (isSchemaTag(XsdSchemaToken::Alternative, token, namespaceToken)) {
       
  4636                 const XsdAlternative::Ptr alternative = parseAlternative();
       
  4637                 alternatives.append(alternative);
       
  4638             } else if (isSchemaTag(XsdSchemaToken::Unique, token, namespaceToken)) {
       
  4639                 const XsdIdentityConstraint::Ptr constraint = parseUnique();
       
  4640                 element->addIdentityConstraint(constraint);
       
  4641             } else if (isSchemaTag(XsdSchemaToken::Key, token, namespaceToken)) {
       
  4642                 const XsdIdentityConstraint::Ptr constraint = parseKey();
       
  4643                 element->addIdentityConstraint(constraint);
       
  4644             } else if (isSchemaTag(XsdSchemaToken::Keyref, token, namespaceToken)) {
       
  4645                 const XsdIdentityConstraint::Ptr constraint = parseKeyRef(element);
       
  4646                 element->addIdentityConstraint(constraint);
       
  4647             } else {
       
  4648                 parseUnknown();
       
  4649             }
       
  4650         }
       
  4651     }
       
  4652 
       
  4653     tagValidator.finalize();
       
  4654 
       
  4655     if (!hasTypeSpecified) {
       
  4656         if (hasSubstitutionGroup)
       
  4657             m_schemaResolver->addSubstitutionGroupType(element);
       
  4658         else
       
  4659             element->setType(BuiltinTypes::xsAnyType);
       
  4660     }
       
  4661 
       
  4662     if (!alternatives.isEmpty()) {
       
  4663         element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
       
  4664 
       
  4665         for (int i = 0; i < alternatives.count(); ++i) {
       
  4666             if (alternatives.at(i)->test())
       
  4667                 element->typeTable()->addAlternative(alternatives.at(i));
       
  4668 
       
  4669             if (i == (alternatives.count() - 1)) { // the final one
       
  4670                 if (!alternatives.at(i)->test()) {
       
  4671                     element->typeTable()->setDefaultTypeDefinition(alternatives.at(i));
       
  4672                 } else {
       
  4673                     const XsdAlternative::Ptr alternative(new XsdAlternative());
       
  4674                     if (element->type())
       
  4675                         alternative->setType(element->type());
       
  4676                     else
       
  4677                         m_schemaResolver->addAlternativeType(alternative, element); // add to resolver
       
  4678 
       
  4679                     element->typeTable()->setDefaultTypeDefinition(alternative);
       
  4680                 }
       
  4681             }
       
  4682         }
       
  4683     }
       
  4684 
       
  4685     return element;
       
  4686 }
       
  4687 
       
  4688 XsdTerm::Ptr XsdSchemaParser::parseLocalElement(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
       
  4689 {
       
  4690     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this);
       
  4691 
       
  4692     validateElement(XsdTagScope::LocalElement);
       
  4693 
       
  4694     bool hasRefAttribute = false;
       
  4695     bool hasTypeAttribute = false;
       
  4696     bool hasTypeSpecified = false;
       
  4697 
       
  4698     XsdTerm::Ptr term;
       
  4699     XsdElement::Ptr element;
       
  4700     if (hasAttribute(QString::fromLatin1("ref"))) {
       
  4701         term = XsdReference::Ptr(new XsdReference());
       
  4702         hasRefAttribute = true;
       
  4703     } else {
       
  4704         term = XsdElement::Ptr(new XsdElement());
       
  4705         element = term;
       
  4706     }
       
  4707 
       
  4708     if (hasRefAttribute) {
       
  4709         if (hasAttribute(QString::fromLatin1("name"))) {
       
  4710             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4711                                    .arg(formatElement("element"))
       
  4712                                    .arg(formatAttribute("ref"))
       
  4713                                    .arg(formatAttribute("name")));
       
  4714             return term;
       
  4715         } else if (hasAttribute(QString::fromLatin1("block"))) {
       
  4716             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4717                                    .arg(formatElement("element"))
       
  4718                                    .arg(formatAttribute("ref"))
       
  4719                                    .arg(formatAttribute("block")));
       
  4720             return term;
       
  4721         } else if (hasAttribute(QString::fromLatin1("nillable"))) {
       
  4722             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4723                                    .arg(formatElement("element"))
       
  4724                                    .arg(formatAttribute("ref"))
       
  4725                                    .arg(formatAttribute("nillable")));
       
  4726             return term;
       
  4727         } else if (hasAttribute(QString::fromLatin1("default"))) {
       
  4728             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4729                                    .arg(formatElement("element"))
       
  4730                                    .arg(formatAttribute("ref"))
       
  4731                                    .arg(formatAttribute("default")));
       
  4732             return term;
       
  4733         } else if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  4734             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4735                                    .arg(formatElement("element"))
       
  4736                                    .arg(formatAttribute("ref"))
       
  4737                                    .arg(formatAttribute("fixed")));
       
  4738             return term;
       
  4739         } else if (hasAttribute(QString::fromLatin1("form"))) {
       
  4740             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4741                                    .arg(formatElement("element"))
       
  4742                                    .arg(formatAttribute("ref"))
       
  4743                                    .arg(formatAttribute("form")));
       
  4744             return term;
       
  4745         } else if (hasAttribute(QString::fromLatin1("type"))) {
       
  4746             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4747                                    .arg(formatElement("element"))
       
  4748                                    .arg(formatAttribute("ref"))
       
  4749                                    .arg(formatAttribute("type")));
       
  4750             return term;
       
  4751         }
       
  4752     }
       
  4753 
       
  4754     // parse attributes
       
  4755     if (!parseMinMaxConstraint(particle, "element")) {
       
  4756         return element;
       
  4757     }
       
  4758 
       
  4759     if (!hasAttribute(QString::fromLatin1("name")) && !hasAttribute(QString::fromLatin1("ref"))) {
       
  4760         error(QtXmlPatterns::tr("%1 element must have either %2 or %3 attribute.")
       
  4761                                .arg(formatElement("element"))
       
  4762                                .arg(formatAttribute("name"))
       
  4763                                .arg(formatAttribute("ref")));
       
  4764         return element;
       
  4765     }
       
  4766 
       
  4767     if (hasRefAttribute) {
       
  4768         const QString ref = readQNameAttribute(QString::fromLatin1("ref"), "element");
       
  4769         QXmlName referenceName;
       
  4770         convertName(ref, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
       
  4771 
       
  4772         const XsdReference::Ptr reference = term;
       
  4773         reference->setReferenceName(referenceName);
       
  4774         reference->setType(XsdReference::Element);
       
  4775         reference->setSourceLocation(currentSourceLocation());
       
  4776     } else {
       
  4777         element->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope()));
       
  4778         element->scope()->setVariety(XsdElement::Scope::Local);
       
  4779         element->scope()->setParent(parent);
       
  4780 
       
  4781         if (hasAttribute(QString::fromLatin1("name"))) {
       
  4782             const QString elementName = readNameAttribute("element");
       
  4783 
       
  4784             QXmlName objectName;
       
  4785             if (hasAttribute(QString::fromLatin1("form"))) {
       
  4786                 const QString value = readAttribute(QString::fromLatin1("form"));
       
  4787                 if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
       
  4788                     attributeContentError("form", "element", value);
       
  4789                     return element;
       
  4790                 }
       
  4791 
       
  4792                 if (value == QString::fromLatin1("qualified")) {
       
  4793                     objectName = m_namePool->allocateQName(m_targetNamespace, elementName);
       
  4794                 } else {
       
  4795                     objectName = m_namePool->allocateQName(QString(), elementName);
       
  4796                 }
       
  4797             } else {
       
  4798                 if (m_elementFormDefault == QString::fromLatin1("qualified")) {
       
  4799                     objectName = m_namePool->allocateQName(m_targetNamespace, elementName);
       
  4800                 } else {
       
  4801                     objectName = m_namePool->allocateQName(QString(), elementName);
       
  4802                 }
       
  4803             }
       
  4804 
       
  4805             element->setName(objectName);
       
  4806         }
       
  4807 
       
  4808         if (hasAttribute(QString::fromLatin1("nillable"))) {
       
  4809             const QString nillable = readAttribute(QString::fromLatin1("nillable"));
       
  4810 
       
  4811             const Boolean::Ptr value = Boolean::fromLexical(nillable);
       
  4812             if (value->hasError()) {
       
  4813                 attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean);
       
  4814                 return term;
       
  4815             }
       
  4816 
       
  4817             element->setIsNillable(value->as<Boolean>()->value());
       
  4818         } else {
       
  4819             element->setIsNillable(false); // the default value
       
  4820         }
       
  4821 
       
  4822         if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
       
  4823             error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
       
  4824                                    .arg(formatElement("element"))
       
  4825                                    .arg(formatAttribute("default"))
       
  4826                                    .arg(formatAttribute("fixed")));
       
  4827             return element;
       
  4828         }
       
  4829 
       
  4830         if (hasAttribute(QString::fromLatin1("default"))) {
       
  4831             const QString value = readAttribute(QString::fromLatin1("default"));
       
  4832             element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
       
  4833             element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default);
       
  4834             element->valueConstraint()->setValue(value);
       
  4835         } else if (hasAttribute(QString::fromLatin1("fixed"))) {
       
  4836             const QString value = readAttribute(QString::fromLatin1("fixed"));
       
  4837             element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
       
  4838             element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed);
       
  4839             element->valueConstraint()->setValue(value);
       
  4840         }
       
  4841 
       
  4842         if (hasAttribute(QString::fromLatin1("type"))) {
       
  4843             const QString type = readQNameAttribute(QString::fromLatin1("type"), "element");
       
  4844             QXmlName typeName;
       
  4845             convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  4846             m_schemaResolver->addElementType(element, typeName, currentSourceLocation()); // add to resolver
       
  4847 
       
  4848             hasTypeAttribute = true;
       
  4849             hasTypeSpecified = true;
       
  4850         }
       
  4851 
       
  4852         element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element"));
       
  4853     }
       
  4854 
       
  4855     validateIdAttribute("element");
       
  4856 
       
  4857     XsdAlternative::List alternatives;
       
  4858 
       
  4859     TagValidationHandler tagValidator(XsdTagScope::LocalElement, this, m_namePool);
       
  4860 
       
  4861     while (!atEnd()) {
       
  4862         readNext();
       
  4863 
       
  4864         if (isEndElement())
       
  4865             break;
       
  4866 
       
  4867         if (isStartElement()) {
       
  4868             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  4869             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  4870 
       
  4871             tagValidator.validate(token);
       
  4872 
       
  4873             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  4874                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  4875                 term->addAnnotation(annotation);
       
  4876             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
       
  4877                 if (hasRefAttribute) {
       
  4878                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4879                                            .arg(formatElement("element"))
       
  4880                                            .arg(formatElement("simpleType"))
       
  4881                                            .arg(formatAttribute("ref")));
       
  4882                     return term;
       
  4883                 } else if (hasTypeAttribute) {
       
  4884                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4885                                            .arg(formatElement("element"))
       
  4886                                            .arg(formatElement("simpleType"))
       
  4887                                            .arg(formatAttribute("type")));
       
  4888                     return term;
       
  4889                 }
       
  4890 
       
  4891                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
       
  4892                 type->setContext(element);
       
  4893                 element->setType(type);
       
  4894 
       
  4895                 // add it to list of anonymous types as well
       
  4896                 addAnonymousType(type);
       
  4897 
       
  4898                 hasTypeSpecified = true;
       
  4899             } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
       
  4900                 if (hasRefAttribute) {
       
  4901                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4902                                            .arg(formatElement("element"))
       
  4903                                            .arg(formatElement("complexType"))
       
  4904                                            .arg(formatAttribute("ref")));
       
  4905                     return term;
       
  4906                 } else if (hasTypeAttribute) {
       
  4907                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4908                                            .arg(formatElement("element"))
       
  4909                                            .arg(formatElement("complexType"))
       
  4910                                            .arg(formatAttribute("type")));
       
  4911                     return term;
       
  4912                 }
       
  4913 
       
  4914                 const XsdComplexType::Ptr type = parseLocalComplexType();
       
  4915                 type->setContext(element);
       
  4916                 element->setType(type);
       
  4917 
       
  4918                 // add it to list of anonymous types as well
       
  4919                 addAnonymousType(type);
       
  4920 
       
  4921                 hasTypeSpecified = true;
       
  4922             } else if (isSchemaTag(XsdSchemaToken::Alternative, token, namespaceToken)) {
       
  4923                 if (hasRefAttribute) {
       
  4924                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4925                                            .arg(formatElement("element"))
       
  4926                                            .arg(formatElement("alternative"))
       
  4927                                            .arg(formatAttribute("ref")));
       
  4928                     return term;
       
  4929                 }
       
  4930 
       
  4931                 const XsdAlternative::Ptr alternative = parseAlternative();
       
  4932                 alternatives.append(alternative);
       
  4933             } else if (isSchemaTag(XsdSchemaToken::Unique, token, namespaceToken)) {
       
  4934                 if (hasRefAttribute) {
       
  4935                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4936                                            .arg(formatElement("element"))
       
  4937                                            .arg(formatElement("unique"))
       
  4938                                            .arg(formatAttribute("ref")));
       
  4939                     return term;
       
  4940                 }
       
  4941 
       
  4942                 const XsdIdentityConstraint::Ptr constraint = parseUnique();
       
  4943                 element->addIdentityConstraint(constraint);
       
  4944             } else if (isSchemaTag(XsdSchemaToken::Key, token, namespaceToken)) {
       
  4945                 if (hasRefAttribute) {
       
  4946                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4947                                            .arg(formatElement("element"))
       
  4948                                            .arg(formatElement("key"))
       
  4949                                            .arg(formatAttribute("ref")));
       
  4950                     return term;
       
  4951                 }
       
  4952 
       
  4953                 const XsdIdentityConstraint::Ptr constraint = parseKey();
       
  4954                 element->addIdentityConstraint(constraint);
       
  4955             } else if (isSchemaTag(XsdSchemaToken::Keyref, token, namespaceToken)) {
       
  4956                 if (hasRefAttribute) {
       
  4957                     error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
       
  4958                                            .arg(formatElement("element"))
       
  4959                                            .arg(formatElement("keyref"))
       
  4960                                            .arg(formatAttribute("ref")));
       
  4961                     return term;
       
  4962                 }
       
  4963 
       
  4964                 const XsdIdentityConstraint::Ptr constraint = parseKeyRef(element);
       
  4965                 element->addIdentityConstraint(constraint);
       
  4966             } else {
       
  4967                 parseUnknown();
       
  4968             }
       
  4969         }
       
  4970     }
       
  4971 
       
  4972     tagValidator.finalize();
       
  4973 
       
  4974     if (!hasTypeSpecified && !hasRefAttribute)
       
  4975         element->setType(BuiltinTypes::xsAnyType);
       
  4976 
       
  4977     if (!hasRefAttribute && !alternatives.isEmpty()) {
       
  4978         element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
       
  4979 
       
  4980         for (int i = 0; i < alternatives.count(); ++i) {
       
  4981             if (alternatives.at(i)->test())
       
  4982                 element->typeTable()->addAlternative(alternatives.at(i));
       
  4983 
       
  4984             if (i == (alternatives.count() - 1)) { // the final one
       
  4985                 if (!alternatives.at(i)->test()) {
       
  4986                     element->typeTable()->setDefaultTypeDefinition(alternatives.at(i));
       
  4987                 } else {
       
  4988                     const XsdAlternative::Ptr alternative(new XsdAlternative());
       
  4989                     if (element->type())
       
  4990                         alternative->setType(element->type());
       
  4991                     else
       
  4992                         m_schemaResolver->addAlternativeType(alternative, element); // add to resolver
       
  4993 
       
  4994                     element->typeTable()->setDefaultTypeDefinition(alternative);
       
  4995                 }
       
  4996             }
       
  4997         }
       
  4998     }
       
  4999 
       
  5000     return term;
       
  5001 }
       
  5002 
       
  5003 XsdIdentityConstraint::Ptr XsdSchemaParser::parseUnique()
       
  5004 {
       
  5005     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Unique, this);
       
  5006 
       
  5007     validateElement(XsdTagScope::Unique);
       
  5008 
       
  5009     const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
       
  5010     constraint->setCategory(XsdIdentityConstraint::Unique);
       
  5011 
       
  5012     // parse attributes
       
  5013     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("unique"));
       
  5014     constraint->setName(objectName);
       
  5015 
       
  5016     validateIdAttribute("unique");
       
  5017 
       
  5018     TagValidationHandler tagValidator(XsdTagScope::Unique, this, m_namePool);
       
  5019 
       
  5020     while (!atEnd()) {
       
  5021         readNext();
       
  5022 
       
  5023         if (isEndElement())
       
  5024             break;
       
  5025 
       
  5026         if (isStartElement()) {
       
  5027             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  5028             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  5029 
       
  5030             tagValidator.validate(token);
       
  5031 
       
  5032             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  5033                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  5034                 constraint->addAnnotation(annotation);
       
  5035             } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) {
       
  5036                 parseSelector(constraint);
       
  5037             } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) {
       
  5038                 parseField(constraint);
       
  5039             } else {
       
  5040                 parseUnknown();
       
  5041             }
       
  5042         }
       
  5043     }
       
  5044 
       
  5045     // add constraint to schema for further checking
       
  5046     addIdentityConstraint(constraint);
       
  5047 
       
  5048     tagValidator.finalize();
       
  5049 
       
  5050     return constraint;
       
  5051 }
       
  5052 
       
  5053 XsdIdentityConstraint::Ptr XsdSchemaParser::parseKey()
       
  5054 {
       
  5055     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Key, this);
       
  5056 
       
  5057     validateElement(XsdTagScope::Key);
       
  5058 
       
  5059     const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
       
  5060     constraint->setCategory(XsdIdentityConstraint::Key);
       
  5061 
       
  5062     // parse attributes
       
  5063     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("key"));
       
  5064     constraint->setName(objectName);
       
  5065 
       
  5066     validateIdAttribute("key");
       
  5067 
       
  5068     TagValidationHandler tagValidator(XsdTagScope::Key, this, m_namePool);
       
  5069 
       
  5070     while (!atEnd()) {
       
  5071         readNext();
       
  5072 
       
  5073         if (isEndElement())
       
  5074             break;
       
  5075 
       
  5076         if (isStartElement()) {
       
  5077             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  5078             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  5079 
       
  5080             tagValidator.validate(token);
       
  5081 
       
  5082             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  5083                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  5084                 constraint->addAnnotation(annotation);
       
  5085             } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) {
       
  5086                 parseSelector(constraint);
       
  5087             } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) {
       
  5088                 parseField(constraint);
       
  5089             } else {
       
  5090                 parseUnknown();
       
  5091             }
       
  5092         }
       
  5093     }
       
  5094 
       
  5095     // add constraint to schema for further checking
       
  5096     addIdentityConstraint(constraint);
       
  5097 
       
  5098     tagValidator.finalize();
       
  5099 
       
  5100     return constraint;
       
  5101 }
       
  5102 
       
  5103 XsdIdentityConstraint::Ptr XsdSchemaParser::parseKeyRef(const XsdElement::Ptr &element)
       
  5104 {
       
  5105     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Keyref, this);
       
  5106 
       
  5107     validateElement(XsdTagScope::KeyRef);
       
  5108 
       
  5109     const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
       
  5110     constraint->setCategory(XsdIdentityConstraint::KeyReference);
       
  5111 
       
  5112     // parse attributes
       
  5113     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("keyref"));
       
  5114     constraint->setName(objectName);
       
  5115 
       
  5116     const QString refer = readQNameAttribute(QString::fromLatin1("refer"), "keyref");
       
  5117     QXmlName referenceName;
       
  5118     convertName(refer, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
       
  5119     m_schemaResolver->addKeyReference(element, constraint, referenceName, currentSourceLocation()); // add to resolver
       
  5120 
       
  5121     validateIdAttribute("keyref");
       
  5122 
       
  5123     TagValidationHandler tagValidator(XsdTagScope::KeyRef, this, m_namePool);
       
  5124 
       
  5125     while (!atEnd()) {
       
  5126         readNext();
       
  5127 
       
  5128         if (isEndElement())
       
  5129             break;
       
  5130 
       
  5131         if (isStartElement()) {
       
  5132             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  5133             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  5134 
       
  5135             tagValidator.validate(token);
       
  5136 
       
  5137             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  5138                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  5139                 constraint->addAnnotation(annotation);
       
  5140             } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) {
       
  5141                 parseSelector(constraint);
       
  5142             } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) {
       
  5143                 parseField(constraint);
       
  5144             } else {
       
  5145                 parseUnknown();
       
  5146             }
       
  5147         }
       
  5148     }
       
  5149 
       
  5150     // add constraint to schema for further checking
       
  5151     addIdentityConstraint(constraint);
       
  5152 
       
  5153     tagValidator.finalize();
       
  5154 
       
  5155     return constraint;
       
  5156 }
       
  5157 
       
  5158 void XsdSchemaParser::parseSelector(const XsdIdentityConstraint::Ptr &ptr)
       
  5159 {
       
  5160     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Selector, this);
       
  5161 
       
  5162     validateElement(XsdTagScope::Selector);
       
  5163 
       
  5164     // parse attributes
       
  5165     const XsdXPathExpression::Ptr expression = readXPathExpression("selector");
       
  5166 
       
  5167     const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathSelector, "selector");
       
  5168     expression->setExpression(xpath);
       
  5169 
       
  5170     ptr->setSelector(expression);
       
  5171 
       
  5172     validateIdAttribute("selector");
       
  5173 
       
  5174     TagValidationHandler tagValidator(XsdTagScope::Selector, this, m_namePool);
       
  5175 
       
  5176     while (!atEnd()) {
       
  5177         readNext();
       
  5178 
       
  5179         if (isEndElement())
       
  5180             break;
       
  5181 
       
  5182         if (isStartElement()) {
       
  5183             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  5184             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  5185 
       
  5186             tagValidator.validate(token);
       
  5187 
       
  5188             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  5189                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  5190                 expression->addAnnotation(annotation);
       
  5191             } else {
       
  5192                 parseUnknown();
       
  5193             }
       
  5194         }
       
  5195     }
       
  5196 
       
  5197     tagValidator.finalize();
       
  5198 }
       
  5199 
       
  5200 void XsdSchemaParser::parseField(const XsdIdentityConstraint::Ptr &ptr)
       
  5201 {
       
  5202     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Field, this);
       
  5203 
       
  5204     validateElement(XsdTagScope::Field);
       
  5205 
       
  5206     // parse attributes
       
  5207     const XsdXPathExpression::Ptr expression = readXPathExpression("field");
       
  5208 
       
  5209     const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathField, "field");
       
  5210     expression->setExpression(xpath);
       
  5211 
       
  5212     ptr->addField(expression);
       
  5213 
       
  5214     validateIdAttribute("field");
       
  5215 
       
  5216     TagValidationHandler tagValidator(XsdTagScope::Field, this, m_namePool);
       
  5217 
       
  5218     while (!atEnd()) {
       
  5219         readNext();
       
  5220 
       
  5221         if (isEndElement())
       
  5222             break;
       
  5223 
       
  5224         if (isStartElement()) {
       
  5225             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  5226             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  5227 
       
  5228             tagValidator.validate(token);
       
  5229 
       
  5230             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  5231                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  5232                 expression->addAnnotation(annotation);
       
  5233             } else {
       
  5234                 parseUnknown();
       
  5235             }
       
  5236         }
       
  5237     }
       
  5238 
       
  5239     tagValidator.finalize();
       
  5240 }
       
  5241 
       
  5242 XsdAlternative::Ptr XsdSchemaParser::parseAlternative()
       
  5243 {
       
  5244     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Alternative, this);
       
  5245 
       
  5246     validateElement(XsdTagScope::Alternative);
       
  5247 
       
  5248     const XsdAlternative::Ptr alternative(new XsdAlternative());
       
  5249 
       
  5250     bool hasTypeSpecified = false;
       
  5251 
       
  5252     if (hasAttribute(QString::fromLatin1("test"))) {
       
  5253         const XsdXPathExpression::Ptr expression = readXPathExpression("alternative");
       
  5254 
       
  5255         const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "alternative");
       
  5256         expression->setExpression(test);
       
  5257 
       
  5258         alternative->setTest(expression);
       
  5259     }
       
  5260 
       
  5261     if (hasAttribute(QString::fromLatin1("type"))) {
       
  5262         const QString type = readQNameAttribute(QString::fromLatin1("type"), "alternative");
       
  5263         QXmlName typeName;
       
  5264         convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
       
  5265         m_schemaResolver->addAlternativeType(alternative, typeName, currentSourceLocation()); // add to resolver
       
  5266 
       
  5267         hasTypeSpecified = true;
       
  5268     }
       
  5269 
       
  5270     validateIdAttribute("alternative");
       
  5271 
       
  5272     TagValidationHandler tagValidator(XsdTagScope::Alternative, this, m_namePool);
       
  5273 
       
  5274     while (!atEnd()) {
       
  5275         readNext();
       
  5276 
       
  5277         if (isEndElement())
       
  5278             break;
       
  5279 
       
  5280         if (isStartElement()) {
       
  5281             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  5282             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  5283 
       
  5284             tagValidator.validate(token);
       
  5285 
       
  5286             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  5287                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  5288                 alternative->addAnnotation(annotation);
       
  5289             } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
       
  5290                 const XsdSimpleType::Ptr type = parseLocalSimpleType();
       
  5291                 alternative->setType(type);
       
  5292 
       
  5293                 // add it to list of anonymous types as well
       
  5294                 addAnonymousType(type);
       
  5295 
       
  5296                 hasTypeSpecified = true;
       
  5297             } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
       
  5298                 const XsdComplexType::Ptr type = parseLocalComplexType();
       
  5299                 alternative->setType(type);
       
  5300 
       
  5301                 // add it to list of anonymous types as well
       
  5302                 addAnonymousType(type);
       
  5303 
       
  5304                 hasTypeSpecified = true;
       
  5305             } else {
       
  5306                 parseUnknown();
       
  5307             }
       
  5308         }
       
  5309     }
       
  5310 
       
  5311     tagValidator.finalize();
       
  5312 
       
  5313     if (!hasTypeSpecified) {
       
  5314         error(QtXmlPatterns::tr("%1 element must have either %2 attribute or %3 or %4 as child element.")
       
  5315                                .arg(formatElement("alternative"))
       
  5316                                .arg(formatAttribute("type"))
       
  5317                                .arg(formatElement("simpleType"))
       
  5318                                .arg(formatElement("complexType")));
       
  5319         return alternative;
       
  5320     }
       
  5321 
       
  5322     return alternative;
       
  5323 }
       
  5324 
       
  5325 XsdNotation::Ptr XsdSchemaParser::parseNotation()
       
  5326 {
       
  5327     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Notation, this);
       
  5328 
       
  5329     validateElement(XsdTagScope::Notation);
       
  5330 
       
  5331     const XsdNotation::Ptr notation(new XsdNotation());
       
  5332 
       
  5333     // parse attributes
       
  5334     const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("notation"));
       
  5335     notation->setName(objectName);
       
  5336 
       
  5337     bool hasOptionalAttribute = false;
       
  5338 
       
  5339     if (hasAttribute(QString::fromLatin1("public"))) {
       
  5340         const QString value = readAttribute(QString::fromLatin1("public"));
       
  5341         if (!value.isEmpty()) {
       
  5342             const DerivedString<TypeToken>::Ptr publicId = DerivedString<TypeToken>::fromLexical(m_namePool, value);
       
  5343             if (publicId->hasError()) {
       
  5344                 attributeContentError("public", "notation", value, BuiltinTypes::xsToken);
       
  5345                 return notation;
       
  5346             }
       
  5347             notation->setPublicId(publicId);
       
  5348         }
       
  5349 
       
  5350         hasOptionalAttribute = true;
       
  5351     }
       
  5352 
       
  5353     if (hasAttribute(QString::fromLatin1("system"))) {
       
  5354         const QString value = readAttribute(QString::fromLatin1("system"));
       
  5355         if (!isValidUri(value)) {
       
  5356             attributeContentError("system", "notation", value, BuiltinTypes::xsAnyURI);
       
  5357             return notation;
       
  5358         }
       
  5359 
       
  5360         if (!value.isEmpty()) {
       
  5361             const AnyURI::Ptr systemId = AnyURI::fromLexical(value);
       
  5362             notation->setSystemId(systemId);
       
  5363         }
       
  5364 
       
  5365         hasOptionalAttribute = true;
       
  5366     }
       
  5367 
       
  5368     if (!hasOptionalAttribute) {
       
  5369         error(QtXmlPatterns::tr("%1 element requires either %2 or %3 attribute.")
       
  5370                                .arg(formatElement("notation"))
       
  5371                                .arg(formatAttribute("public"))
       
  5372                                .arg(formatAttribute("system")));
       
  5373         return notation;
       
  5374     }
       
  5375 
       
  5376     validateIdAttribute("notation");
       
  5377 
       
  5378     TagValidationHandler tagValidator(XsdTagScope::Notation, this, m_namePool);
       
  5379 
       
  5380     while (!atEnd()) {
       
  5381         readNext();
       
  5382 
       
  5383         if (isEndElement())
       
  5384             break;
       
  5385 
       
  5386         if (isCharacters() || isEntityReference()) {
       
  5387             if (!text().toString().trimmed().isEmpty()) {
       
  5388                 error(QtXmlPatterns::tr("Text or entity references not allowed inside %1 element").arg(formatElement("notation.")));
       
  5389                 return notation;
       
  5390             }
       
  5391         }
       
  5392 
       
  5393         if (isStartElement()) {
       
  5394             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  5395             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  5396 
       
  5397             tagValidator.validate(token);
       
  5398 
       
  5399             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  5400                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  5401                 notation->addAnnotation(annotation);
       
  5402             } else {
       
  5403                 parseUnknown();
       
  5404             }
       
  5405         }
       
  5406     }
       
  5407 
       
  5408     tagValidator.finalize();
       
  5409 
       
  5410     return notation;
       
  5411 }
       
  5412 
       
  5413 XsdWildcard::Ptr XsdSchemaParser::parseAny(const XsdParticle::Ptr &particle)
       
  5414 {
       
  5415     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Any, this);
       
  5416 
       
  5417     validateElement(XsdTagScope::Any);
       
  5418 
       
  5419     const XsdWildcard::Ptr wildcard(new XsdWildcard());
       
  5420 
       
  5421     // parse attributes
       
  5422     if (!parseMinMaxConstraint(particle, "any")) {
       
  5423         return wildcard;
       
  5424     }
       
  5425 
       
  5426     if (hasAttribute(QString::fromLatin1("namespace"))) {
       
  5427         const QSet<QString> values = readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
       
  5428         if ((values.contains(QString::fromLatin1("##any")) || values.contains(QString::fromLatin1("##other"))) && values.count() != 1) {
       
  5429             error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs.")
       
  5430                                    .arg(formatAttribute("namespace"))
       
  5431                                    .arg(formatElement("any"))
       
  5432                                    .arg(formatData("##any"))
       
  5433                                    .arg(formatData("##other")));
       
  5434             return wildcard;
       
  5435         }
       
  5436 
       
  5437         if (values.contains(QString::fromLatin1("##any"))) {
       
  5438             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
       
  5439         } else if (values.contains(QString::fromLatin1("##other"))) {
       
  5440             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
       
  5441             if (!m_targetNamespace.isEmpty())
       
  5442                 wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << m_targetNamespace);
       
  5443             else
       
  5444                 wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
       
  5445         } else {
       
  5446             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
       
  5447             QStringList newValues = values.toList();
       
  5448 
       
  5449             // replace the ##targetNamespace entry
       
  5450             for (int i = 0; i < newValues.count(); ++i) {
       
  5451                 if (newValues.at(i) == QString::fromLatin1("##targetNamespace")) {
       
  5452                     if (!m_targetNamespace.isEmpty())
       
  5453                         newValues[i] = m_targetNamespace;
       
  5454                     else
       
  5455                         newValues[i] = XsdWildcard::absentNamespace();
       
  5456                 } else if (newValues.at(i) == QString::fromLatin1("##local")) {
       
  5457                     newValues[i] = XsdWildcard::absentNamespace();
       
  5458                 }
       
  5459             }
       
  5460 
       
  5461             // check for invalid URIs
       
  5462             for (int i = 0; i < newValues.count(); ++i) {
       
  5463                 const QString stringValue = newValues.at(i);
       
  5464                 if (stringValue == XsdWildcard::absentNamespace())
       
  5465                     continue;
       
  5466 
       
  5467                 if (!isValidUri(stringValue)) {
       
  5468                     attributeContentError("namespace", "any", stringValue, BuiltinTypes::xsAnyURI);
       
  5469                     return wildcard;
       
  5470                 }
       
  5471             }
       
  5472 
       
  5473             wildcard->namespaceConstraint()->setNamespaces(newValues.toSet());
       
  5474         }
       
  5475     } else {
       
  5476         wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
       
  5477     }
       
  5478 
       
  5479     if (hasAttribute(QString::fromLatin1("processContents"))) {
       
  5480         const QString value = readAttribute(QString::fromLatin1("processContents"));
       
  5481         if (value != QString::fromLatin1("lax") &&
       
  5482             value != QString::fromLatin1("skip") &&
       
  5483             value != QString::fromLatin1("strict")) {
       
  5484             attributeContentError("processContents", "any", value);
       
  5485             return wildcard;
       
  5486         }
       
  5487 
       
  5488         if (value == QString::fromLatin1("lax")) {
       
  5489             wildcard->setProcessContents(XsdWildcard::Lax);
       
  5490         } else if (value == QString::fromLatin1("skip")) {
       
  5491             wildcard->setProcessContents(XsdWildcard::Skip);
       
  5492         } else if (value == QString::fromLatin1("strict")) {
       
  5493             wildcard->setProcessContents(XsdWildcard::Strict);
       
  5494         }
       
  5495     } else {
       
  5496         wildcard->setProcessContents(XsdWildcard::Strict);
       
  5497     }
       
  5498 
       
  5499     validateIdAttribute("any");
       
  5500 
       
  5501     TagValidationHandler tagValidator(XsdTagScope::Any, this, m_namePool);
       
  5502 
       
  5503     while (!atEnd()) {
       
  5504         readNext();
       
  5505 
       
  5506         if (isEndElement())
       
  5507             break;
       
  5508 
       
  5509         if (isStartElement()) {
       
  5510             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  5511             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  5512 
       
  5513             tagValidator.validate(token);
       
  5514 
       
  5515             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  5516                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  5517                 wildcard->addAnnotation(annotation);
       
  5518             } else {
       
  5519                 parseUnknown();
       
  5520             }
       
  5521         }
       
  5522     }
       
  5523 
       
  5524     tagValidator.finalize();
       
  5525 
       
  5526     return wildcard;
       
  5527 }
       
  5528 
       
  5529 XsdWildcard::Ptr XsdSchemaParser::parseAnyAttribute()
       
  5530 {
       
  5531     const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AnyAttribute, this);
       
  5532 
       
  5533     validateElement(XsdTagScope::AnyAttribute);
       
  5534 
       
  5535     const XsdWildcard::Ptr wildcard(new XsdWildcard());
       
  5536 
       
  5537     // parse attributes
       
  5538     if (hasAttribute(QString::fromLatin1("namespace"))) {
       
  5539         const QSet<QString> values = readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
       
  5540         if ((values.contains(QString::fromLatin1("##any")) || values.contains(QString::fromLatin1("##other"))) && values.count() != 1) {
       
  5541             error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs.")
       
  5542                                    .arg(formatAttribute("namespace"))
       
  5543                                    .arg(formatElement("anyAttribute"))
       
  5544                                    .arg(formatData("##any"))
       
  5545                                    .arg(formatData("##other")));
       
  5546             return wildcard;
       
  5547         }
       
  5548 
       
  5549         if (values.contains(QString::fromLatin1("##any"))) {
       
  5550             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
       
  5551         } else if (values.contains(QString::fromLatin1("##other"))) {
       
  5552             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
       
  5553             if (!m_targetNamespace.isEmpty())
       
  5554                 wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << m_targetNamespace);
       
  5555             else
       
  5556                 wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
       
  5557         } else {
       
  5558             wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
       
  5559             QStringList newValues = values.toList();
       
  5560 
       
  5561             // replace the ##targetNamespace entry
       
  5562             for (int i = 0; i < newValues.count(); ++i) {
       
  5563                 if (newValues.at(i) == QString::fromLatin1("##targetNamespace")) {
       
  5564                     if (!m_targetNamespace.isEmpty())
       
  5565                         newValues[i] = m_targetNamespace;
       
  5566                     else
       
  5567                         newValues[i] = XsdWildcard::absentNamespace();
       
  5568                 } else if (newValues.at(i) == QString::fromLatin1("##local")) {
       
  5569                     newValues[i] = XsdWildcard::absentNamespace();
       
  5570                 }
       
  5571             }
       
  5572 
       
  5573             // check for invalid URIs
       
  5574             for (int i = 0; i < newValues.count(); ++i) {
       
  5575                 const QString stringValue = newValues.at(i);
       
  5576                 if (stringValue == XsdWildcard::absentNamespace())
       
  5577                     continue;
       
  5578 
       
  5579                 if (!isValidUri(stringValue)) {
       
  5580                     attributeContentError("namespace", "anyAttribute", stringValue, BuiltinTypes::xsAnyURI);
       
  5581                     return wildcard;
       
  5582                 }
       
  5583             }
       
  5584 
       
  5585             wildcard->namespaceConstraint()->setNamespaces(newValues.toSet());
       
  5586         }
       
  5587     } else {
       
  5588         wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
       
  5589     }
       
  5590 
       
  5591     if (hasAttribute(QString::fromLatin1("processContents"))) {
       
  5592         const QString value = readAttribute(QString::fromLatin1("processContents"));
       
  5593         if (value != QString::fromLatin1("lax") &&
       
  5594             value != QString::fromLatin1("skip") &&
       
  5595             value != QString::fromLatin1("strict")) {
       
  5596             attributeContentError("processContents", "anyAttribute", value);
       
  5597             return wildcard;
       
  5598         }
       
  5599 
       
  5600         if (value == QString::fromLatin1("lax")) {
       
  5601             wildcard->setProcessContents(XsdWildcard::Lax);
       
  5602         } else if (value == QString::fromLatin1("skip")) {
       
  5603             wildcard->setProcessContents(XsdWildcard::Skip);
       
  5604         } else if (value == QString::fromLatin1("strict")) {
       
  5605             wildcard->setProcessContents(XsdWildcard::Strict);
       
  5606         }
       
  5607     } else {
       
  5608         wildcard->setProcessContents(XsdWildcard::Strict);
       
  5609     }
       
  5610 
       
  5611     validateIdAttribute("anyAttribute");
       
  5612 
       
  5613     TagValidationHandler tagValidator(XsdTagScope::AnyAttribute, this, m_namePool);
       
  5614 
       
  5615     while (!atEnd()) {
       
  5616         readNext();
       
  5617 
       
  5618         if (isEndElement())
       
  5619             break;
       
  5620 
       
  5621         if (isStartElement()) {
       
  5622             const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
       
  5623             const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
       
  5624 
       
  5625             tagValidator.validate(token);
       
  5626 
       
  5627             if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
       
  5628                 const XsdAnnotation::Ptr annotation = parseAnnotation();
       
  5629                 wildcard->addAnnotation(annotation);
       
  5630             } else {
       
  5631                 parseUnknown();
       
  5632             }
       
  5633         }
       
  5634     }
       
  5635 
       
  5636     tagValidator.finalize();
       
  5637 
       
  5638     return wildcard;
       
  5639 }
       
  5640 
       
  5641 
       
  5642 void XsdSchemaParser::parseUnknownDocumentation()
       
  5643 {
       
  5644     Q_ASSERT(isStartElement());
       
  5645     m_namespaceSupport.pushContext();
       
  5646     m_namespaceSupport.setPrefixes(namespaceDeclarations());
       
  5647 
       
  5648     while (!atEnd()) {
       
  5649         readNext();
       
  5650 
       
  5651         if (isEndElement())
       
  5652             break;
       
  5653 
       
  5654         if (isStartElement())
       
  5655             parseUnknownDocumentation();
       
  5656     }
       
  5657 
       
  5658     m_namespaceSupport.popContext();
       
  5659 }
       
  5660 
       
  5661 void XsdSchemaParser::parseUnknown()
       
  5662 {
       
  5663     Q_ASSERT(isStartElement());
       
  5664     m_namespaceSupport.pushContext();
       
  5665     m_namespaceSupport.setPrefixes(namespaceDeclarations());
       
  5666 
       
  5667     error(QtXmlPatterns::tr("%1 element is not allowed in this context.").arg(formatElement(name().toString())));
       
  5668 
       
  5669     while (!atEnd()) {
       
  5670         readNext();
       
  5671 
       
  5672         if (isEndElement())
       
  5673             break;
       
  5674 
       
  5675         if (isStartElement())
       
  5676             parseUnknown();
       
  5677     }
       
  5678 
       
  5679     m_namespaceSupport.popContext();
       
  5680 }
       
  5681 
       
  5682 bool XsdSchemaParser::parseMinMaxConstraint(const XsdParticle::Ptr &particle, const char *elementName)
       
  5683 {
       
  5684     if (hasAttribute(QString::fromLatin1("minOccurs"))) {
       
  5685         const QString value = readAttribute(QString::fromLatin1("minOccurs"));
       
  5686 
       
  5687         DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
       
  5688         if (integer->hasError()) {
       
  5689             attributeContentError("minOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger);
       
  5690             return false;
       
  5691         } else {
       
  5692             particle->setMinimumOccurs(integer->as< DerivedInteger<TypeNonNegativeInteger> >()->storedValue());
       
  5693         }
       
  5694     } else {
       
  5695         particle->setMinimumOccurs(1);
       
  5696     }
       
  5697 
       
  5698     if (hasAttribute(QString::fromLatin1("maxOccurs"))) {
       
  5699         const QString value = readAttribute(QString::fromLatin1("maxOccurs"));
       
  5700 
       
  5701         if (value == QString::fromLatin1("unbounded")) {
       
  5702             particle->setMaximumOccursUnbounded(true);
       
  5703         } else {
       
  5704             particle->setMaximumOccursUnbounded(false);
       
  5705             DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
       
  5706             if (integer->hasError()) {
       
  5707                 attributeContentError("maxOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger);
       
  5708                 return false;
       
  5709             } else {
       
  5710                 particle->setMaximumOccurs(integer->as< DerivedInteger<TypeNonNegativeInteger> >()->storedValue());
       
  5711             }
       
  5712         }
       
  5713     } else {
       
  5714         particle->setMaximumOccursUnbounded(false);
       
  5715         particle->setMaximumOccurs(1);
       
  5716     }
       
  5717 
       
  5718     if (!particle->maximumOccursUnbounded()) {
       
  5719         if (particle->maximumOccurs() < particle->minimumOccurs()) {
       
  5720             error(QtXmlPatterns::tr("%1 attribute of %2 element has larger value than %3 attribute.")
       
  5721                                    .arg(formatAttribute("minOccurs"))
       
  5722                                    .arg(formatElement(elementName))
       
  5723                                    .arg(formatAttribute("maxOccurs")));
       
  5724             return false;
       
  5725         }
       
  5726     }
       
  5727 
       
  5728     return true;
       
  5729 }
       
  5730 
       
  5731 QSourceLocation XsdSchemaParser::currentSourceLocation() const
       
  5732 {
       
  5733     QSourceLocation location;
       
  5734     location.setLine(lineNumber());
       
  5735     location.setColumn(columnNumber());
       
  5736     location.setUri(m_documentURI);
       
  5737 
       
  5738     return location;
       
  5739 }
       
  5740 
       
  5741 void XsdSchemaParser::convertName(const QString &qualifiedName, NamespaceSupport::NameType type, QXmlName &name)
       
  5742 {
       
  5743     bool result = m_namespaceSupport.processName(qualifiedName, type, name);
       
  5744     if (!result) {
       
  5745         error(QtXmlPatterns::tr("Prefix of qualified name %1 is not defined.").arg(formatKeyword(qualifiedName)));
       
  5746     }
       
  5747 }
       
  5748 
       
  5749 QString XsdSchemaParser::readNameAttribute(const char *elementName)
       
  5750 {
       
  5751     const QString value = readAttribute(QString::fromLatin1("name")).simplified();
       
  5752     if (!QXmlUtils::isNCName(value)) {
       
  5753         attributeContentError("name", elementName, value, BuiltinTypes::xsNCName);
       
  5754         return QString();
       
  5755     } else {
       
  5756         return value;
       
  5757     }
       
  5758 }
       
  5759 
       
  5760 QString XsdSchemaParser::readQNameAttribute(const QString &typeAttribute, const char *elementName)
       
  5761 {
       
  5762     const QString value = readAttribute(typeAttribute).simplified();
       
  5763     if (!XPathHelper::isQName(value)) {
       
  5764         attributeContentError(typeAttribute.toLatin1(), elementName, value, BuiltinTypes::xsQName);
       
  5765         return QString();
       
  5766     } else {
       
  5767         return value;
       
  5768     }
       
  5769 }
       
  5770 
       
  5771 QString XsdSchemaParser::readNamespaceAttribute(const QString &attributeName, const char *elementName)
       
  5772 {
       
  5773     const QString value = readAttribute(attributeName);
       
  5774     if (value.isEmpty()) {
       
  5775         attributeContentError(attributeName.toLatin1(), elementName, value, BuiltinTypes::xsAnyURI);
       
  5776         return QString();
       
  5777     }
       
  5778 
       
  5779     return value;
       
  5780 }
       
  5781 
       
  5782 SchemaType::DerivationConstraints XsdSchemaParser::readDerivationConstraintAttribute(const SchemaType::DerivationConstraints &allowedConstraints, const char *elementName)
       
  5783 {
       
  5784     // first convert the flags into strings for easier comparision
       
  5785     QSet<QString> allowedContent;
       
  5786     if (allowedConstraints & SchemaType::RestrictionConstraint)
       
  5787         allowedContent.insert(QString::fromLatin1("restriction"));
       
  5788     if (allowedConstraints & SchemaType::ExtensionConstraint)
       
  5789         allowedContent.insert(QString::fromLatin1("extension"));
       
  5790     if (allowedConstraints & SchemaType::ListConstraint)
       
  5791         allowedContent.insert(QString::fromLatin1("list"));
       
  5792     if (allowedConstraints & SchemaType::UnionConstraint)
       
  5793         allowedContent.insert(QString::fromLatin1("union"));
       
  5794 
       
  5795     // read content from the attribute if available, otherwise use the default definitions from the schema tag
       
  5796     QString content;
       
  5797     if (hasAttribute(QString::fromLatin1("final"))) {
       
  5798         content = readAttribute(QString::fromLatin1("final"));
       
  5799 
       
  5800         // split string into list to validate the content of the attribute
       
  5801         const QStringList values = content.split(QLatin1Char(' '), QString::SkipEmptyParts);
       
  5802         for (int i = 0; i < values.count(); i++) {
       
  5803             const QString value = values.at(i);
       
  5804             if (!allowedContent.contains(value) && (value != QString::fromLatin1("#all"))) {
       
  5805                 attributeContentError("final", elementName, value);
       
  5806                 return SchemaType::DerivationConstraints();
       
  5807             }
       
  5808 
       
  5809             if ((value == QString::fromLatin1("#all")) && values.count() != 1) {
       
  5810                 error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values.")
       
  5811                                        .arg(formatAttribute("final"))
       
  5812                                        .arg(formatElement(elementName))
       
  5813                                        .arg(formatData("#all")));
       
  5814                 return SchemaType::DerivationConstraints();
       
  5815             }
       
  5816         }
       
  5817     } else {
       
  5818         // content of the default value has been validated in parseSchema already
       
  5819         content = m_finalDefault;
       
  5820     }
       
  5821 
       
  5822     QSet<QString> contentSet = content.split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
       
  5823 
       
  5824     // if the '#all' tag is defined, we return all allowed values
       
  5825     if (contentSet.contains(QString::fromLatin1("#all"))) {
       
  5826         return allowedConstraints;
       
  5827     } else { // return the values from content set that intersects with the allowed values
       
  5828         contentSet.intersect(allowedContent);
       
  5829 
       
  5830         SchemaType::DerivationConstraints constraints;
       
  5831 
       
  5832         if (contentSet.contains(QString::fromLatin1("restriction")))
       
  5833             constraints |= SchemaType::RestrictionConstraint;
       
  5834         if (contentSet.contains(QString::fromLatin1("extension")))
       
  5835             constraints |= SchemaType::ExtensionConstraint;
       
  5836         if (contentSet.contains(QString::fromLatin1("list")))
       
  5837             constraints |= SchemaType::ListConstraint;
       
  5838         if (contentSet.contains(QString::fromLatin1("union")))
       
  5839             constraints |= SchemaType::UnionConstraint;
       
  5840 
       
  5841         return constraints;
       
  5842     }
       
  5843 }
       
  5844 
       
  5845 NamedSchemaComponent::BlockingConstraints XsdSchemaParser::readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints &allowedConstraints, const char *elementName)
       
  5846 {
       
  5847     // first convert the flags into strings for easier comparision
       
  5848     QSet<QString> allowedContent;
       
  5849     if (allowedConstraints & NamedSchemaComponent::RestrictionConstraint)
       
  5850         allowedContent.insert(QString::fromLatin1("restriction"));
       
  5851     if (allowedConstraints & NamedSchemaComponent::ExtensionConstraint)
       
  5852         allowedContent.insert(QString::fromLatin1("extension"));
       
  5853     if (allowedConstraints & NamedSchemaComponent::SubstitutionConstraint)
       
  5854         allowedContent.insert(QString::fromLatin1("substitution"));
       
  5855 
       
  5856     // read content from the attribute if available, otherwise use the default definitions from the schema tag
       
  5857     QString content;
       
  5858     if (hasAttribute(QString::fromLatin1("block"))) {
       
  5859         content = readAttribute(QString::fromLatin1("block"));
       
  5860 
       
  5861         // split string into list to validate the content of the attribute
       
  5862         const QStringList values = content.split(QLatin1Char(' '), QString::SkipEmptyParts);
       
  5863         for (int i = 0; i < values.count(); i++) {
       
  5864             const QString value = values.at(i);
       
  5865             if (!allowedContent.contains(value) && (value != QString::fromLatin1("#all"))) {
       
  5866                 attributeContentError("block", elementName, value);
       
  5867                 return NamedSchemaComponent::BlockingConstraints();
       
  5868             }
       
  5869 
       
  5870             if ((value == QString::fromLatin1("#all")) && values.count() != 1) {
       
  5871                 error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values.")
       
  5872                                        .arg(formatAttribute("block"))
       
  5873                                        .arg(formatElement(elementName))
       
  5874                                        .arg(formatData("#all")));
       
  5875                 return NamedSchemaComponent::BlockingConstraints();
       
  5876             }
       
  5877         }
       
  5878     } else {
       
  5879         // content of the default value has been validated in parseSchema already
       
  5880         content = m_blockDefault;
       
  5881     }
       
  5882 
       
  5883     QSet<QString> contentSet = content.split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
       
  5884 
       
  5885     // if the '#all' tag is defined, we return all allowed values
       
  5886     if (contentSet.contains(QString::fromLatin1("#all"))) {
       
  5887         return allowedConstraints;
       
  5888     } else { // return the values from content set that intersects with the allowed values
       
  5889         contentSet.intersect(allowedContent);
       
  5890 
       
  5891         NamedSchemaComponent::BlockingConstraints constraints;
       
  5892 
       
  5893         if (contentSet.contains(QString::fromLatin1("restriction")))
       
  5894             constraints |= NamedSchemaComponent::RestrictionConstraint;
       
  5895         if (contentSet.contains(QString::fromLatin1("extension")))
       
  5896             constraints |= NamedSchemaComponent::ExtensionConstraint;
       
  5897         if (contentSet.contains(QString::fromLatin1("substitution")))
       
  5898             constraints |= NamedSchemaComponent::SubstitutionConstraint;
       
  5899 
       
  5900         return constraints;
       
  5901     }
       
  5902 }
       
  5903 
       
  5904 XsdXPathExpression::Ptr XsdSchemaParser::readXPathExpression(const char *elementName)
       
  5905 {
       
  5906     const XsdXPathExpression::Ptr expression(new XsdXPathExpression());
       
  5907 
       
  5908     const QList<QXmlName> namespaceBindings = m_namespaceSupport.namespaceBindings();
       
  5909     QXmlName emptyName;
       
  5910     for (int i = 0; i < namespaceBindings.count(); ++i) {
       
  5911         if (namespaceBindings.at(i).prefix() == StandardPrefixes::empty)
       
  5912             emptyName = namespaceBindings.at(i);
       
  5913     }
       
  5914 
       
  5915     expression->setNamespaceBindings(namespaceBindings);
       
  5916 
       
  5917     QString xpathDefaultNamespace;
       
  5918     if (hasAttribute(QString::fromLatin1("xpathDefaultNamespace"))) {
       
  5919         xpathDefaultNamespace = readAttribute(QString::fromLatin1("xpathDefaultNamespace"));
       
  5920         if (xpathDefaultNamespace != QString::fromLatin1("##defaultNamespace") &&
       
  5921             xpathDefaultNamespace != QString::fromLatin1("##targetNamespace") &&
       
  5922             xpathDefaultNamespace != QString::fromLatin1("##local")) {
       
  5923             if (!isValidUri(xpathDefaultNamespace)) {
       
  5924                 attributeContentError("xpathDefaultNamespace", elementName, xpathDefaultNamespace, BuiltinTypes::xsAnyURI);
       
  5925                 return expression;
       
  5926             }
       
  5927         }
       
  5928     } else {
       
  5929         xpathDefaultNamespace = m_xpathDefaultNamespace;
       
  5930     }
       
  5931 
       
  5932     AnyURI::Ptr namespaceURI;
       
  5933     if (xpathDefaultNamespace == QString::fromLatin1("##defaultNamespace")) {
       
  5934         if (!emptyName.isNull())
       
  5935             namespaceURI = AnyURI::fromLexical(m_namePool->stringForNamespace(emptyName.namespaceURI()));
       
  5936     } else if (xpathDefaultNamespace == QString::fromLatin1("##targetNamespace")) {
       
  5937         if (!m_targetNamespace.isEmpty())
       
  5938             namespaceURI = AnyURI::fromLexical(m_targetNamespace);
       
  5939     } else if (xpathDefaultNamespace == QString::fromLatin1("##local")) {
       
  5940         // it is absent
       
  5941     } else {
       
  5942         namespaceURI = AnyURI::fromLexical(xpathDefaultNamespace);
       
  5943     }
       
  5944     if (namespaceURI) {
       
  5945         if (namespaceURI->hasError()) {
       
  5946             attributeContentError("xpathDefaultNamespace", elementName, xpathDefaultNamespace, BuiltinTypes::xsAnyURI);
       
  5947             return expression;
       
  5948         }
       
  5949 
       
  5950         expression->setDefaultNamespace(namespaceURI);
       
  5951     }
       
  5952 
       
  5953     //TODO: read the base uri if qmaintaining reader support it
       
  5954 
       
  5955     return expression;
       
  5956 }
       
  5957 
       
  5958 QString XsdSchemaParser::readXPathAttribute(const QString &attributeName, XPathType type,  const char *elementName)
       
  5959 {
       
  5960     const QString value = readAttribute(attributeName);
       
  5961     if (value.isEmpty() || value.startsWith(QLatin1Char('/'))) {
       
  5962         attributeContentError(attributeName.toLatin1(), elementName, value);
       
  5963         return QString();
       
  5964     }
       
  5965 
       
  5966     QXmlNamePool namePool(m_namePool.data());
       
  5967 
       
  5968     QXmlQuery::QueryLanguage language = QXmlQuery::XPath20;
       
  5969     switch (type) {
       
  5970         case XPath20: language = QXmlQuery::XPath20; break;
       
  5971         case XPathSelector: language = QXmlQuery::XmlSchema11IdentityConstraintSelector; break;
       
  5972         case XPathField: language = QXmlQuery::XmlSchema11IdentityConstraintField; break;
       
  5973     };
       
  5974 
       
  5975     QXmlQuery query(language, namePool);
       
  5976     QXmlQueryPrivate *queryPrivate = query.d;
       
  5977 
       
  5978     const QList<QXmlName> namespaceBindings = m_namespaceSupport.namespaceBindings();
       
  5979     for (int i = 0; i < namespaceBindings.count(); ++i) {
       
  5980         if (!namespaceBindings.at(i).prefix() == StandardPrefixes::empty)
       
  5981             queryPrivate->addAdditionalNamespaceBinding(namespaceBindings.at(i));
       
  5982     }
       
  5983 
       
  5984     query.setQuery(value, m_documentURI);
       
  5985     if (!query.isValid()) {
       
  5986         attributeContentError(attributeName.toLatin1(), elementName, value);
       
  5987         return QString();
       
  5988     }
       
  5989 
       
  5990     return value;
       
  5991 }
       
  5992 
       
  5993 void XsdSchemaParser::validateIdAttribute(const char *elementName)
       
  5994 {
       
  5995     if (hasAttribute(QString::fromLatin1("id"))) {
       
  5996         const QString value = readAttribute(QString::fromLatin1("id"));
       
  5997         DerivedString<TypeID>::Ptr id = DerivedString<TypeID>::fromLexical(m_namePool, value);
       
  5998         if (id->hasError()) {
       
  5999             attributeContentError("id", elementName, value, BuiltinTypes::xsID);
       
  6000         } else {
       
  6001             if (m_idCache->hasId(value)) {
       
  6002                 error(QtXmlPatterns::tr("Component with ID %1 has been defined previously.").arg(formatData(value)));
       
  6003             } else {
       
  6004                 m_idCache->addId(value);
       
  6005             }
       
  6006         }
       
  6007     }
       
  6008 }
       
  6009 
       
  6010 bool XsdSchemaParser::isSchemaTag(XsdSchemaToken::NodeName tag, XsdSchemaToken::NodeName token, XsdSchemaToken::NodeName namespaceToken) const
       
  6011 {
       
  6012     return ((tag == token) && (namespaceToken == XsdSchemaToken::XML_NS_SCHEMA_URI));
       
  6013 }
       
  6014 
       
  6015 void XsdSchemaParser::addElement(const XsdElement::Ptr &element)
       
  6016 {
       
  6017     const QXmlName objectName = element->name(m_namePool);
       
  6018     if (m_schema->element(objectName)) {
       
  6019         error(QtXmlPatterns::tr("Element %1 already defined.").arg(formatElement(m_namePool->displayName(objectName))));
       
  6020     } else {
       
  6021         m_schema->addElement(element);
       
  6022         m_componentLocationHash.insert(element, currentSourceLocation());
       
  6023     }
       
  6024 }
       
  6025 
       
  6026 void XsdSchemaParser::addAttribute(const XsdAttribute::Ptr &attribute)
       
  6027 {
       
  6028     const QXmlName objectName = attribute->name(m_namePool);
       
  6029     if (m_schema->attribute(objectName)) {
       
  6030         error(QtXmlPatterns::tr("Attribute %1 already defined.").arg(formatAttribute(m_namePool->displayName(objectName))));
       
  6031     } else {
       
  6032         m_schema->addAttribute(attribute);
       
  6033         m_componentLocationHash.insert(attribute, currentSourceLocation());
       
  6034     }
       
  6035 }
       
  6036 
       
  6037 void XsdSchemaParser::addType(const SchemaType::Ptr &type)
       
  6038 {
       
  6039     // we don't import redefinitions of builtin types, that just causes problems
       
  6040     if (m_builtinTypeNames.contains(type->name(m_namePool)))
       
  6041         return;
       
  6042 
       
  6043     const QXmlName objectName = type->name(m_namePool);
       
  6044     if (m_schema->type(objectName)) {
       
  6045         error(QtXmlPatterns::tr("Type %1 already defined.").arg(formatType(m_namePool, objectName)));
       
  6046     } else {
       
  6047         m_schema->addType(type);
       
  6048         if (type->isSimpleType())
       
  6049             m_componentLocationHash.insert(XsdSimpleType::Ptr(type), currentSourceLocation());
       
  6050         else
       
  6051             m_componentLocationHash.insert(XsdComplexType::Ptr(type), currentSourceLocation());
       
  6052     }
       
  6053 }
       
  6054 
       
  6055 void XsdSchemaParser::addAnonymousType(const SchemaType::Ptr &type)
       
  6056 {
       
  6057     m_schema->addAnonymousType(type);
       
  6058     if (type->isSimpleType())
       
  6059         m_componentLocationHash.insert(XsdSimpleType::Ptr(type), currentSourceLocation());
       
  6060     else
       
  6061         m_componentLocationHash.insert(XsdComplexType::Ptr(type), currentSourceLocation());
       
  6062 }
       
  6063 
       
  6064 void XsdSchemaParser::addAttributeGroup(const XsdAttributeGroup::Ptr &group)
       
  6065 {
       
  6066     const QXmlName objectName = group->name(m_namePool);
       
  6067     if (m_schema->attributeGroup(objectName)) {
       
  6068         error(QtXmlPatterns::tr("Attribute group %1 already defined.").arg(formatKeyword(m_namePool, objectName)));
       
  6069     } else {
       
  6070         m_schema->addAttributeGroup(group);
       
  6071         m_componentLocationHash.insert(group, currentSourceLocation());
       
  6072     }
       
  6073 }
       
  6074 
       
  6075 void XsdSchemaParser::addElementGroup(const XsdModelGroup::Ptr &group)
       
  6076 {
       
  6077     const QXmlName objectName = group->name(m_namePool);
       
  6078     if (m_schema->elementGroup(objectName)) {
       
  6079         error(QtXmlPatterns::tr("Element group %1 already defined.").arg(formatKeyword(m_namePool, objectName)));
       
  6080     } else {
       
  6081         m_schema->addElementGroup(group);
       
  6082         m_componentLocationHash.insert(group, currentSourceLocation());
       
  6083     }
       
  6084 }
       
  6085 
       
  6086 void XsdSchemaParser::addNotation(const XsdNotation::Ptr &notation)
       
  6087 {
       
  6088     const QXmlName objectName = notation->name(m_namePool);
       
  6089     if (m_schema->notation(objectName)) {
       
  6090         error(QtXmlPatterns::tr("Notation %1 already defined.").arg(formatKeyword(m_namePool, objectName)));
       
  6091     } else {
       
  6092         m_schema->addNotation(notation);
       
  6093         m_componentLocationHash.insert(notation, currentSourceLocation());
       
  6094     }
       
  6095 }
       
  6096 
       
  6097 void XsdSchemaParser::addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint)
       
  6098 {
       
  6099     const QXmlName objectName = constraint->name(m_namePool);
       
  6100     if (m_schema->identityConstraint(objectName)) {
       
  6101         error(QtXmlPatterns::tr("Identity constraint %1 already defined.").arg(formatKeyword(m_namePool, objectName)));
       
  6102     } else {
       
  6103         m_schema->addIdentityConstraint(constraint);
       
  6104         m_componentLocationHash.insert(constraint, currentSourceLocation());
       
  6105     }
       
  6106 }
       
  6107 
       
  6108 void XsdSchemaParser::addFacet(const XsdFacet::Ptr &facet, XsdFacet::Hash &facets, const SchemaType::Ptr &type)
       
  6109 {
       
  6110     // @see http://www.w3.org/TR/xmlschema-2/#src-single-facet-value
       
  6111     if (facets.contains(facet->type())) {
       
  6112         error(QtXmlPatterns::tr("Duplicated facets in simple type %1.").arg(formatType(m_namePool, type)));
       
  6113         return;
       
  6114     }
       
  6115 
       
  6116     facets.insert(facet->type(), facet);
       
  6117 }
       
  6118 
       
  6119 QT_END_NAMESPACE