source: trunk/src/xmlpatterns/schema/qxsdschemaparser.cpp@ 1054

Last change on this file since 1054 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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