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