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

source code of qtxmlpatterns/src/xmlpatterns/schema/qxsdschemaparser.cpp