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