Fixing some GCC warnings
[qt-netbsd.git] / src / xmlpatterns / schema / qxsdschemaparser.cpp
blob41c6b82bf1a70b16730d87ef8c7457459c1e03f6
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.
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
42 #include "qxsdschemaparser_p.h"
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"
58 #include <QtCore/QFile>
59 #include <QtXmlPatterns/QXmlQuery>
61 QT_BEGIN_NAMESPACE
63 /**
64 * @page schema_overview Overview
65 * @section structure_and_components Structure and Components
67 * The schema validator code consists of 4 major components
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>
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>
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>
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>
100 * @ingroup Patternist_schema
103 using namespace QPatternist;
105 namespace QPatternist
109 * @short A helper class for automatically handling namespace scopes of elements.
111 * This class should be instantiated at the beginning of each parse XYZ method.
113 class ElementNamespaceHandler
115 public:
117 * Creates a new element namespace handler object.
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.
122 ElementNamespaceHandler(const XsdSchemaToken::NodeName &tag, XsdSchemaParser *parser)
123 : m_parser(parser)
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());
132 * Destroys the element namespace handler object.
134 * It destroys the local namespace context.
136 ~ElementNamespaceHandler()
138 m_parser->m_namespaceSupport.popContext();
141 private:
142 XsdSchemaParser *m_parser;
146 * A helper class that checks for the right occurrence of
147 * xml tags with the help of a DFA.
149 class TagValidationHandler
151 public:
152 TagValidationHandler(XsdTagScope::Type tag, XsdSchemaParser *parser, const NamePool::Ptr &namePool)
153 : m_parser(parser), m_machine(namePool)
155 Q_ASSERT(m_parser->m_stateMachines.contains(tag));
157 m_machine = m_parser->m_stateMachines.value(tag);
158 m_machine.reset();
161 void validate(XsdSchemaToken::NodeName token)
163 if (token == XsdSchemaToken::NoKeyword) {
164 const QList<XsdSchemaToken::NodeName> tokens = m_machine.possibleTransitions();
166 QStringList elementNames;
167 for (int i = 0; i < tokens.count(); ++i)
168 elementNames.append(formatElement(XsdSchemaToken::toString(tokens.at(i))));
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;
176 if (!m_machine.proceed(token)) {
177 const QList<XsdSchemaToken::NodeName> tokens = m_machine.possibleTransitions();
179 QStringList elementNames;
180 for (int i = 0; i < tokens.count(); ++i)
181 elementNames.append(formatElement(XsdSchemaToken::toString(tokens.at(i))));
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;
190 void finalize() const
192 if (!m_machine.inEndState()) {
193 const QList<XsdSchemaToken::NodeName> tokens = m_machine.possibleTransitions();
195 QStringList elementNames;
196 for (int i = 0; i < tokens.count(); ++i)
197 elementNames.append(formatElement(XsdSchemaToken::toString(tokens.at(i))));
199 m_parser->error(QtXmlPatterns::tr("Child element is missing in that scope, possible child elements are: %1.")
200 .arg(elementNames.join(QLatin1String(", "))));
204 private:
205 XsdSchemaParser *m_parser;
206 XsdStateMachine<XsdSchemaToken::NodeName> m_machine;
212 * Returns a list of all particles with group references that appear at any level of
213 * the given unresolved @p group.
215 static XsdParticle::List collectGroupRef(const XsdModelGroup::Ptr &group)
217 XsdParticle::List refParticles;
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));
226 if (particles.at(i)->term()->isModelGroup()) {
227 refParticles << collectGroupRef(XsdModelGroup::Ptr(particles.at(i)->term()));
231 return refParticles;
235 * Helper function that works around the limited facilities of
236 * QUrl/AnyURI::fromLexical to detect invalid URIs
238 inline static bool isValidUri(const QString &string)
240 // an empty URI points to the current document as defined in RFC 2396 (4.2)
241 if (string.isEmpty())
242 return true;
244 // explicit check as that is not checked by the code below
245 if (string.startsWith(QLatin1String("##")))
246 return false;
248 const AnyURI::Ptr uri = AnyURI::fromLexical(string);
249 return (!(uri->hasError()));
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)
259 m_schema = m_parserContext->schema();
260 m_schemaResolver = m_parserContext->resolver();
261 m_idCache = XsdIdCache::Ptr(new XsdIdCache());
263 setupStateMachines();
264 setupBuiltinTypeNames();
267 void XsdSchemaParser::setIncludedSchemas(const NamespaceSet &schemas)
269 m_includedSchemas = schemas;
272 void XsdSchemaParser::setImportedSchemas(const NamespaceSet &schemas)
274 m_importedSchemas = schemas;
277 void XsdSchemaParser::setRedefinedSchemas(const NamespaceSet &schemas)
279 m_redefinedSchemas = schemas;
282 void XsdSchemaParser::setTargetNamespace(const QString &targetNamespace)
284 m_targetNamespace = targetNamespace;
287 void XsdSchemaParser::setTargetNamespaceExtended(const QString &targetNamespace)
289 m_targetNamespace = targetNamespace;
290 m_namespaceSupport.setTargetNamespace(m_namePool->allocateNamespace(m_targetNamespace));
293 void XsdSchemaParser::setDocumentURI(const QUrl &uri)
295 m_documentURI = uri;
297 // prevent to get included/imported/redefined twice
298 m_includedSchemas.insert(uri);
299 m_importedSchemas.insert(uri);
302 QUrl XsdSchemaParser::documentURI() const
304 return m_documentURI;
307 bool XsdSchemaParser::isAnyAttributeAllowed() const
309 return false;
312 bool XsdSchemaParser::parse(ParserType parserType)
314 m_componentLocationHash.clear();
316 while (!atEnd()) {
317 readNext();
319 if (isStartElement()) {
320 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
321 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
323 if (isSchemaTag(XsdSchemaToken::Schema, token, namespaceToken)) {
324 parseSchema(parserType);
325 } else {
326 error(QtXmlPatterns::tr("Document is not a XML schema."));
331 m_schemaResolver->addComponentLocationHash(m_componentLocationHash);
332 m_schemaResolver->setDefaultOpenContent(m_defaultOpenContent, m_defaultOpenContentAppliesToEmpty);
334 if (QXmlStreamReader::error() != QXmlStreamReader::NoError)
335 error(errorString());
337 return true;
340 void XsdSchemaParser::error(const QString &msg)
342 MaintainingReader<XsdSchemaToken, XsdTagScope::Type>::error(msg, XsdSchemaContext::XSDError);
345 void XsdSchemaParser::attributeContentError(const char *attributeName, const char *elementName, const QString &value, const SchemaType::Ptr &type)
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)));
361 void XsdSchemaParser::parseSchema(ParserType parserType)
363 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Schema, this);
365 validateElement(XsdTagScope::Schema);
367 // parse attributes
369 if (parserType == TopLevelParser) {
370 if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
371 m_targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
373 } else if (parserType == IncludeParser) {
374 // m_targetNamespace is set to the target namespace of the including schema at this point
376 if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
377 const QString targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
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;
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
388 QString targetNamespace;
389 if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
390 targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
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;
398 } else if (parserType == RedefineParser) {
399 // m_targetNamespace is set to the target namespace of the redefining schema at this point
401 if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
402 const QString targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
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;
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;
419 m_attributeFormDefault = value;
420 } else {
421 m_attributeFormDefault = QString::fromLatin1("unqualified");
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;
431 m_elementFormDefault = value;
432 } else {
433 m_elementFormDefault = QString::fromLatin1("unqualified");
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;
450 m_blockDefault = blockDefault;
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;
468 m_finalDefault = finalDefault;
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;
481 m_xpathDefaultNamespace = xpathDefaultNamespace;
482 } else {
483 m_xpathDefaultNamespace = QString::fromLatin1("##local");
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
491 if (hasAttribute(QString::fromLatin1("version"))) {
492 const QString version = readAttribute(QString::fromLatin1("version"));
495 if (hasAttribute(CommonNamespaces::XML, QString::fromLatin1("lang"))) {
496 const QString value = readAttribute(QString::fromLatin1("lang"), CommonNamespaces::XML);
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;
505 validateIdAttribute("schema");
507 TagValidationHandler tagValidator(XsdTagScope::Schema, this, m_namePool);
509 while (!atEnd()) {
510 readNext();
512 if (isEndElement())
513 break;
515 if (isStartElement()) {
516 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
517 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
519 tagValidator.validate(token);
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();
559 tagValidator.finalize();
561 m_schema->setTargetNamespace(m_targetNamespace);
564 void XsdSchemaParser::parseInclude()
566 Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Include &&
567 XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI);
569 validateElement(XsdTagScope::Include);
571 // parse attributes
572 const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation"));
574 QUrl url(schemaLocation);
575 if (url.isRelative()) {
576 Q_ASSERT(m_documentURI.isValid());
578 url = m_documentURI.resolved(url);
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);
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;
602 validateIdAttribute("include");
604 TagValidationHandler tagValidator(XsdTagScope::Include, this, m_namePool);
606 while (!atEnd()) {
607 readNext();
609 if (isEndElement())
610 break;
612 if (isStartElement()) {
613 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
614 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
616 tagValidator.validate(token);
618 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
619 const XsdAnnotation::Ptr annotation = parseAnnotation();
620 m_schema->addAnnotation(annotation);
621 } else {
622 parseUnknown();
627 tagValidator.finalize();
630 void XsdSchemaParser::parseImport()
632 Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Import &&
633 XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI);
635 validateElement(XsdTagScope::Import);
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;
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;
657 if (hasAttribute(QString::fromLatin1("schemaLocation"))) {
658 const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation"));
660 QUrl url(schemaLocation);
661 if (url.isRelative()) {
662 Q_ASSERT(m_documentURI.isValid());
664 url = m_documentURI.resolved(url);
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);
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);
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;
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);
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;
709 } else {
710 // we don't import anything... that is valid according to the schema
714 validateIdAttribute("import");
716 TagValidationHandler tagValidator(XsdTagScope::Import, this, m_namePool);
718 while (!atEnd()) {
719 readNext();
721 if (isEndElement())
722 break;
724 if (isStartElement()) {
725 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
726 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
728 tagValidator.validate(token);
730 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
731 const XsdAnnotation::Ptr annotation = parseAnnotation();
732 m_schema->addAnnotation(annotation);
733 } else {
734 parseUnknown();
739 tagValidator.finalize();
742 void XsdSchemaParser::parseRedefine()
744 Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Redefine &&
745 XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI);
747 validateElement(XsdTagScope::Redefine);
749 // parse attributes
750 validateIdAttribute("redefine");
752 const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation"));
754 TagValidationHandler tagValidator(XsdTagScope::Redefine, this, m_namePool);
756 XsdSimpleType::List redefinedSimpleTypes;
757 XsdComplexType::List redefinedComplexTypes;
758 XsdModelGroup::List redefinedGroups;
759 XsdAttributeGroup::List redefinedAttributeGroups;
761 while (!atEnd()) {
762 readNext();
764 if (isEndElement())
765 break;
767 if (isStartElement()) {
768 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
769 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
771 tagValidator.validate(token);
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);
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;
785 } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
786 const XsdComplexType::Ptr type = parseGlobalComplexType();
787 redefinedComplexTypes.append(type);
789 // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
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;
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);
804 } else {
805 parseUnknown();
810 bool locationMustResolve = false;
811 if (!redefinedSimpleTypes.isEmpty() || !redefinedComplexTypes.isEmpty() ||
812 !redefinedGroups.isEmpty() || !redefinedAttributeGroups.isEmpty()) {
813 locationMustResolve = true;
816 QUrl url(schemaLocation);
817 if (url.isRelative()) {
818 Q_ASSERT(m_documentURI.isValid());
820 url = m_documentURI.resolved(url);
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));
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;
845 delete reply;
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();
854 // now we do the actual redefinition:
856 // iterate over all redefined simple types
857 for (int i = 0; i < redefinedSimpleTypes.count(); ++i) {
858 XsdSimpleType::Ptr redefinedType = redefinedSimpleTypes.at(i);
860 //TODONEXT: validation
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);
867 if (redefinedType->name(m_namePool) == contextType->name(m_namePool)) { // we found the right type
868 found = true;
870 // 1) set name of context type to empty name
871 contextType->setName(m_parserContext->createAnonymousName(QString()));
873 // 2) set the context type as base type for the redefined type
874 redefinedType->setWxsSuperType(contextType);
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);
880 // 4) add the redefined type to the schema
881 addType(redefinedType);
883 // 5) add the context type as anonymous type, so the resolver
884 // can resolve it further.
885 addAnonymousType(contextType);
887 // 6) remove the context type from the list
888 contextSimpleTypes.removeAt(j);
890 break;
894 if (!found) {
895 error(QString::fromLatin1("no matching type found to redefine simple type %1").arg(formatType(m_namePool, redefinedType)));
896 return;
900 // add all remaining context simple types to the schema
901 for (int i = 0; i < contextSimpleTypes.count(); ++i) {
902 addType(contextSimpleTypes.at(i));
905 // iterate over all redefined complex types
906 for (int i = 0; i < redefinedComplexTypes.count(); ++i) {
907 XsdComplexType::Ptr redefinedType = redefinedComplexTypes.at(i);
909 //TODONEXT: validation
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);
916 if (redefinedType->name(m_namePool) == contextType->name(m_namePool)) { // we found the right type
917 found = true;
919 // 1) set name of context type to empty name
920 contextType->setName(m_parserContext->createAnonymousName(QString()));
922 // 2) set the context type as base type for the redefined type
923 redefinedType->setWxsSuperType(contextType);
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);
929 // 4) add the redefined type to the schema
930 addType(redefinedType);
932 // 5) add the context type as anonymous type, so the resolver
933 // can resolve its attribute uses etc.
934 addAnonymousType(contextType);
936 // 6) remove the context type from the list
937 contextComplexTypes.removeAt(j);
939 break;
943 if (!found) {
944 error(QString::fromLatin1("no matching type found to redefine complex type %1").arg(formatType(m_namePool, redefinedType)));
945 return;
949 // iterate over all redefined element groups
950 for (int i = 0; i < redefinedGroups.count(); ++i) {
951 const XsdModelGroup::Ptr group(redefinedGroups.at(i));
953 // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
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);
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;
968 sameNameCounter++;
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;
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;
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;
992 if (sameNameCounter == 1) {
993 // there was a self reference in the redefined group, so use the
994 // group from the included schema
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())));
999 // replace the self-reference with the group from the included schema
1000 referencedParticle->setTerm(contextGroup);
1002 addElementGroup(group);
1004 addElementGroup(contextGroup);
1005 contextGroups.removeAll(contextGroup);
1006 } else {
1007 // there was no self reference in the redefined group
1009 // just add the redefined group...
1010 addElementGroup(group);
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);
1016 m_schemaResolver->addRedefinedGroups(group, contextGroup);
1018 // ...and forget about the group from the included schema
1019 contextGroups.removeAll(contextGroup);
1023 // iterate over all redefined attribute groups
1024 for (int i = 0; i < redefinedAttributeGroups.count(); ++i) {
1025 const XsdAttributeGroup::Ptr group(redefinedAttributeGroups.at(i));
1027 // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
1029 // 7
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++;
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;
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;
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;
1063 if (sameNameCounter == 1) {
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())));
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;
1085 // add both groups to the target schema
1086 addAttributeGroup(baseGroup);
1087 addAttributeGroup(group);
1089 contextAttributeGroups.removeAll(baseGroup);
1092 if (sameNameCounter == 0) { // 7.2
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);
1098 m_schemaResolver->addRedefinedAttributeGroups(group, baseGroup);
1100 // just add the redefined attribute group to the target schema...
1101 addAttributeGroup(group);
1103 // ... and forget about the one from the included schema
1104 contextAttributeGroups.removeAll(baseGroup);
1108 // add all remaining context complex types to the schema
1109 for (int i = 0; i < contextComplexTypes.count(); ++i) {
1110 addType(contextComplexTypes.at(i));
1113 // add all remaining context element groups to the schema
1114 for (int i = 0; i < contextGroups.count(); ++i) {
1115 addElementGroup(contextGroups.at(i));
1118 // add all remaining context attribute groups to the schema
1119 for (int i = 0; i < contextAttributeGroups.count(); ++i) {
1120 addAttributeGroup(contextAttributeGroups.at(i));
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));
1129 const XsdAttribute::List contextAttributes = redefinedContext->schema()->attributes();
1130 for (int i = 0; i < contextAttributes.count(); ++i) {
1131 addAttribute(contextAttributes.at(i));
1134 const XsdNotation::List contextNotations = redefinedContext->schema()->notations();
1135 for (int i = 0; i < contextNotations.count(); ++i) {
1136 addNotation(contextNotations.at(i));
1139 // push all data to resolve from the context resolver to our resolver
1140 redefinedContext->resolver()->copyDataTo(m_parserContext->resolver());
1142 tagValidator.finalize();
1145 XsdAnnotation::Ptr XsdSchemaParser::parseAnnotation()
1147 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Annotation, this);
1149 validateElement(XsdTagScope::Annotation);
1151 // parse attributes
1152 validateIdAttribute("annotation");
1154 TagValidationHandler tagValidator(XsdTagScope::Annotation, this, m_namePool);
1156 const XsdAnnotation::Ptr annotation(new XsdAnnotation());
1158 while (!atEnd()) {
1159 readNext();
1161 if (isEndElement())
1162 break;
1164 if (isStartElement()) {
1165 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1166 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1168 tagValidator.validate(token);
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();
1182 tagValidator.finalize();
1184 return annotation;
1187 XsdApplicationInformation::Ptr XsdSchemaParser::parseAppInfo()
1189 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Appinfo, this);
1191 validateElement(XsdTagScope::AppInfo);
1193 const XsdApplicationInformation::Ptr info(new XsdApplicationInformation());
1195 // parse attributes
1196 if (hasAttribute(QString::fromLatin1("source"))) {
1197 const QString value = readAttribute(QString::fromLatin1("source"));
1199 if (!isValidUri(value)) {
1200 attributeContentError("source", "appinfo", value, BuiltinTypes::xsAnyURI);
1201 return info;
1204 if (!value.isEmpty()) {
1205 const AnyURI::Ptr source = AnyURI::fromLexical(value);
1206 info->setSource(source);
1210 while (!atEnd()) { //EVAL: can be anything... what to do?
1211 readNext();
1213 if (isEndElement())
1214 break;
1216 if (isStartElement())
1217 parseUnknownDocumentation();
1220 return info;
1223 XsdDocumentation::Ptr XsdSchemaParser::parseDocumentation()
1225 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Documentation, this);
1227 validateElement(XsdTagScope::Documentation);
1229 const XsdDocumentation::Ptr documentation(new XsdDocumentation());
1231 // parse attributes
1232 if (hasAttribute(QString::fromLatin1("source"))) {
1233 const QString value = readAttribute(QString::fromLatin1("source"));
1235 if (!isValidUri(value)) {
1236 attributeContentError("source", "documentation", value, BuiltinTypes::xsAnyURI);
1237 return documentation;
1240 if (!value.isEmpty()) {
1241 const AnyURI::Ptr source = AnyURI::fromLexical(value);
1242 documentation->setSource(source);
1246 if (hasAttribute(CommonNamespaces::XML, QString::fromLatin1("lang"))) {
1247 const QString value = readAttribute(QString::fromLatin1("lang"), CommonNamespaces::XML);
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;
1256 while (!atEnd()) { //EVAL: can by any... what to do?
1257 readNext();
1259 if (isEndElement())
1260 break;
1262 if (isStartElement())
1263 parseUnknownDocumentation();
1266 return documentation;
1269 void XsdSchemaParser::parseDefaultOpenContent()
1271 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::DefaultOpenContent, this);
1273 validateElement(XsdTagScope::DefaultOpenContent);
1275 m_defaultOpenContent = XsdComplexType::OpenContent::Ptr(new XsdComplexType::OpenContent());
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;
1285 m_defaultOpenContentAppliesToEmpty = appliesToEmpty->as<Boolean>()->value();
1286 } else {
1287 m_defaultOpenContentAppliesToEmpty = false;
1290 if (hasAttribute(QString::fromLatin1("mode"))) {
1291 const QString mode = readAttribute(QString::fromLatin1("mode"));
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;
1301 } else {
1302 m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave);
1305 validateIdAttribute("defaultOpenContent");
1307 TagValidationHandler tagValidator(XsdTagScope::DefaultOpenContent, this, m_namePool);
1309 while (!atEnd()) {
1310 readNext();
1312 if (isEndElement())
1313 break;
1315 if (isStartElement()) {
1316 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1317 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1319 tagValidator.validate(token);
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();
1334 tagValidator.finalize();
1337 XsdSimpleType::Ptr XsdSchemaParser::parseGlobalSimpleType()
1339 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleType, this);
1341 validateElement(XsdTagScope::GlobalSimpleType);
1343 const XsdSimpleType::Ptr simpleType(new XsdSimpleType());
1344 simpleType->setCategory(XsdSimpleType::SimpleTypeAtomic); // just to make sure it's not invalid
1346 // parse attributes
1347 const SchemaType::DerivationConstraints allowedConstraints(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint | SchemaType::ListConstraint | SchemaType::UnionConstraint);
1348 simpleType->setDerivationConstraints(readDerivationConstraintAttribute(allowedConstraints, "simpleType"));
1350 const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("simpleType"));
1351 simpleType->setName(objectName);
1353 validateIdAttribute("simpleType");
1355 TagValidationHandler tagValidator(XsdTagScope::GlobalSimpleType, this, m_namePool);
1357 while (!atEnd()) {
1358 readNext();
1360 if (isEndElement())
1361 break;
1363 if (isStartElement()) {
1364 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1365 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1367 tagValidator.validate(token);
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();
1384 tagValidator.finalize();
1386 return simpleType;
1389 XsdSimpleType::Ptr XsdSchemaParser::parseLocalSimpleType()
1391 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleType, this);
1393 validateElement(XsdTagScope::LocalSimpleType);
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));
1399 validateIdAttribute("simpleType");
1401 TagValidationHandler tagValidator(XsdTagScope::LocalSimpleType, this, m_namePool);
1403 while (!atEnd()) {
1404 readNext();
1406 if (isEndElement())
1407 break;
1409 if (isStartElement()) {
1410 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1411 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1413 tagValidator.validate(token);
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();
1430 tagValidator.finalize();
1432 return simpleType;
1435 void XsdSchemaParser::parseSimpleRestriction(const XsdSimpleType::Ptr &ptr)
1437 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
1439 validateElement(XsdTagScope::SimpleRestriction);
1441 ptr->setDerivationMethod(XsdSimpleType::DerivationRestriction);
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;
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
1454 hasBaseAttribute = true;
1455 hasBaseTypeSpecified = true;
1457 validateIdAttribute("restriction");
1459 XsdFacet::Hash facets;
1460 QList<XsdFacet::Ptr> patternFacets;
1461 QList<XsdFacet::Ptr> enumerationFacets;
1462 QList<XsdFacet::Ptr> assertionFacets;
1464 TagValidationHandler tagValidator(XsdTagScope::SimpleRestriction, this, m_namePool);
1466 while (!atEnd()) {
1467 readNext();
1469 if (isEndElement())
1470 break;
1472 if (isStartElement()) {
1473 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1474 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1476 tagValidator.validate(token);
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;
1490 const XsdSimpleType::Ptr type = parseLocalSimpleType();
1491 type->setContext(ptr);
1492 ptr->setWxsSuperType(type);
1493 ptr->setCategory(type->category());
1494 hasBaseTypeSpecified = true;
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();
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;
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);
1556 AtomicValue::List multiValue;
1557 for (int i = 0; i < patternFacets.count(); ++i)
1558 multiValue << patternFacets.at(i)->multiValue();
1560 patternFacet->setMultiValue(multiValue);
1561 addFacet(patternFacet, facets, ptr);
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);
1569 AtomicValue::List multiValue;
1570 for (int i = 0; i < enumerationFacets.count(); ++i)
1571 multiValue << enumerationFacets.at(i)->multiValue();
1573 enumerationFacet->setMultiValue(multiValue);
1574 addFacet(enumerationFacet, facets, ptr);
1577 // merge all assertion facets into one facet
1578 if (!assertionFacets.isEmpty()) {
1579 const XsdFacet::Ptr assertionFacet(new XsdFacet());
1580 assertionFacet->setType(XsdFacet::Assertion);
1582 XsdAssertion::List assertions;
1583 for (int i = 0; i < assertionFacets.count(); ++i)
1584 assertions << assertionFacets.at(i)->assertions();
1586 assertionFacet->setAssertions(assertions);
1587 addFacet(assertionFacet, facets, ptr);
1590 ptr->setFacets(facets);
1592 tagValidator.finalize();
1595 void XsdSchemaParser::parseList(const XsdSimpleType::Ptr &ptr)
1597 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::List, this);
1599 validateElement(XsdTagScope::List);
1601 ptr->setCategory(XsdSimpleType::SimpleTypeList);
1602 ptr->setDerivationMethod(XsdSimpleType::DerivationList);
1603 ptr->setWxsSuperType(BuiltinTypes::xsAnySimpleType);
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;
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
1616 hasItemTypeAttribute = true;
1617 hasItemTypeSpecified = true;
1620 validateIdAttribute("list");
1622 TagValidationHandler tagValidator(XsdTagScope::List, this, m_namePool);
1624 while (!atEnd()) {
1625 readNext();
1627 if (isEndElement())
1628 break;
1630 if (isStartElement()) {
1631 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1632 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1634 tagValidator.validate(token);
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;
1648 const XsdSimpleType::Ptr type = parseLocalSimpleType();
1649 type->setContext(ptr);
1650 ptr->setItemType(type);
1652 hasItemTypeSpecified = true;
1654 // add it to list of anonymous types as well
1655 addAnonymousType(type);
1656 } else {
1657 parseUnknown();
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;
1670 tagValidator.finalize();
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);
1682 void XsdSchemaParser::parseUnion(const XsdSimpleType::Ptr &ptr)
1684 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Union, this);
1686 validateElement(XsdTagScope::Union);
1688 ptr->setCategory(XsdSimpleType::SimpleTypeUnion);
1689 ptr->setDerivationMethod(XsdSimpleType::DerivationUnion);
1690 ptr->setWxsSuperType(BuiltinTypes::xsAnySimpleType);
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;
1697 if (hasAttribute(QString::fromLatin1("memberTypes"))) {
1698 hasMemberTypesAttribute = true;
1700 const QStringList memberTypes = readAttribute(QString::fromLatin1("memberTypes")).split(QLatin1Char(' '), QString::SkipEmptyParts);
1701 QList<QXmlName> typeNames;
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);
1709 if (!typeNames.isEmpty()) {
1710 m_schemaResolver->addSimpleUnionTypes(ptr, typeNames, currentSourceLocation()); // add to resolver
1711 hasMemberTypesSpecified = true;
1715 validateIdAttribute("union");
1717 AnySimpleType::List memberTypes;
1719 TagValidationHandler tagValidator(XsdTagScope::Union, this, m_namePool);
1721 while (!atEnd()) {
1722 readNext();
1724 if (isEndElement())
1725 break;
1727 if (isStartElement()) {
1728 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1729 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1731 tagValidator.validate(token);
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);
1741 // add it to list of anonymous types as well
1742 addAnonymousType(type);
1743 } else {
1744 parseUnknown();
1749 if (!memberTypes.isEmpty()) {
1750 ptr->setMemberTypes(memberTypes);
1751 hasMemberTypesSpecified = true;
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;
1762 tagValidator.finalize();
1765 XsdFacet::Ptr XsdSchemaParser::parseMinExclusiveFacet()
1767 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinExclusive, this);
1769 validateElement(XsdTagScope::MinExclusiveFacet);
1771 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
1772 facet->setType(XsdFacet::MinimumExclusive);
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;
1783 facet->setFixed(fixed->as<Boolean>()->value());
1784 } else {
1785 facet->setFixed(false); // the default value
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);
1799 validateIdAttribute("minExclusive");
1801 TagValidationHandler tagValidator(XsdTagScope::MinExclusiveFacet, this, m_namePool);
1803 while (!atEnd()) {
1804 readNext();
1806 if (isEndElement())
1807 break;
1809 if (isStartElement()) {
1810 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1811 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1813 tagValidator.validate(token);
1815 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1816 const XsdAnnotation::Ptr annotation = parseAnnotation();
1817 facet->addAnnotation(annotation);
1818 } else {
1819 parseUnknown();
1824 tagValidator.finalize();
1826 return facet;
1829 XsdFacet::Ptr XsdSchemaParser::parseMinInclusiveFacet()
1831 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinInclusive, this);
1833 validateElement(XsdTagScope::MinInclusiveFacet);
1835 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
1836 facet->setType(XsdFacet::MinimumInclusive);
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;
1847 facet->setFixed(fixed->as<Boolean>()->value());
1848 } else {
1849 facet->setFixed(false); // the default value
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);
1863 validateIdAttribute("minInclusive");
1865 TagValidationHandler tagValidator(XsdTagScope::MinInclusiveFacet, this, m_namePool);
1867 while (!atEnd()) {
1868 readNext();
1870 if (isEndElement())
1871 break;
1873 if (isStartElement()) {
1874 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1875 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1877 tagValidator.validate(token);
1879 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1880 const XsdAnnotation::Ptr annotation = parseAnnotation();
1881 facet->addAnnotation(annotation);
1882 } else {
1883 parseUnknown();
1888 tagValidator.finalize();
1890 return facet;
1893 XsdFacet::Ptr XsdSchemaParser::parseMaxExclusiveFacet()
1895 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxExclusive, this);
1897 validateElement(XsdTagScope::MaxExclusiveFacet);
1899 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
1900 facet->setType(XsdFacet::MaximumExclusive);
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;
1911 facet->setFixed(fixed->as<Boolean>()->value());
1912 } else {
1913 facet->setFixed(false); // the default value
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);
1927 validateIdAttribute("maxExclusive");
1929 TagValidationHandler tagValidator(XsdTagScope::MaxExclusiveFacet, this, m_namePool);
1931 while (!atEnd()) {
1932 readNext();
1934 if (isEndElement())
1935 break;
1937 if (isStartElement()) {
1938 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
1939 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
1941 tagValidator.validate(token);
1943 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
1944 const XsdAnnotation::Ptr annotation = parseAnnotation();
1945 facet->addAnnotation(annotation);
1946 } else {
1947 parseUnknown();
1952 tagValidator.finalize();
1954 return facet;
1957 XsdFacet::Ptr XsdSchemaParser::parseMaxInclusiveFacet()
1959 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxInclusive, this);
1961 validateElement(XsdTagScope::MaxInclusiveFacet);
1963 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
1964 facet->setType(XsdFacet::MaximumInclusive);
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;
1975 facet->setFixed(fixed->as<Boolean>()->value());
1976 } else {
1977 facet->setFixed(false); // the default value
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);
1991 validateIdAttribute("maxInclusive");
1993 TagValidationHandler tagValidator(XsdTagScope::MaxInclusiveFacet, this, m_namePool);
1995 while (!atEnd()) {
1996 readNext();
1998 if (isEndElement())
1999 break;
2001 if (isStartElement()) {
2002 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2003 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2005 tagValidator.validate(token);
2007 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2008 const XsdAnnotation::Ptr annotation = parseAnnotation();
2009 facet->addAnnotation(annotation);
2010 } else {
2011 parseUnknown();
2016 tagValidator.finalize();
2018 return facet;
2021 XsdFacet::Ptr XsdSchemaParser::parseTotalDigitsFacet()
2023 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::TotalDigits, this);
2025 validateElement(XsdTagScope::TotalDigitsFacet);
2027 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2028 facet->setType(XsdFacet::TotalDigits);
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;
2039 facet->setFixed(fixed->as<Boolean>()->value());
2040 } else {
2041 facet->setFixed(false); // the default value
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);
2053 validateIdAttribute("totalDigits");
2055 TagValidationHandler tagValidator(XsdTagScope::TotalDigitsFacet, this, m_namePool);
2057 while (!atEnd()) {
2058 readNext();
2060 if (isEndElement())
2061 break;
2063 if (isStartElement()) {
2064 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2065 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2067 tagValidator.validate(token);
2069 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2070 const XsdAnnotation::Ptr annotation = parseAnnotation();
2071 facet->addAnnotation(annotation);
2072 } else {
2073 parseUnknown();
2078 tagValidator.finalize();
2080 return facet;
2083 XsdFacet::Ptr XsdSchemaParser::parseFractionDigitsFacet()
2085 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::FractionDigits, this);
2087 validateElement(XsdTagScope::FractionDigitsFacet);
2089 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2090 facet->setType(XsdFacet::FractionDigits);
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;
2101 facet->setFixed(fixed->as<Boolean>()->value());
2102 } else {
2103 facet->setFixed(false); // the default value
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);
2115 validateIdAttribute("fractionDigits");
2117 TagValidationHandler tagValidator(XsdTagScope::FractionDigitsFacet, this, m_namePool);
2119 while (!atEnd()) {
2120 readNext();
2122 if (isEndElement())
2123 break;
2125 if (isStartElement()) {
2126 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2127 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2129 tagValidator.validate(token);
2131 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2132 const XsdAnnotation::Ptr annotation = parseAnnotation();
2133 facet->addAnnotation(annotation);
2134 } else {
2135 parseUnknown();
2140 tagValidator.finalize();
2142 return facet;
2145 XsdFacet::Ptr XsdSchemaParser::parseLengthFacet()
2147 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Length, this);
2149 validateElement(XsdTagScope::LengthFacet);
2151 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2152 facet->setType(XsdFacet::Length);
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;
2163 facet->setFixed(fixed->as<Boolean>()->value());
2164 } else {
2165 facet->setFixed(false); // the default value
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);
2177 validateIdAttribute("length");
2179 TagValidationHandler tagValidator(XsdTagScope::LengthFacet, this, m_namePool);
2181 while (!atEnd()) {
2182 readNext();
2184 if (isEndElement())
2185 break;
2187 if (isStartElement()) {
2188 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2189 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2191 tagValidator.validate(token);
2193 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2194 const XsdAnnotation::Ptr annotation = parseAnnotation();
2195 facet->addAnnotation(annotation);
2196 } else {
2197 parseUnknown();
2202 tagValidator.finalize();
2204 return facet;
2207 XsdFacet::Ptr XsdSchemaParser::parseMinLengthFacet()
2209 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinLength, this);
2211 validateElement(XsdTagScope::MinLengthFacet);
2213 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2214 facet->setType(XsdFacet::MinimumLength);
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;
2225 facet->setFixed(fixed->as<Boolean>()->value());
2226 } else {
2227 facet->setFixed(false); // the default value
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);
2239 validateIdAttribute("minLength");
2241 TagValidationHandler tagValidator(XsdTagScope::MinLengthFacet, this, m_namePool);
2243 while (!atEnd()) {
2244 readNext();
2246 if (isEndElement())
2247 break;
2249 if (isStartElement()) {
2250 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2251 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2253 tagValidator.validate(token);
2255 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2256 const XsdAnnotation::Ptr annotation = parseAnnotation();
2257 facet->addAnnotation(annotation);
2258 } else {
2259 parseUnknown();
2264 tagValidator.finalize();
2266 return facet;
2269 XsdFacet::Ptr XsdSchemaParser::parseMaxLengthFacet()
2271 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxLength, this);
2273 validateElement(XsdTagScope::MaxLengthFacet);
2275 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2276 facet->setType(XsdFacet::MaximumLength);
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;
2287 facet->setFixed(fixed->as<Boolean>()->value());
2288 } else {
2289 facet->setFixed(false); // the default value
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);
2301 validateIdAttribute("maxLength");
2303 TagValidationHandler tagValidator(XsdTagScope::MaxLengthFacet, this, m_namePool);
2305 while (!atEnd()) {
2306 readNext();
2308 if (isEndElement())
2309 break;
2311 if (isStartElement()) {
2312 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2313 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2315 tagValidator.validate(token);
2317 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2318 const XsdAnnotation::Ptr annotation = parseAnnotation();
2319 facet->addAnnotation(annotation);
2320 } else {
2321 parseUnknown();
2326 tagValidator.finalize();
2328 return facet;
2331 XsdFacet::Ptr XsdSchemaParser::parseEnumerationFacet()
2333 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Enumeration, this);
2335 validateElement(XsdTagScope::EnumerationFacet);
2337 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2338 facet->setType(XsdFacet::Enumeration);
2340 // parse attributes
2341 facet->setFixed(false); // not defined in schema, but can't hurt
2343 const QString value = readAttribute(QString::fromLatin1("value"));
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);
2356 m_schemaResolver->addEnumerationFacetValue(string, m_namespaceSupport);
2358 validateIdAttribute("enumeration");
2360 TagValidationHandler tagValidator(XsdTagScope::EnumerationFacet, this, m_namePool);
2362 while (!atEnd()) {
2363 readNext();
2365 if (isEndElement())
2366 break;
2368 if (isStartElement()) {
2369 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2370 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2372 tagValidator.validate(token);
2374 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2375 const XsdAnnotation::Ptr annotation = parseAnnotation();
2376 facet->addAnnotation(annotation);
2377 } else {
2378 parseUnknown();
2383 tagValidator.finalize();
2385 return facet;
2388 XsdFacet::Ptr XsdSchemaParser::parseWhiteSpaceFacet()
2390 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::WhiteSpace, this);
2392 validateElement(XsdTagScope::WhiteSpaceFacet);
2394 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2395 facet->setType(XsdFacet::WhiteSpace);
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;
2406 facet->setFixed(fixed->as<Boolean>()->value());
2407 } else {
2408 facet->setFixed(false); // the default value
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);
2427 validateIdAttribute("whiteSpace");
2429 TagValidationHandler tagValidator(XsdTagScope::WhiteSpaceFacet, this, m_namePool);
2431 while (!atEnd()) {
2432 readNext();
2434 if (isEndElement())
2435 break;
2437 if (isStartElement()) {
2438 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2439 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2441 tagValidator.validate(token);
2443 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2444 const XsdAnnotation::Ptr annotation = parseAnnotation();
2445 facet->addAnnotation(annotation);
2446 } else {
2447 parseUnknown();
2452 tagValidator.finalize();
2454 return facet;
2457 XsdFacet::Ptr XsdSchemaParser::parsePatternFacet()
2459 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Pattern, this);
2461 validateElement(XsdTagScope::PatternFacet);
2463 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2464 facet->setType(XsdFacet::Pattern);
2466 // parse attributes
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);
2481 validateIdAttribute("pattern");
2483 TagValidationHandler tagValidator(XsdTagScope::PatternFacet, this, m_namePool);
2485 while (!atEnd()) {
2486 readNext();
2488 if (isEndElement())
2489 break;
2491 if (isStartElement()) {
2492 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2493 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2495 tagValidator.validate(token);
2497 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
2498 const XsdAnnotation::Ptr annotation = parseAnnotation();
2499 facet->addAnnotation(annotation);
2500 } else {
2501 parseUnknown();
2506 tagValidator.finalize();
2508 return facet;
2511 XsdFacet::Ptr XsdSchemaParser::parseAssertionFacet()
2513 // this is just a wrapper function around the parseAssertion() method
2515 const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assertion, XsdTagScope::Assertion);
2517 const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
2518 facet->setType(XsdFacet::Assertion);
2519 facet->setAssertions(XsdAssertion::List() << assertion);
2521 return facet;
2524 XsdComplexType::Ptr XsdSchemaParser::parseGlobalComplexType()
2526 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this);
2528 validateElement(XsdTagScope::GlobalComplexType);
2530 bool hasTypeSpecified = false;
2531 bool hasComplexContent = false;
2533 const XsdComplexType::Ptr complexType(new XsdComplexType());
2535 // parse attributes
2536 if (hasAttribute(QString::fromLatin1("abstract"))) {
2537 const QString abstract = readAttribute(QString::fromLatin1("abstract"));
2539 const Boolean::Ptr value = Boolean::fromLexical(abstract);
2540 if (value->hasError()) {
2541 attributeContentError("abstract", "complexType", abstract, BuiltinTypes::xsBoolean);
2542 return complexType;
2545 complexType->setIsAbstract(value->as<Boolean>()->value());
2546 } else {
2547 complexType->setIsAbstract(false); // default value
2550 complexType->setProhibitedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint, "complexType"));
2551 complexType->setDerivationConstraints(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "complexType"));
2553 const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("complexType"));
2554 complexType->setName(objectName);
2556 bool effectiveMixed = false;
2557 if (hasAttribute(QString::fromLatin1("mixed"))) {
2558 const QString mixed = readAttribute(QString::fromLatin1("mixed"));
2560 const Boolean::Ptr value = Boolean::fromLexical(mixed);
2561 if (value->hasError()) {
2562 attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean);
2563 return complexType;
2566 effectiveMixed = value->as<Boolean>()->value();
2569 validateIdAttribute("complexType");
2571 TagValidationHandler tagValidator(XsdTagScope::GlobalComplexType, this, m_namePool);
2573 while (!atEnd()) {
2574 readNext();
2576 if (isEndElement())
2577 break;
2579 if (isStartElement()) {
2580 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2581 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2583 tagValidator.validate(token);
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;
2597 parseSimpleContent(complexType);
2598 hasTypeSpecified = true;
2599 } else if (isSchemaTag(XsdSchemaToken::ComplexContent, token, namespaceToken)) {
2600 bool mixed;
2601 parseComplexContent(complexType, &mixed);
2602 hasTypeSpecified = true;
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);
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);
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);
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);
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);
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);
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);
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();
2683 tagValidator.finalize();
2685 if (!hasTypeSpecified) {
2686 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2687 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2688 hasComplexContent = true;
2691 if (hasComplexContent == true) {
2692 resolveComplexContentType(complexType, effectiveMixed);
2695 return complexType;
2698 XsdComplexType::Ptr XsdSchemaParser::parseLocalComplexType()
2700 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this);
2702 validateElement(XsdTagScope::LocalComplexType);
2704 bool hasTypeSpecified = false;
2705 bool hasComplexContent = true;
2707 const XsdComplexType::Ptr complexType(new XsdComplexType());
2708 complexType->setName(m_parserContext->createAnonymousName(m_targetNamespace));
2710 // parse attributes
2711 bool effectiveMixed = false;
2712 if (hasAttribute(QString::fromLatin1("mixed"))) {
2713 const QString mixed = readAttribute(QString::fromLatin1("mixed"));
2715 const Boolean::Ptr value = Boolean::fromLexical(mixed);
2716 if (value->hasError()) {
2717 attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean);
2718 return complexType;
2721 effectiveMixed = value->as<Boolean>()->value();
2724 validateIdAttribute("complexType");
2726 TagValidationHandler tagValidator(XsdTagScope::LocalComplexType, this, m_namePool);
2728 while (!atEnd()) {
2729 readNext();
2731 if (isEndElement())
2732 break;
2734 if (isStartElement()) {
2735 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2736 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2738 tagValidator.validate(token);
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;
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);
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);
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);
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);
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);
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);
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);
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();
2830 tagValidator.finalize();
2832 if (!hasTypeSpecified) {
2833 complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
2834 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
2835 hasComplexContent = true;
2838 if (hasComplexContent == true) {
2839 resolveComplexContentType(complexType, effectiveMixed);
2842 return complexType;
2845 void XsdSchemaParser::resolveComplexContentType(const XsdComplexType::Ptr &complexType, bool effectiveMixed)
2847 // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctcc.common
2849 // 1
2850 // the effectiveMixed contains the effective mixed value
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
2867 if ((complexType->contentType()->particle()->maximumOccursUnbounded() == false) && (complexType->contentType()->particle()->maximumOccurs() == 0))
2868 hasEmptyContent = true; // 2.1.4
2872 const XsdParticle::Ptr explicitContent = (hasEmptyContent ? XsdParticle::Ptr() : complexType->contentType()->particle());
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);
2878 void XsdSchemaParser::parseSimpleContent(const XsdComplexType::Ptr &complexType)
2880 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleContent, this);
2882 validateElement(XsdTagScope::SimpleContent);
2884 complexType->contentType()->setVariety(XsdComplexType::ContentType::Simple);
2886 // parse attributes
2887 validateIdAttribute("simpleContent");
2889 TagValidationHandler tagValidator(XsdTagScope::SimpleContent, this, m_namePool);
2891 while (!atEnd()) {
2892 readNext();
2894 if (isEndElement())
2895 break;
2897 if (isStartElement()) {
2898 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2899 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2901 tagValidator.validate(token);
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();
2916 tagValidator.finalize();
2919 void XsdSchemaParser::parseSimpleContentRestriction(const XsdComplexType::Ptr &complexType)
2921 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
2923 validateElement(XsdTagScope::SimpleContentRestriction);
2925 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
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
2932 validateIdAttribute("restriction");
2934 XsdFacet::Hash facets;
2935 QList<XsdFacet::Ptr> patternFacets;
2936 QList<XsdFacet::Ptr> enumerationFacets;
2937 QList<XsdFacet::Ptr> assertionFacets;
2939 TagValidationHandler tagValidator(XsdTagScope::SimpleContentRestriction, this, m_namePool);
2941 while (!atEnd()) {
2942 readNext();
2944 if (isEndElement())
2945 break;
2947 if (isStartElement()) {
2948 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
2949 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
2951 tagValidator.validate(token);
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);
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();
3020 tagValidator.finalize();
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);
3027 AtomicValue::List multiValue;
3028 for (int i = 0; i < patternFacets.count(); ++i)
3029 multiValue << patternFacets.at(i)->multiValue();
3031 patternFacet->setMultiValue(multiValue);
3032 addFacet(patternFacet, facets, complexType);
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);
3040 AtomicValue::List multiValue;
3041 for (int i = 0; i < enumerationFacets.count(); ++i)
3042 multiValue << enumerationFacets.at(i)->multiValue();
3044 enumerationFacet->setMultiValue(multiValue);
3045 addFacet(enumerationFacet, facets, complexType);
3048 // merge all assertion facets into one facet
3049 if (!assertionFacets.isEmpty()) {
3050 const XsdFacet::Ptr assertionFacet(new XsdFacet());
3051 assertionFacet->setType(XsdFacet::Assertion);
3053 XsdAssertion::List assertions;
3054 for (int i = 0; i < assertionFacets.count(); ++i)
3055 assertions << assertionFacets.at(i)->assertions();
3057 assertionFacet->setAssertions(assertions);
3058 addFacet(assertionFacet, facets, complexType);
3061 m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation(), facets); // add to resolver
3064 void XsdSchemaParser::parseSimpleContentExtension(const XsdComplexType::Ptr &complexType)
3066 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this);
3068 validateElement(XsdTagScope::SimpleContentExtension);
3070 complexType->setDerivationMethod(XsdComplexType::DerivationExtension);
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
3078 validateIdAttribute("extension");
3080 TagValidationHandler tagValidator(XsdTagScope::SimpleContentExtension, this, m_namePool);
3082 while (!atEnd()) {
3083 readNext();
3085 if (isEndElement())
3086 break;
3088 if (isStartElement()) {
3089 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3090 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3092 tagValidator.validate(token);
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();
3115 tagValidator.finalize();
3118 void XsdSchemaParser::parseComplexContent(const XsdComplexType::Ptr &complexType, bool *mixed)
3120 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexContent, this);
3122 validateElement(XsdTagScope::ComplexContent);
3124 complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
3126 // parse attributes
3127 if (hasAttribute(QString::fromLatin1("mixed"))) {
3128 const QString mixedStr = readAttribute(QString::fromLatin1("mixed"));
3130 const Boolean::Ptr value = Boolean::fromLexical(mixedStr);
3131 if (value->hasError()) {
3132 attributeContentError("mixed", "complexType", mixedStr, BuiltinTypes::xsBoolean);
3133 return;
3136 *mixed = value->as<Boolean>()->value();
3137 } else {
3138 *mixed = false;
3141 validateIdAttribute("complexContent");
3143 TagValidationHandler tagValidator(XsdTagScope::ComplexContent, this, m_namePool);
3145 while (!atEnd()) {
3146 readNext();
3148 if (isEndElement())
3149 break;
3151 if (isStartElement()) {
3152 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3153 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3155 tagValidator.validate(token);
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();
3170 tagValidator.finalize();
3173 void XsdSchemaParser::parseComplexContentRestriction(const XsdComplexType::Ptr &complexType)
3175 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
3177 validateElement(XsdTagScope::ComplexContentRestriction);
3179 complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
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
3187 validateIdAttribute("restriction");
3189 TagValidationHandler tagValidator(XsdTagScope::ComplexContentRestriction, this, m_namePool);
3191 bool hasContent = false;
3192 while (!atEnd()) {
3193 readNext();
3195 if (isEndElement())
3196 break;
3198 if (isStartElement()) {
3199 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3200 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3202 tagValidator.validate(token);
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();
3253 if (!hasContent)
3254 complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty);
3256 tagValidator.finalize();
3259 void XsdSchemaParser::parseComplexContentExtension(const XsdComplexType::Ptr &complexType)
3261 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this);
3263 validateElement(XsdTagScope::ComplexContentExtension);
3265 complexType->setDerivationMethod(XsdComplexType::DerivationExtension);
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
3273 validateIdAttribute("extension");
3275 TagValidationHandler tagValidator(XsdTagScope::ComplexContentExtension, this, m_namePool);
3277 bool hasContent = false;
3278 while (!atEnd()) {
3279 readNext();
3281 if (isEndElement())
3282 break;
3284 if (isStartElement()) {
3285 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3286 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3288 tagValidator.validate(token);
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();
3339 if (!hasContent)
3340 complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty);
3342 tagValidator.finalize();
3346 XsdAssertion::Ptr XsdSchemaParser::parseAssertion(const XsdSchemaToken::NodeName &nodeName, const XsdTagScope::Type &tag)
3348 const ElementNamespaceHandler namespaceHandler(nodeName, this);
3350 validateElement(tag);
3352 const XsdAssertion::Ptr assertion(new XsdAssertion());
3354 // parse attributes
3356 const XsdXPathExpression::Ptr expression = readXPathExpression("assertion");
3357 assertion->setTest(expression);
3359 const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "assertion");
3360 expression->setExpression(test);
3362 validateIdAttribute("assertion");
3364 TagValidationHandler tagValidator(tag, this, m_namePool);
3366 while (!atEnd()) {
3367 readNext();
3369 if (isEndElement())
3370 break;
3372 if (isStartElement()) {
3373 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3374 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3376 tagValidator.validate(token);
3378 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3379 const XsdAnnotation::Ptr annotation = parseAnnotation();
3380 assertion->addAnnotation(annotation);
3381 } else {
3382 parseUnknown();
3387 tagValidator.finalize();
3389 return assertion;
3392 XsdComplexType::OpenContent::Ptr XsdSchemaParser::parseOpenContent()
3394 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::OpenContent, this);
3396 validateElement(XsdTagScope::OpenContent);
3398 const XsdComplexType::OpenContent::Ptr openContent(new XsdComplexType::OpenContent());
3400 if (hasAttribute(QString::fromLatin1("mode"))) {
3401 const QString mode = readAttribute(QString::fromLatin1("mode"));
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;
3413 } else {
3414 openContent->setMode(XsdComplexType::OpenContent::Interleave);
3417 validateIdAttribute("openContent");
3419 TagValidationHandler tagValidator(XsdTagScope::OpenContent, this, m_namePool);
3421 while (!atEnd()) {
3422 readNext();
3424 if (isEndElement())
3425 break;
3427 if (isStartElement()) {
3428 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3429 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3431 tagValidator.validate(token);
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();
3446 tagValidator.finalize();
3448 return openContent;
3451 XsdModelGroup::Ptr XsdSchemaParser::parseNamedGroup()
3453 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this);
3455 validateElement(XsdTagScope::NamedGroup);
3457 const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3458 XsdModelGroup::Ptr group;
3460 QXmlName objectName;
3461 if (hasAttribute(QString::fromLatin1("name"))) {
3462 objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("group"));
3465 validateIdAttribute("group");
3467 TagValidationHandler tagValidator(XsdTagScope::NamedGroup, this, m_namePool);
3469 XsdAnnotation::Ptr annotation;
3471 while (!atEnd()) {
3472 readNext();
3474 if (isEndElement())
3475 break;
3477 if (isStartElement()) {
3478 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3479 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3481 tagValidator.validate(token);
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();
3497 tagValidator.finalize();
3499 group->setName(objectName);
3501 if (annotation)
3502 group->addAnnotation(annotation);
3504 return group;
3507 XsdTerm::Ptr XsdSchemaParser::parseReferredGroup(const XsdParticle::Ptr &particle)
3509 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this);
3511 validateElement(XsdTagScope::ReferredGroup);
3513 const XsdReference::Ptr reference(new XsdReference());
3514 reference->setType(XsdReference::ModelGroup);
3515 reference->setSourceLocation(currentSourceLocation());
3517 // parse attributes
3518 if (!parseMinMaxConstraint(particle, "group")) {
3519 return reference;
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);
3527 validateIdAttribute("group");
3529 TagValidationHandler tagValidator(XsdTagScope::ReferredGroup, this, m_namePool);
3531 while (!atEnd()) {
3532 readNext();
3534 if (isEndElement())
3535 break;
3537 if (isStartElement()) {
3538 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3539 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3541 tagValidator.validate(token);
3543 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
3544 const XsdAnnotation::Ptr annotation = parseAnnotation();
3545 reference->addAnnotation(annotation);
3546 } else {
3547 parseUnknown();
3552 tagValidator.finalize();
3554 return reference;
3557 XsdModelGroup::Ptr XsdSchemaParser::parseAll(const NamedSchemaComponent::Ptr &parent)
3559 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this);
3561 validateElement(XsdTagScope::All);
3563 const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3564 modelGroup->setCompositor(XsdModelGroup::AllCompositor);
3566 validateIdAttribute("all");
3568 TagValidationHandler tagValidator(XsdTagScope::All, this, m_namePool);
3570 XsdParticle::List particles;
3571 while (!atEnd()) {
3572 readNext();
3574 if (isEndElement())
3575 break;
3577 if (isStartElement()) {
3578 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3579 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3581 tagValidator.validate(token);
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);
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;
3600 particles.append(particle);
3601 } else {
3602 parseUnknown();
3607 modelGroup->setParticles(particles);
3609 tagValidator.finalize();
3611 return modelGroup;
3614 XsdModelGroup::Ptr XsdSchemaParser::parseLocalAll(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
3616 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this);
3618 validateElement(XsdTagScope::LocalAll);
3620 const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3621 modelGroup->setCompositor(XsdModelGroup::AllCompositor);
3623 // parse attributes
3624 if (!parseMinMaxConstraint(particle, "all")) {
3625 return modelGroup;
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;
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;
3643 validateIdAttribute("all");
3645 TagValidationHandler tagValidator(XsdTagScope::LocalAll, this, m_namePool);
3647 XsdParticle::List particles;
3648 while (!atEnd()) {
3649 readNext();
3651 if (isEndElement())
3652 break;
3654 if (isStartElement()) {
3655 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3656 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3658 tagValidator.validate(token);
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);
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;
3677 particles.append(particle);
3678 } else {
3679 parseUnknown();
3684 modelGroup->setParticles(particles);
3686 tagValidator.finalize();
3688 return modelGroup;
3691 XsdModelGroup::Ptr XsdSchemaParser::parseChoice(const NamedSchemaComponent::Ptr &parent)
3693 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this);
3695 validateElement(XsdTagScope::Choice);
3697 const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3698 modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor);
3700 validateIdAttribute("choice");
3702 XsdParticle::List particles;
3704 TagValidationHandler tagValidator(XsdTagScope::Choice, this, m_namePool);
3706 while (!atEnd()) {
3707 readNext();
3709 if (isEndElement())
3710 break;
3712 if (isStartElement()) {
3713 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3714 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3716 tagValidator.validate(token);
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();
3753 modelGroup->setParticles(particles);
3755 tagValidator.finalize();
3757 return modelGroup;
3760 XsdModelGroup::Ptr XsdSchemaParser::parseLocalChoice(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
3762 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this);
3764 validateElement(XsdTagScope::LocalChoice);
3766 const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3767 modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor);
3769 // parse attributes
3770 if (!parseMinMaxConstraint(particle, "choice")) {
3771 return modelGroup;
3774 validateIdAttribute("choice");
3776 XsdParticle::List particles;
3778 TagValidationHandler tagValidator(XsdTagScope::LocalChoice, this, m_namePool);
3780 while (!atEnd()) {
3781 readNext();
3783 if (isEndElement())
3784 break;
3786 if (isStartElement()) {
3787 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3788 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3790 tagValidator.validate(token);
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();
3827 modelGroup->setParticles(particles);
3829 tagValidator.finalize();
3831 return modelGroup;
3834 XsdModelGroup::Ptr XsdSchemaParser::parseSequence(const NamedSchemaComponent::Ptr &parent)
3836 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this);
3838 validateElement(XsdTagScope::Sequence);
3840 const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3841 modelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
3843 validateIdAttribute("sequence");
3845 XsdParticle::List particles;
3847 TagValidationHandler tagValidator(XsdTagScope::Sequence, this, m_namePool);
3849 while (!atEnd()) {
3850 readNext();
3852 if (isEndElement())
3853 break;
3855 if (isStartElement()) {
3856 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3857 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3859 tagValidator.validate(token);
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();
3896 modelGroup->setParticles(particles);
3898 tagValidator.finalize();
3900 return modelGroup;
3903 XsdModelGroup::Ptr XsdSchemaParser::parseLocalSequence(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
3905 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this);
3907 validateElement(XsdTagScope::LocalSequence);
3909 const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
3910 modelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
3912 // parse attributes
3913 if (!parseMinMaxConstraint(particle, "sequence")) {
3914 return modelGroup;
3917 validateIdAttribute("sequence");
3919 XsdParticle::List particles;
3921 TagValidationHandler tagValidator(XsdTagScope::LocalSequence, this, m_namePool);
3923 while (!atEnd()) {
3924 readNext();
3926 if (isEndElement())
3927 break;
3929 if (isStartElement()) {
3930 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
3931 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
3933 tagValidator.validate(token);
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();
3970 modelGroup->setParticles(particles);
3972 tagValidator.finalize();
3974 return modelGroup;
3977 XsdAttribute::Ptr XsdSchemaParser::parseGlobalAttribute()
3979 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this);
3981 validateElement(XsdTagScope::GlobalAttribute);
3983 const XsdAttribute::Ptr attribute(new XsdAttribute());
3984 attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
3985 attribute->scope()->setVariety(XsdAttribute::Scope::Global);
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;
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);
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"))) {
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;
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;
4028 attribute->setName(objectName);
4030 bool hasTypeAttribute = false;
4031 bool hasTypeSpecified = false;
4033 if (hasAttribute(QString::fromLatin1("type"))) {
4034 hasTypeAttribute = true;
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;
4043 validateIdAttribute("attribute");
4045 TagValidationHandler tagValidator(XsdTagScope::GlobalAttribute, this, m_namePool);
4047 while (!atEnd()) {
4048 readNext();
4050 if (isEndElement())
4051 break;
4053 if (isStartElement()) {
4054 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4055 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4057 tagValidator.validate(token);
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;
4071 const XsdSimpleType::Ptr type = parseLocalSimpleType();
4072 type->setContext(attribute);
4073 attribute->setType(type);
4074 hasTypeSpecified = true;
4076 // add it to list of anonymous types as well
4077 addAnonymousType(type);
4078 } else {
4079 parseUnknown();
4084 if (!hasTypeSpecified) {
4085 attribute->setType(BuiltinTypes::xsAnySimpleType); // default value
4086 return attribute;
4089 tagValidator.finalize();
4091 return attribute;
4094 XsdAttributeUse::Ptr XsdSchemaParser::parseLocalAttribute(const NamedSchemaComponent::Ptr &parent)
4096 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this);
4098 validateElement(XsdTagScope::LocalAttribute);
4100 bool hasRefAttribute = false;
4101 bool hasTypeAttribute = false;
4102 bool hasTypeSpecified = false;
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());
4110 attributeUse = reference;
4111 hasRefAttribute = true;
4112 } else {
4113 attributeUse = XsdAttributeUse::Ptr(new XsdAttributeUse());
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;
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;
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;
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;
4148 // parse attributes
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);
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;
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);
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;
4189 const XsdAttribute::Ptr attribute(new XsdAttribute());
4191 attributeUse->setAttribute(attribute);
4192 m_componentLocationHash.insert(attribute, currentSourceLocation());
4194 attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
4195 attribute->scope()->setVariety(XsdAttribute::Scope::Local);
4196 attribute->scope()->setParent(parent);
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
4204 const XsdAttributeReference::Ptr attributeReference = attributeUse;
4205 attributeReference->setReferenceName(referenceName);
4206 } else {
4207 if (hasAttribute(QString::fromLatin1("name"))) {
4208 const QString attributeName = readNameAttribute("attribute");
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;
4218 if (value == QString::fromLatin1("qualified")) {
4219 objectName = m_namePool->allocateQName(m_targetNamespace, attributeName);
4220 } else {
4221 objectName = m_namePool->allocateQName(QString(), attributeName);
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);
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"))) {
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;
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;
4251 attribute->setName(objectName);
4254 if (hasAttribute(QString::fromLatin1("type"))) {
4255 hasTypeAttribute = true;
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;
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()));
4269 attribute->valueConstraint()->setVariety((XsdAttribute::ValueConstraint::Variety)attributeUse->valueConstraint()->variety());
4270 attribute->valueConstraint()->setValue(attributeUse->valueConstraint()->value());
4271 attribute->valueConstraint()->setLexicalForm(attributeUse->valueConstraint()->lexicalForm());
4275 validateIdAttribute("attribute");
4277 TagValidationHandler tagValidator(XsdTagScope::LocalAttribute, this, m_namePool);
4279 while (!atEnd()) {
4280 readNext();
4282 if (isEndElement())
4283 break;
4285 if (isStartElement()) {
4286 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4287 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4289 tagValidator.validate(token);
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;
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;
4310 const XsdSimpleType::Ptr type = parseLocalSimpleType();
4311 type->setContext(attribute);
4312 attribute->setType(type);
4313 hasTypeSpecified = true;
4315 // add it to list of anonymous types as well
4316 addAnonymousType(type);
4317 } else {
4318 parseUnknown();
4323 if (!hasTypeSpecified) {
4324 attribute->setType(BuiltinTypes::xsAnySimpleType); // default value
4327 tagValidator.finalize();
4329 return attributeUse;
4332 XsdAttributeGroup::Ptr XsdSchemaParser::parseNamedAttributeGroup()
4334 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this);
4336 validateElement(XsdTagScope::NamedAttributeGroup);
4338 const XsdAttributeGroup::Ptr attributeGroup(new XsdAttributeGroup());
4340 // parse attributes
4341 const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("attributeGroup"));
4342 attributeGroup->setName(objectName);
4344 validateIdAttribute("attributeGroup");
4346 TagValidationHandler tagValidator(XsdTagScope::NamedAttributeGroup, this, m_namePool);
4348 while (!atEnd()) {
4349 readNext();
4351 if (isEndElement())
4352 break;
4354 if (isStartElement()) {
4355 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4356 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4358 tagValidator.validate(token);
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);
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);
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();
4383 tagValidator.finalize();
4385 return attributeGroup;
4388 XsdAttributeUse::Ptr XsdSchemaParser::parseReferredAttributeGroup()
4390 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this);
4392 validateElement(XsdTagScope::ReferredAttributeGroup);
4394 const XsdAttributeReference::Ptr attributeReference(new XsdAttributeReference());
4395 attributeReference->setType(XsdAttributeReference::AttributeGroup);
4396 attributeReference->setSourceLocation(currentSourceLocation());
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);
4404 validateIdAttribute("attributeGroup");
4406 TagValidationHandler tagValidator(XsdTagScope::ReferredAttributeGroup, this, m_namePool);
4408 while (!atEnd()) {
4409 readNext();
4411 if (isEndElement())
4412 break;
4414 if (isStartElement()) {
4415 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4416 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4418 tagValidator.validate(token);
4420 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
4421 const XsdAnnotation::Ptr annotation = parseAnnotation();
4422 attributeReference->addAnnotation(annotation);
4423 } else {
4424 parseUnknown();
4429 tagValidator.finalize();
4431 return attributeReference;
4434 XsdElement::Ptr XsdSchemaParser::parseGlobalElement()
4436 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this);
4438 validateElement(XsdTagScope::GlobalElement);
4440 const XsdElement::Ptr element(new XsdElement());
4441 element->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope()));
4442 element->scope()->setVariety(XsdElement::Scope::Global);
4444 bool hasTypeAttribute = false;
4445 bool hasTypeSpecified = false;
4446 bool hasSubstitutionGroup = false;
4448 // parse attributes
4449 const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("element"));
4450 element->setName(objectName);
4452 if (hasAttribute(QString::fromLatin1("abstract"))) {
4453 const QString abstract = readAttribute(QString::fromLatin1("abstract"));
4455 const Boolean::Ptr value = Boolean::fromLexical(abstract);
4456 if (value->hasError()) {
4457 attributeContentError("abstract", "element", abstract, BuiltinTypes::xsBoolean);
4458 return element;
4461 element->setIsAbstract(value->as<Boolean>()->value());
4462 } else {
4463 element->setIsAbstract(false); // the default value
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;
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);
4486 element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element"));
4487 element->setSubstitutionGroupExclusions(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "element"));
4489 if (hasAttribute(QString::fromLatin1("nillable"))) {
4490 const QString nillable = readAttribute(QString::fromLatin1("nillable"));
4492 const Boolean::Ptr value = Boolean::fromLexical(nillable);
4493 if (value->hasError()) {
4494 attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean);
4495 return element;
4498 element->setIsNillable(value->as<Boolean>()->value());
4499 } else {
4500 element->setIsNillable(false); // the default value
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
4509 hasTypeAttribute = true;
4510 hasTypeSpecified = true;
4513 if (hasAttribute(QString::fromLatin1("substitutionGroup"))) {
4514 QList<QXmlName> elementNames;
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;
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;
4530 QXmlName elementName;
4531 convertName(value, NamespaceSupport::ElementName, elementName); // translate qualified name into QXmlName
4532 elementNames.append(elementName);
4535 m_schemaResolver->addSubstitutionGroupAffiliation(element, elementNames, currentSourceLocation()); // add to resolver
4537 hasSubstitutionGroup = true;
4540 validateIdAttribute("element");
4542 XsdAlternative::List alternatives;
4544 TagValidationHandler tagValidator(XsdTagScope::GlobalElement, this, m_namePool);
4546 while (!atEnd()) {
4547 readNext();
4549 if (isEndElement())
4550 break;
4552 if (isStartElement()) {
4553 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4554 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4556 tagValidator.validate(token);
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;
4570 const XsdSimpleType::Ptr type = parseLocalSimpleType();
4571 type->setContext(element);
4572 element->setType(type);
4574 // add it to list of anonymous types as well
4575 addAnonymousType(type);
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;
4587 const XsdComplexType::Ptr type = parseLocalComplexType();
4588 type->setContext(element);
4589 element->setType(type);
4591 // add it to list of anonymous types as well
4592 addAnonymousType(type);
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();
4613 tagValidator.finalize();
4615 if (!hasTypeSpecified) {
4616 if (hasSubstitutionGroup)
4617 m_schemaResolver->addSubstitutionGroupType(element);
4618 else
4619 element->setType(BuiltinTypes::xsAnyType);
4622 if (!alternatives.isEmpty()) {
4623 element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
4625 for (int i = 0; i < alternatives.count(); ++i) {
4626 if (alternatives.at(i)->test())
4627 element->typeTable()->addAlternative(alternatives.at(i));
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
4639 element->typeTable()->setDefaultTypeDefinition(alternative);
4645 return element;
4648 XsdTerm::Ptr XsdSchemaParser::parseLocalElement(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
4650 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this);
4652 validateElement(XsdTagScope::LocalElement);
4654 bool hasRefAttribute = false;
4655 bool hasTypeAttribute = false;
4656 bool hasTypeSpecified = false;
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;
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;
4714 // parse attributes
4715 if (!parseMinMaxConstraint(particle, "element")) {
4716 return element;
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;
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
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);
4741 if (hasAttribute(QString::fromLatin1("name"))) {
4742 const QString elementName = readNameAttribute("element");
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;
4752 if (value == QString::fromLatin1("qualified")) {
4753 objectName = m_namePool->allocateQName(m_targetNamespace, elementName);
4754 } else {
4755 objectName = m_namePool->allocateQName(QString(), elementName);
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);
4765 element->setName(objectName);
4768 if (hasAttribute(QString::fromLatin1("nillable"))) {
4769 const QString nillable = readAttribute(QString::fromLatin1("nillable"));
4771 const Boolean::Ptr value = Boolean::fromLexical(nillable);
4772 if (value->hasError()) {
4773 attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean);
4774 return term;
4777 element->setIsNillable(value->as<Boolean>()->value());
4778 } else {
4779 element->setIsNillable(false); // the default value
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;
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);
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
4808 hasTypeAttribute = true;
4809 hasTypeSpecified = true;
4812 element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element"));
4815 validateIdAttribute("element");
4817 XsdAlternative::List alternatives;
4819 TagValidationHandler tagValidator(XsdTagScope::LocalElement, this, m_namePool);
4821 while (!atEnd()) {
4822 readNext();
4824 if (isEndElement())
4825 break;
4827 if (isStartElement()) {
4828 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4829 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4831 tagValidator.validate(token);
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;
4851 const XsdSimpleType::Ptr type = parseLocalSimpleType();
4852 type->setContext(element);
4853 element->setType(type);
4855 // add it to list of anonymous types as well
4856 addAnonymousType(type);
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;
4874 const XsdComplexType::Ptr type = parseLocalComplexType();
4875 type->setContext(element);
4876 element->setType(type);
4878 // add it to list of anonymous types as well
4879 addAnonymousType(type);
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;
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;
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;
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;
4924 const XsdIdentityConstraint::Ptr constraint = parseKeyRef(element);
4925 element->addIdentityConstraint(constraint);
4926 } else {
4927 parseUnknown();
4932 tagValidator.finalize();
4934 if (!hasTypeSpecified && !hasRefAttribute)
4935 element->setType(BuiltinTypes::xsAnyType);
4937 if (!hasRefAttribute && !alternatives.isEmpty()) {
4938 element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
4940 for (int i = 0; i < alternatives.count(); ++i) {
4941 if (alternatives.at(i)->test())
4942 element->typeTable()->addAlternative(alternatives.at(i));
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
4954 element->typeTable()->setDefaultTypeDefinition(alternative);
4960 return term;
4963 XsdIdentityConstraint::Ptr XsdSchemaParser::parseUnique()
4965 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Unique, this);
4967 validateElement(XsdTagScope::Unique);
4969 const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
4970 constraint->setCategory(XsdIdentityConstraint::Unique);
4972 // parse attributes
4973 const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("unique"));
4974 constraint->setName(objectName);
4976 validateIdAttribute("unique");
4978 TagValidationHandler tagValidator(XsdTagScope::Unique, this, m_namePool);
4980 while (!atEnd()) {
4981 readNext();
4983 if (isEndElement())
4984 break;
4986 if (isStartElement()) {
4987 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
4988 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
4990 tagValidator.validate(token);
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();
5005 // add constraint to schema for further checking
5006 addIdentityConstraint(constraint);
5008 tagValidator.finalize();
5010 return constraint;
5013 XsdIdentityConstraint::Ptr XsdSchemaParser::parseKey()
5015 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Key, this);
5017 validateElement(XsdTagScope::Key);
5019 const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
5020 constraint->setCategory(XsdIdentityConstraint::Key);
5022 // parse attributes
5023 const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("key"));
5024 constraint->setName(objectName);
5026 validateIdAttribute("key");
5028 TagValidationHandler tagValidator(XsdTagScope::Key, this, m_namePool);
5030 while (!atEnd()) {
5031 readNext();
5033 if (isEndElement())
5034 break;
5036 if (isStartElement()) {
5037 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5038 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5040 tagValidator.validate(token);
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();
5055 // add constraint to schema for further checking
5056 addIdentityConstraint(constraint);
5058 tagValidator.finalize();
5060 return constraint;
5063 XsdIdentityConstraint::Ptr XsdSchemaParser::parseKeyRef(const XsdElement::Ptr &element)
5065 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Keyref, this);
5067 validateElement(XsdTagScope::KeyRef);
5069 const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
5070 constraint->setCategory(XsdIdentityConstraint::KeyReference);
5072 // parse attributes
5073 const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("keyref"));
5074 constraint->setName(objectName);
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
5081 validateIdAttribute("keyref");
5083 TagValidationHandler tagValidator(XsdTagScope::KeyRef, this, m_namePool);
5085 while (!atEnd()) {
5086 readNext();
5088 if (isEndElement())
5089 break;
5091 if (isStartElement()) {
5092 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5093 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5095 tagValidator.validate(token);
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();
5110 // add constraint to schema for further checking
5111 addIdentityConstraint(constraint);
5113 tagValidator.finalize();
5115 return constraint;
5118 void XsdSchemaParser::parseSelector(const XsdIdentityConstraint::Ptr &ptr)
5120 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Selector, this);
5122 validateElement(XsdTagScope::Selector);
5124 // parse attributes
5125 const XsdXPathExpression::Ptr expression = readXPathExpression("selector");
5127 const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathSelector, "selector");
5128 expression->setExpression(xpath);
5130 ptr->setSelector(expression);
5132 validateIdAttribute("selector");
5134 TagValidationHandler tagValidator(XsdTagScope::Selector, this, m_namePool);
5136 while (!atEnd()) {
5137 readNext();
5139 if (isEndElement())
5140 break;
5142 if (isStartElement()) {
5143 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5144 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5146 tagValidator.validate(token);
5148 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5149 const XsdAnnotation::Ptr annotation = parseAnnotation();
5150 expression->addAnnotation(annotation);
5151 } else {
5152 parseUnknown();
5157 tagValidator.finalize();
5160 void XsdSchemaParser::parseField(const XsdIdentityConstraint::Ptr &ptr)
5162 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Field, this);
5164 validateElement(XsdTagScope::Field);
5166 // parse attributes
5167 const XsdXPathExpression::Ptr expression = readXPathExpression("field");
5169 const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathField, "field");
5170 expression->setExpression(xpath);
5172 ptr->addField(expression);
5174 validateIdAttribute("field");
5176 TagValidationHandler tagValidator(XsdTagScope::Field, this, m_namePool);
5178 while (!atEnd()) {
5179 readNext();
5181 if (isEndElement())
5182 break;
5184 if (isStartElement()) {
5185 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5186 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5188 tagValidator.validate(token);
5190 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5191 const XsdAnnotation::Ptr annotation = parseAnnotation();
5192 expression->addAnnotation(annotation);
5193 } else {
5194 parseUnknown();
5199 tagValidator.finalize();
5202 XsdAlternative::Ptr XsdSchemaParser::parseAlternative()
5204 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Alternative, this);
5206 validateElement(XsdTagScope::Alternative);
5208 const XsdAlternative::Ptr alternative(new XsdAlternative());
5210 bool hasTypeSpecified = false;
5212 if (hasAttribute(QString::fromLatin1("test"))) {
5213 const XsdXPathExpression::Ptr expression = readXPathExpression("alternative");
5215 const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "alternative");
5216 expression->setExpression(test);
5218 alternative->setTest(expression);
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
5227 hasTypeSpecified = true;
5230 validateIdAttribute("alternative");
5232 TagValidationHandler tagValidator(XsdTagScope::Alternative, this, m_namePool);
5234 while (!atEnd()) {
5235 readNext();
5237 if (isEndElement())
5238 break;
5240 if (isStartElement()) {
5241 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5242 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5244 tagValidator.validate(token);
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);
5253 // add it to list of anonymous types as well
5254 addAnonymousType(type);
5256 hasTypeSpecified = true;
5257 } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
5258 const XsdComplexType::Ptr type = parseLocalComplexType();
5259 alternative->setType(type);
5261 // add it to list of anonymous types as well
5262 addAnonymousType(type);
5264 hasTypeSpecified = true;
5265 } else {
5266 parseUnknown();
5271 tagValidator.finalize();
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;
5282 return alternative;
5285 XsdNotation::Ptr XsdSchemaParser::parseNotation()
5287 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Notation, this);
5289 validateElement(XsdTagScope::Notation);
5291 const XsdNotation::Ptr notation(new XsdNotation());
5293 // parse attributes
5294 const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("notation"));
5295 notation->setName(objectName);
5297 bool hasOptionalAttribute = false;
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;
5307 notation->setPublicId(publicId);
5310 hasOptionalAttribute = true;
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;
5320 if (!value.isEmpty()) {
5321 const AnyURI::Ptr systemId = AnyURI::fromLexical(value);
5322 notation->setSystemId(systemId);
5325 hasOptionalAttribute = true;
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;
5336 validateIdAttribute("notation");
5338 TagValidationHandler tagValidator(XsdTagScope::Notation, this, m_namePool);
5340 while (!atEnd()) {
5341 readNext();
5343 if (isEndElement())
5344 break;
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;
5353 if (isStartElement()) {
5354 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5355 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5357 tagValidator.validate(token);
5359 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5360 const XsdAnnotation::Ptr annotation = parseAnnotation();
5361 notation->addAnnotation(annotation);
5362 } else {
5363 parseUnknown();
5368 tagValidator.finalize();
5370 return notation;
5373 XsdWildcard::Ptr XsdSchemaParser::parseAny(const XsdParticle::Ptr &particle)
5375 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Any, this);
5377 validateElement(XsdTagScope::Any);
5379 const XsdWildcard::Ptr wildcard(new XsdWildcard());
5381 // parse attributes
5382 if (!parseMinMaxConstraint(particle, "any")) {
5383 return wildcard;
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;
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();
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();
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;
5427 if (!isValidUri(stringValue)) {
5428 attributeContentError("namespace", "any", stringValue, BuiltinTypes::xsAnyURI);
5429 return wildcard;
5433 wildcard->namespaceConstraint()->setNamespaces(newValues.toSet());
5435 } else {
5436 wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
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;
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);
5455 } else {
5456 wildcard->setProcessContents(XsdWildcard::Strict);
5459 validateIdAttribute("any");
5461 TagValidationHandler tagValidator(XsdTagScope::Any, this, m_namePool);
5463 while (!atEnd()) {
5464 readNext();
5466 if (isEndElement())
5467 break;
5469 if (isStartElement()) {
5470 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5471 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5473 tagValidator.validate(token);
5475 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5476 const XsdAnnotation::Ptr annotation = parseAnnotation();
5477 wildcard->addAnnotation(annotation);
5478 } else {
5479 parseUnknown();
5484 tagValidator.finalize();
5486 return wildcard;
5489 XsdWildcard::Ptr XsdSchemaParser::parseAnyAttribute()
5491 const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AnyAttribute, this);
5493 validateElement(XsdTagScope::AnyAttribute);
5495 const XsdWildcard::Ptr wildcard(new XsdWildcard());
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;
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();
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();
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;
5539 if (!isValidUri(stringValue)) {
5540 attributeContentError("namespace", "anyAttribute", stringValue, BuiltinTypes::xsAnyURI);
5541 return wildcard;
5545 wildcard->namespaceConstraint()->setNamespaces(newValues.toSet());
5547 } else {
5548 wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
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;
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);
5567 } else {
5568 wildcard->setProcessContents(XsdWildcard::Strict);
5571 validateIdAttribute("anyAttribute");
5573 TagValidationHandler tagValidator(XsdTagScope::AnyAttribute, this, m_namePool);
5575 while (!atEnd()) {
5576 readNext();
5578 if (isEndElement())
5579 break;
5581 if (isStartElement()) {
5582 const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
5583 const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
5585 tagValidator.validate(token);
5587 if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
5588 const XsdAnnotation::Ptr annotation = parseAnnotation();
5589 wildcard->addAnnotation(annotation);
5590 } else {
5591 parseUnknown();
5596 tagValidator.finalize();
5598 return wildcard;
5602 void XsdSchemaParser::parseUnknownDocumentation()
5604 Q_ASSERT(isStartElement());
5605 m_namespaceSupport.pushContext();
5606 m_namespaceSupport.setPrefixes(namespaceDeclarations());
5608 while (!atEnd()) {
5609 readNext();
5611 if (isEndElement())
5612 break;
5614 if (isStartElement())
5615 parseUnknownDocumentation();
5618 m_namespaceSupport.popContext();
5621 void XsdSchemaParser::parseUnknown()
5623 Q_ASSERT(isStartElement());
5624 m_namespaceSupport.pushContext();
5625 m_namespaceSupport.setPrefixes(namespaceDeclarations());
5627 error(QtXmlPatterns::tr("%1 element is not allowed in this context.").arg(formatElement(name().toString())));
5629 while (!atEnd()) {
5630 readNext();
5632 if (isEndElement())
5633 break;
5635 if (isStartElement())
5636 parseUnknown();
5639 m_namespaceSupport.popContext();
5642 bool XsdSchemaParser::parseMinMaxConstraint(const XsdParticle::Ptr &particle, const char *elementName)
5644 if (hasAttribute(QString::fromLatin1("minOccurs"))) {
5645 const QString value = readAttribute(QString::fromLatin1("minOccurs"));
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());
5654 } else {
5655 particle->setMinimumOccurs(1);
5658 if (hasAttribute(QString::fromLatin1("maxOccurs"))) {
5659 const QString value = readAttribute(QString::fromLatin1("maxOccurs"));
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());
5673 } else {
5674 particle->setMaximumOccursUnbounded(false);
5675 particle->setMaximumOccurs(1);
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;
5688 return true;
5691 QSourceLocation XsdSchemaParser::currentSourceLocation() const
5693 QSourceLocation location;
5694 location.setLine(lineNumber());
5695 location.setColumn(columnNumber());
5696 location.setUri(m_documentURI);
5698 return location;
5701 void XsdSchemaParser::convertName(const QString &qualifiedName, NamespaceSupport::NameType type, QXmlName &name)
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)));
5709 QString XsdSchemaParser::readNameAttribute(const char *elementName)
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;
5720 QString XsdSchemaParser::readQNameAttribute(const QString &typeAttribute, const char *elementName)
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;
5731 QString XsdSchemaParser::readNamespaceAttribute(const QString &attributeName, const char *elementName)
5733 const QString value = readAttribute(attributeName);
5734 if (value.isEmpty()) {
5735 attributeContentError(attributeName.toLatin1(), elementName, value, BuiltinTypes::xsAnyURI);
5736 return QString();
5739 return value;
5742 SchemaType::DerivationConstraints XsdSchemaParser::readDerivationConstraintAttribute(const SchemaType::DerivationConstraints &allowedConstraints, const char *elementName)
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"));
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"));
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();
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();
5777 } else {
5778 // content of the default value has been validated in parseSchema already
5779 content = m_finalDefault;
5782 QSet<QString> contentSet = content.split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
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);
5790 SchemaType::DerivationConstraints constraints;
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;
5801 return constraints;
5805 NamedSchemaComponent::BlockingConstraints XsdSchemaParser::readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints &allowedConstraints, const char *elementName)
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"));
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"));
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();
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();
5838 } else {
5839 // content of the default value has been validated in parseSchema already
5840 content = m_blockDefault;
5843 QSet<QString> contentSet = content.split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
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);
5851 NamedSchemaComponent::BlockingConstraints constraints;
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;
5860 return constraints;
5864 XsdXPathExpression::Ptr XsdSchemaParser::readXPathExpression(const char *elementName)
5866 const XsdXPathExpression::Ptr expression(new XsdXPathExpression());
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);
5875 expression->setNamespaceBindings(namespaceBindings);
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;
5888 } else {
5889 xpathDefaultNamespace = m_xpathDefaultNamespace;
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);
5904 if (namespaceURI) {
5905 if (namespaceURI->hasError()) {
5906 attributeContentError("xpathDefaultNamespace", elementName, xpathDefaultNamespace, BuiltinTypes::xsAnyURI);
5907 return expression;
5910 expression->setDefaultNamespace(namespaceURI);
5913 //TODO: read the base uri if qmaintaining reader support it
5915 return expression;
5918 QString XsdSchemaParser::readXPathAttribute(const QString &attributeName, XPathType type, const char *elementName)
5920 const QString value = readAttribute(attributeName);
5921 if (value.isEmpty() || value.startsWith(QLatin1Char('/'))) {
5922 attributeContentError(attributeName.toLatin1(), elementName, value);
5923 return QString();
5926 QXmlNamePool namePool(m_namePool.data());
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;
5935 QXmlQuery query(language, namePool);
5936 QXmlQueryPrivate *queryPrivate = query.d;
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));
5944 query.setQuery(value, m_documentURI);
5945 if (!query.isValid()) {
5946 attributeContentError(attributeName.toLatin1(), elementName, value);
5947 return QString();
5950 return value;
5953 void XsdSchemaParser::validateIdAttribute(const char *elementName)
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);
5970 bool XsdSchemaParser::isSchemaTag(XsdSchemaToken::NodeName tag, XsdSchemaToken::NodeName token, XsdSchemaToken::NodeName namespaceToken) const
5972 return ((tag == token) && (namespaceToken == XsdSchemaToken::XML_NS_SCHEMA_URI));
5975 void XsdSchemaParser::addElement(const XsdElement::Ptr &element)
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());
5986 void XsdSchemaParser::addAttribute(const XsdAttribute::Ptr &attribute)
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());
5997 void XsdSchemaParser::addType(const SchemaType::Ptr &type)
5999 // we don't import redefinitions of builtin types, that just causes problems
6000 if (m_builtinTypeNames.contains(type->name(m_namePool)))
6001 return;
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());
6015 void XsdSchemaParser::addAnonymousType(const SchemaType::Ptr &type)
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());
6024 void XsdSchemaParser::addAttributeGroup(const XsdAttributeGroup::Ptr &group)
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());
6035 void XsdSchemaParser::addElementGroup(const XsdModelGroup::Ptr &group)
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());
6046 void XsdSchemaParser::addNotation(const XsdNotation::Ptr &notation)
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());
6057 void XsdSchemaParser::addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint)
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());
6068 void XsdSchemaParser::addFacet(const XsdFacet::Ptr &facet, XsdFacet::Hash &facets, const SchemaType::Ptr &type)
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;
6076 facets.insert(facet->type(), facet);
6079 QT_END_NAMESPACE