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

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

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