1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qxsdschemaparser_p.h"
44 #include "private/qxmlutils_p.h"
45 #include "qacceltreeresourceloader_p.h"
46 #include "qautoptr_p.h"
47 #include "qboolean_p.h"
48 #include "qcommonnamespaces_p.h"
49 #include "qderivedinteger_p.h"
50 #include "qderivedstring_p.h"
51 #include "qqnamevalue_p.h"
52 #include "qxmlquery_p.h"
53 #include "qxpathhelper_p.h"
54 #include "qxsdattributereference_p.h"
55 #include "qxsdreference_p.h"
56 #include "qxsdschematoken_p.h"
58 #include <QtCore/QFile>
59 #include <QtXmlPatterns/QXmlQuery>
64 * @page schema_overview Overview
65 * @section structure_and_components Structure and Components
67 * The schema validator code consists of 4 major components
70 * <dt>The schema parser (QPatternist::XsdSchemaParser)</dt>
71 * <dd>This component parses a XML document that is supplied via a QIODevice. It creates
72 * a so called (incomplete) 'compiled schema', which is a representation of the XML Schema
73 * structure as C++ objects.
74 * As the parser is a streaming parser, it can't resolve references to types or elements/attributes
75 * in place, therefor it creates resolver tasks which are passed to the schema resolver component
76 * for resolving at a later point in time.
77 * The parser does furthermore the basic XML structure constraint checking, e.g. if all required
78 * attributes are available or the order of the elements is correct.</dd>
80 * <dt>The schema resolver (QPatternist::XsdSchemaResolver)</dt>
81 * <dd>This component is activated after the schema parser component has been finished the parsing
82 * of all schemas. The resolver has been supplied with resolve tasks by the schema parser that
83 * it will resolve in this step now. Between working on the single resolver tasks, the resolver
84 * calls check methods from the schema checker component to make sure that some assertions are
85 * valid (e.g. no circular inheritance of types), so that the resolver can work without hassle.
86 * During resoving references to attribute or element groups it also checks for circular references
88 * At the end of that phase we have a compiled schema that is fully resolved (not necessarily valid though).</dd>
90 * <dt>The schema checker (QPatternist::XsdSchemaChecker)</dt>
91 * <dd>This component does all the schema constraint checking as given by the Schema specification.
92 * At the end of that phase we have fully resolved and valid compiled schema that can be used for validation
93 * of instance documents.</dd>
95 * <dt>The validator (QPatternist::XsdValidatingInstanceReader)</dt>
96 * <dd>This component is responsible for validating a XML instance document, provided via a QIODevice, against
97 * a valid compiled schema.</dd>
100 * @ingroup Patternist_schema
103 using namespace QPatternist
;
105 namespace QPatternist
109 * @short A helper class for automatically handling namespace scopes of elements.
111 * This class should be instantiated at the beginning of each parse XYZ method.
113 class ElementNamespaceHandler
117 * Creates a new element namespace handler object.
119 * It checks whether the @p parser is on the right @p tag and it creates a new namespace
120 * context that contains the inherited and local namespace declarations.
122 ElementNamespaceHandler(const XsdSchemaToken::NodeName
&tag
, XsdSchemaParser
*parser
)
125 Q_ASSERT(m_parser
->isStartElement() && (XsdSchemaToken::toToken(m_parser
->name()) == tag
) && (XsdSchemaToken::toToken(m_parser
->namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI
));
127 m_parser
->m_namespaceSupport
.pushContext();
128 m_parser
->m_namespaceSupport
.setPrefixes(m_parser
->namespaceDeclarations());
132 * Destroys the element namespace handler object.
134 * It destroys the local namespace context.
136 ~ElementNamespaceHandler()
138 m_parser
->m_namespaceSupport
.popContext();
142 XsdSchemaParser
*m_parser
;
146 * A helper class that checks for the right occurrence of
147 * xml tags with the help of a DFA.
149 class TagValidationHandler
152 TagValidationHandler(XsdTagScope::Type tag
, XsdSchemaParser
*parser
, const NamePool::Ptr
&namePool
)
153 : m_parser(parser
), m_machine(namePool
)
155 Q_ASSERT(m_parser
->m_stateMachines
.contains(tag
));
157 m_machine
= m_parser
->m_stateMachines
.value(tag
);
161 void validate(XsdSchemaToken::NodeName token
)
163 if (token
== XsdSchemaToken::NoKeyword
) {
164 const QList
<XsdSchemaToken::NodeName
> tokens
= m_machine
.possibleTransitions();
166 QStringList elementNames
;
167 for (int i
= 0; i
< tokens
.count(); ++i
)
168 elementNames
.append(formatElement(XsdSchemaToken::toString(tokens
.at(i
))));
170 m_parser
->error(QtXmlPatterns::tr("Can not process unknown element %1, expected elements are: %2.")
171 .arg(formatElement(m_parser
->name().toString()))
172 .arg(elementNames
.join(QLatin1String(", "))));
176 if (!m_machine
.proceed(token
)) {
177 const QList
<XsdSchemaToken::NodeName
> tokens
= m_machine
.possibleTransitions();
179 QStringList elementNames
;
180 for (int i
= 0; i
< tokens
.count(); ++i
)
181 elementNames
.append(formatElement(XsdSchemaToken::toString(tokens
.at(i
))));
183 m_parser
->error(QtXmlPatterns::tr("Element %1 is not allowed in this scope, possible elements are: %2.")
184 .arg(formatElement(XsdSchemaToken::toString(token
)))
185 .arg(elementNames
.join(QLatin1String(", "))));
190 void finalize() const
192 if (!m_machine
.inEndState()) {
193 const QList
<XsdSchemaToken::NodeName
> tokens
= m_machine
.possibleTransitions();
195 QStringList elementNames
;
196 for (int i
= 0; i
< tokens
.count(); ++i
)
197 elementNames
.append(formatElement(XsdSchemaToken::toString(tokens
.at(i
))));
199 m_parser
->error(QtXmlPatterns::tr("Child element is missing in that scope, possible child elements are: %1.")
200 .arg(elementNames
.join(QLatin1String(", "))));
205 XsdSchemaParser
*m_parser
;
206 XsdStateMachine
<XsdSchemaToken::NodeName
> m_machine
;
212 * Returns a list of all particles with group references that appear at any level of
213 * the given unresolved @p group.
215 static XsdParticle::List
collectGroupRef(const XsdModelGroup::Ptr
&group
)
217 XsdParticle::List refParticles
;
219 XsdParticle::List particles
= group
->particles();
220 for (int i
= 0; i
< particles
.count(); ++i
) {
221 if (particles
.at(i
)->term()->isReference()) {
222 const XsdReference::Ptr
reference(particles
.at(i
)->term());
223 if (reference
->type() == XsdReference::ModelGroup
)
224 refParticles
.append(particles
.at(i
));
226 if (particles
.at(i
)->term()->isModelGroup()) {
227 refParticles
<< collectGroupRef(XsdModelGroup::Ptr(particles
.at(i
)->term()));
235 * Helper function that works around the limited facilities of
236 * QUrl/AnyURI::fromLexical to detect invalid URIs
238 inline static bool isValidUri(const QString
&string
)
240 // an empty URI points to the current document as defined in RFC 2396 (4.2)
241 if (string
.isEmpty())
244 // explicit check as that is not checked by the code below
245 if (string
.startsWith(QLatin1String("##")))
248 const AnyURI::Ptr uri
= AnyURI::fromLexical(string
);
249 return (!(uri
->hasError()));
252 XsdSchemaParser::XsdSchemaParser(const XsdSchemaContext::Ptr
&context
, const XsdSchemaParserContext::Ptr
&parserContext
, QIODevice
*device
)
253 : MaintainingReader
<XsdSchemaToken
, XsdTagScope::Type
>(parserContext
->elementDescriptions(), QSet
<XsdSchemaToken::NodeName
>(), context
, device
)
255 , m_parserContext(parserContext
)
256 , m_namePool(m_parserContext
->namePool())
257 , m_namespaceSupport(m_namePool
)
259 m_schema
= m_parserContext
->schema();
260 m_schemaResolver
= m_parserContext
->resolver();
261 m_idCache
= XsdIdCache::Ptr(new XsdIdCache());
263 setupStateMachines();
264 setupBuiltinTypeNames();
267 void XsdSchemaParser::setIncludedSchemas(const NamespaceSet
&schemas
)
269 m_includedSchemas
= schemas
;
272 void XsdSchemaParser::setImportedSchemas(const NamespaceSet
&schemas
)
274 m_importedSchemas
= schemas
;
277 void XsdSchemaParser::setRedefinedSchemas(const NamespaceSet
&schemas
)
279 m_redefinedSchemas
= schemas
;
282 void XsdSchemaParser::setTargetNamespace(const QString
&targetNamespace
)
284 m_targetNamespace
= targetNamespace
;
287 void XsdSchemaParser::setTargetNamespaceExtended(const QString
&targetNamespace
)
289 m_targetNamespace
= targetNamespace
;
290 m_namespaceSupport
.setTargetNamespace(m_namePool
->allocateNamespace(m_targetNamespace
));
293 void XsdSchemaParser::setDocumentURI(const QUrl
&uri
)
297 // prevent to get included/imported/redefined twice
298 m_includedSchemas
.insert(uri
);
299 m_importedSchemas
.insert(uri
);
302 QUrl
XsdSchemaParser::documentURI() const
304 return m_documentURI
;
307 bool XsdSchemaParser::isAnyAttributeAllowed() const
312 bool XsdSchemaParser::parse(ParserType parserType
)
314 m_componentLocationHash
.clear();
319 if (isStartElement()) {
320 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
321 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
323 if (isSchemaTag(XsdSchemaToken::Schema
, token
, namespaceToken
)) {
324 parseSchema(parserType
);
326 error(QtXmlPatterns::tr("Document is not a XML schema."));
331 m_schemaResolver
->addComponentLocationHash(m_componentLocationHash
);
332 m_schemaResolver
->setDefaultOpenContent(m_defaultOpenContent
, m_defaultOpenContentAppliesToEmpty
);
334 if (QXmlStreamReader::error() != QXmlStreamReader::NoError
)
335 error(errorString());
340 void XsdSchemaParser::error(const QString
&msg
)
342 MaintainingReader
<XsdSchemaToken
, XsdTagScope::Type
>::error(msg
, XsdSchemaContext::XSDError
);
345 void XsdSchemaParser::attributeContentError(const char *attributeName
, const char *elementName
, const QString
&value
, const SchemaType::Ptr
&type
)
348 error(QtXmlPatterns::tr("%1 attribute of %2 element contains invalid content: {%3} is not a value of type %4.")
349 .arg(formatAttribute(attributeName
))
350 .arg(formatElement(elementName
))
351 .arg(formatData(value
))
352 .arg(formatType(m_namePool
, type
)));
354 error(QtXmlPatterns::tr("%1 attribute of %2 element contains invalid content: {%3}.")
355 .arg(formatAttribute(attributeName
))
356 .arg(formatElement(elementName
))
357 .arg(formatData(value
)));
361 void XsdSchemaParser::parseSchema(ParserType parserType
)
363 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Schema
, this);
365 validateElement(XsdTagScope::Schema
);
369 if (parserType
== TopLevelParser
) {
370 if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
371 m_targetNamespace
= readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
373 } else if (parserType
== IncludeParser
) {
374 // m_targetNamespace is set to the target namespace of the including schema at this point
376 if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
377 const QString targetNamespace
= readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
379 if (m_targetNamespace
!= targetNamespace
) {
380 error(QtXmlPatterns::tr("Target namespace %1 of included schema is different from the target namespace %2 as defined by the including schema.")
381 .arg(formatURI(targetNamespace
)).arg(formatURI(m_targetNamespace
)));
385 } else if (parserType
== ImportParser
) {
386 // m_targetNamespace is set to the target namespace from the namespace attribute of the <import> tag at this point
388 QString targetNamespace
;
389 if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
390 targetNamespace
= readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
393 if (m_targetNamespace
!= targetNamespace
) {
394 error(QtXmlPatterns::tr("Target namespace %1 of imported schema is different from the target namespace %2 as defined by the importing schema.")
395 .arg(formatURI(targetNamespace
)).arg(formatURI(m_targetNamespace
)));
398 } else if (parserType
== RedefineParser
) {
399 // m_targetNamespace is set to the target namespace of the redefining schema at this point
401 if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
402 const QString targetNamespace
= readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
404 if (m_targetNamespace
!= targetNamespace
) {
405 error(QtXmlPatterns::tr("Target namespace %1 of imported schema is different from the target namespace %2 as defined by the importing schema.")
406 .arg(formatURI(targetNamespace
)).arg(formatURI(m_targetNamespace
)));
412 if (hasAttribute(QString::fromLatin1("attributeFormDefault"))) {
413 const QString value
= readAttribute(QString::fromLatin1("attributeFormDefault"));
414 if (value
!= QString::fromLatin1("qualified") && value
!= QString::fromLatin1("unqualified")) {
415 attributeContentError("attributeFormDefault", "schema", value
);
419 m_attributeFormDefault
= value
;
421 m_attributeFormDefault
= QString::fromLatin1("unqualified");
424 if (hasAttribute(QString::fromLatin1("elementFormDefault"))) {
425 const QString value
= readAttribute(QString::fromLatin1("elementFormDefault"));
426 if (value
!= QString::fromLatin1("qualified") && value
!= QString::fromLatin1("unqualified")) {
427 attributeContentError("elementFormDefault", "schema", value
);
431 m_elementFormDefault
= value
;
433 m_elementFormDefault
= QString::fromLatin1("unqualified");
436 if (hasAttribute(QString::fromLatin1("blockDefault"))) {
437 const QString blockDefault
= readAttribute(QString::fromLatin1("blockDefault"));
438 const QStringList blockDefaultList
= blockDefault
.split(QLatin1Char(' '), QString::SkipEmptyParts
);
439 for (int i
= 0; i
< blockDefaultList
.count(); ++i
) {
440 const QString value
= blockDefaultList
.at(i
);
441 if (value
!= QString::fromLatin1("#all") &&
442 value
!= QString::fromLatin1("extension") &&
443 value
!= QString::fromLatin1("restriction") &&
444 value
!= QString::fromLatin1("substitution")) {
445 attributeContentError("blockDefault", "schema", value
);
450 m_blockDefault
= blockDefault
;
453 if (hasAttribute(QString::fromLatin1("finalDefault"))) {
454 const QString finalDefault
= readAttribute(QString::fromLatin1("finalDefault"));
455 const QStringList finalDefaultList
= finalDefault
.split(QLatin1Char(' '), QString::SkipEmptyParts
);
456 for (int i
= 0; i
< finalDefaultList
.count(); ++i
) {
457 const QString value
= finalDefaultList
.at(i
);
458 if (value
!= QString::fromLatin1("#all") &&
459 value
!= QString::fromLatin1("extension") &&
460 value
!= QString::fromLatin1("restriction") &&
461 value
!= QString::fromLatin1("list") &&
462 value
!= QString::fromLatin1("union")) {
463 attributeContentError("finalDefault", "schema", value
);
468 m_finalDefault
= finalDefault
;
471 if (hasAttribute(QString::fromLatin1("xpathDefaultNamespace"))) {
472 const QString xpathDefaultNamespace
= readAttribute(QString::fromLatin1("xpathDefaultNamespace"));
473 if (xpathDefaultNamespace
!= QString::fromLatin1("##defaultNamespace") &&
474 xpathDefaultNamespace
!= QString::fromLatin1("##targetNamespace") &&
475 xpathDefaultNamespace
!= QString::fromLatin1("##local")) {
476 if (!isValidUri(xpathDefaultNamespace
)) {
477 attributeContentError("xpathDefaultNamespace", "schema", xpathDefaultNamespace
);
481 m_xpathDefaultNamespace
= xpathDefaultNamespace
;
483 m_xpathDefaultNamespace
= QString::fromLatin1("##local");
486 if (hasAttribute(QString::fromLatin1("defaultAttributes"))) {
487 const QString attrGroupName
= readQNameAttribute(QString::fromLatin1("defaultAttributes"), "schema");
488 convertName(attrGroupName
, NamespaceSupport::ElementName
, m_defaultAttributes
); // translate qualified name into QXmlName
491 if (hasAttribute(QString::fromLatin1("version"))) {
492 const QString version
= readAttribute(QString::fromLatin1("version"));
495 if (hasAttribute(CommonNamespaces::XML
, QString::fromLatin1("lang"))) {
496 const QString value
= readAttribute(QString::fromLatin1("lang"), CommonNamespaces::XML
);
498 const QRegExp
exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*"));
499 if (!exp
.exactMatch(value
)) {
500 attributeContentError("xml:lang", "schema", value
);
505 validateIdAttribute("schema");
507 TagValidationHandler
tagValidator(XsdTagScope::Schema
, this, m_namePool
);
515 if (isStartElement()) {
516 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
517 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
519 tagValidator
.validate(token
);
521 if (isSchemaTag(XsdSchemaToken::Include
, token
, namespaceToken
)) {
523 } else if (isSchemaTag(XsdSchemaToken::Import
, token
, namespaceToken
)) {
525 } else if (isSchemaTag(XsdSchemaToken::Redefine
, token
, namespaceToken
)) {
527 } else if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
528 const XsdAnnotation::Ptr annotation
= parseAnnotation();
529 m_schema
->addAnnotation(annotation
);
530 } else if (isSchemaTag(XsdSchemaToken::DefaultOpenContent
, token
, namespaceToken
)) {
531 parseDefaultOpenContent();
532 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
533 const XsdSimpleType::Ptr type
= parseGlobalSimpleType();
535 } else if (isSchemaTag(XsdSchemaToken::ComplexType
, token
, namespaceToken
)) {
536 const XsdComplexType::Ptr type
= parseGlobalComplexType();
538 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
539 const XsdModelGroup::Ptr group
= parseNamedGroup();
540 addElementGroup(group
);
541 } else if (isSchemaTag(XsdSchemaToken::AttributeGroup
, token
, namespaceToken
)) {
542 XsdAttributeGroup::Ptr attributeGroup
= parseNamedAttributeGroup();
543 addAttributeGroup(attributeGroup
);
544 } else if (isSchemaTag(XsdSchemaToken::Element
, token
, namespaceToken
)) {
545 const XsdElement::Ptr element
= parseGlobalElement();
547 } else if (isSchemaTag(XsdSchemaToken::Attribute
, token
, namespaceToken
)) {
548 const XsdAttribute::Ptr attribute
= parseGlobalAttribute();
549 addAttribute(attribute
);
550 } else if (isSchemaTag(XsdSchemaToken::Notation
, token
, namespaceToken
)) {
551 const XsdNotation::Ptr notation
= parseNotation();
552 addNotation(notation
);
559 tagValidator
.finalize();
561 m_schema
->setTargetNamespace(m_targetNamespace
);
564 void XsdSchemaParser::parseInclude()
566 Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Include
&&
567 XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI
);
569 validateElement(XsdTagScope::Include
);
572 const QString schemaLocation
= readAttribute(QString::fromLatin1("schemaLocation"));
574 QUrl
url(schemaLocation
);
575 if (url
.isRelative()) {
576 Q_ASSERT(m_documentURI
.isValid());
578 url
= m_documentURI
.resolved(url
);
581 if (m_includedSchemas
.contains(url
)) {
582 // we have included that file already, according to the schema spec we are
583 // allowed to silently skip it.
585 m_includedSchemas
.insert(url
);
587 const AutoPtr
<QNetworkReply
> reply(AccelTreeResourceLoader::load(url
, m_context
->networkAccessManager(),
588 m_context
, AccelTreeResourceLoader::ContinueOnError
));
590 // parse the included schema by a different parser but with the same context
591 XsdSchemaParser
parser(m_context
, m_parserContext
, reply
.data());
592 parser
.setDocumentURI(url
);
593 parser
.setTargetNamespaceExtended(m_targetNamespace
);
594 parser
.setIncludedSchemas(m_includedSchemas
);
595 parser
.setImportedSchemas(m_importedSchemas
);
596 parser
.setRedefinedSchemas(m_redefinedSchemas
);
597 if (!parser
.parse(XsdSchemaParser::IncludeParser
))
602 validateIdAttribute("include");
604 TagValidationHandler
tagValidator(XsdTagScope::Include
, this, m_namePool
);
612 if (isStartElement()) {
613 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
614 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
616 tagValidator
.validate(token
);
618 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
619 const XsdAnnotation::Ptr annotation
= parseAnnotation();
620 m_schema
->addAnnotation(annotation
);
627 tagValidator
.finalize();
630 void XsdSchemaParser::parseImport()
632 Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Import
&&
633 XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI
);
635 validateElement(XsdTagScope::Import
);
638 QString importNamespace
;
639 if (hasAttribute(QString::fromLatin1("namespace"))) {
640 importNamespace
= readAttribute(QString::fromLatin1("namespace"));
641 if (importNamespace
== m_targetNamespace
) {
642 error(QtXmlPatterns::tr("%1 element is not allowed to have the same %2 attribute value as the target namespace %3.")
643 .arg(formatElement("import"))
644 .arg(formatAttribute("namespace"))
645 .arg(formatURI(m_targetNamespace
)));
649 if (m_targetNamespace
.isEmpty()) {
650 error(QtXmlPatterns::tr("%1 element without %2 attribute is not allowed inside schema without target namespace.")
651 .arg(formatElement("import"))
652 .arg(formatAttribute("namespace")));
657 if (hasAttribute(QString::fromLatin1("schemaLocation"))) {
658 const QString schemaLocation
= readAttribute(QString::fromLatin1("schemaLocation"));
660 QUrl
url(schemaLocation
);
661 if (url
.isRelative()) {
662 Q_ASSERT(m_documentURI
.isValid());
664 url
= m_documentURI
.resolved(url
);
667 if (m_importedSchemas
.contains(url
)) {
668 // we have imported that file already, according to the schema spec we are
669 // allowed to silently skip it.
671 m_importedSchemas
.insert(url
);
673 // as it is possible that well known schemas (e.g. XSD for XML) are only referenced by
674 // namespace we should add it as well
675 m_importedSchemas
.insert(importNamespace
);
677 AutoPtr
<QNetworkReply
> reply(AccelTreeResourceLoader::load(url
, m_context
->networkAccessManager(),
678 m_context
, AccelTreeResourceLoader::ContinueOnError
));
680 // parse the included schema by a different parser but with the same context
681 XsdSchemaParser
parser(m_context
, m_parserContext
, reply
.data());
682 parser
.setDocumentURI(url
);
683 parser
.setTargetNamespace(importNamespace
);
684 parser
.setIncludedSchemas(m_includedSchemas
);
685 parser
.setImportedSchemas(m_importedSchemas
);
686 parser
.setRedefinedSchemas(m_redefinedSchemas
);
687 if (!parser
.parse(XsdSchemaParser::ImportParser
))
692 // check whether it is a known namespace we have a builtin schema for
693 if (!importNamespace
.isEmpty()) {
694 if (!m_importedSchemas
.contains(importNamespace
)) {
695 m_importedSchemas
.insert(importNamespace
);
697 QFile
file(QString::fromLatin1(":") + importNamespace
);
698 if (file
.open(QIODevice::ReadOnly
)) {
699 XsdSchemaParser
parser(m_context
, m_parserContext
, &file
);
700 parser
.setDocumentURI(importNamespace
);
701 parser
.setTargetNamespace(importNamespace
);
702 parser
.setIncludedSchemas(m_includedSchemas
);
703 parser
.setImportedSchemas(m_importedSchemas
);
704 parser
.setRedefinedSchemas(m_redefinedSchemas
);
705 if (!parser
.parse(XsdSchemaParser::ImportParser
))
710 // we don't import anything... that is valid according to the schema
714 validateIdAttribute("import");
716 TagValidationHandler
tagValidator(XsdTagScope::Import
, this, m_namePool
);
724 if (isStartElement()) {
725 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
726 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
728 tagValidator
.validate(token
);
730 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
731 const XsdAnnotation::Ptr annotation
= parseAnnotation();
732 m_schema
->addAnnotation(annotation
);
739 tagValidator
.finalize();
742 void XsdSchemaParser::parseRedefine()
744 Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Redefine
&&
745 XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI
);
747 validateElement(XsdTagScope::Redefine
);
750 validateIdAttribute("redefine");
752 const QString schemaLocation
= readAttribute(QString::fromLatin1("schemaLocation"));
754 TagValidationHandler
tagValidator(XsdTagScope::Redefine
, this, m_namePool
);
756 XsdSimpleType::List redefinedSimpleTypes
;
757 XsdComplexType::List redefinedComplexTypes
;
758 XsdModelGroup::List redefinedGroups
;
759 XsdAttributeGroup::List redefinedAttributeGroups
;
767 if (isStartElement()) {
768 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
769 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
771 tagValidator
.validate(token
);
773 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
774 const XsdAnnotation::Ptr annotation
= parseAnnotation();
775 m_schema
->addAnnotation(annotation
);
776 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
777 const XsdSimpleType::Ptr type
= parseGlobalSimpleType();
778 redefinedSimpleTypes
.append(type
);
780 const QXmlName baseTypeName
= m_parserContext
->resolver()->baseTypeNameOfType(type
);
781 if (baseTypeName
!= type
->name(m_namePool
)) {
782 error(QString::fromLatin1("redefined simple type %1 must have itself as base type").arg(formatType(m_namePool
, type
)));
785 } else if (isSchemaTag(XsdSchemaToken::ComplexType
, token
, namespaceToken
)) {
786 const XsdComplexType::Ptr type
= parseGlobalComplexType();
787 redefinedComplexTypes
.append(type
);
789 // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
792 const QXmlName baseTypeName
= m_parserContext
->resolver()->baseTypeNameOfType(type
);
793 if (baseTypeName
!= type
->name(m_namePool
)) {
794 error(QString::fromLatin1("redefined complex type %1 must have itself as base type").arg(formatType(m_namePool
, type
)));
797 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
798 const XsdModelGroup::Ptr group
= parseNamedGroup();
799 redefinedGroups
.append(group
);
800 } else if (isSchemaTag(XsdSchemaToken::AttributeGroup
, token
, namespaceToken
)) {
801 const XsdAttributeGroup::Ptr group
= parseNamedAttributeGroup();
802 redefinedAttributeGroups
.append(group
);
810 bool locationMustResolve
= false;
811 if (!redefinedSimpleTypes
.isEmpty() || !redefinedComplexTypes
.isEmpty() ||
812 !redefinedGroups
.isEmpty() || !redefinedAttributeGroups
.isEmpty()) {
813 locationMustResolve
= true;
816 QUrl
url(schemaLocation
);
817 if (url
.isRelative()) {
818 Q_ASSERT(m_documentURI
.isValid());
820 url
= m_documentURI
.resolved(url
);
823 // we parse the schema given in the redefine tag into its own context
824 const XsdSchemaParserContext::Ptr
redefinedContext(new XsdSchemaParserContext(m_namePool
, m_context
));
826 if (m_redefinedSchemas
.contains(url
)) {
827 // we have redefined that file already, according to the schema spec we are
828 // allowed to silently skip it.
830 m_redefinedSchemas
.insert(url
);
831 QNetworkReply
*reply
= AccelTreeResourceLoader::load(url
, m_context
->networkAccessManager(),
833 (locationMustResolve
? AccelTreeResourceLoader::FailOnError
: AccelTreeResourceLoader::ContinueOnError
));
835 // parse the included schema by a different parser but with the same context
836 XsdSchemaParser
parser(m_context
, redefinedContext
, reply
);
837 parser
.setDocumentURI(url
);
838 parser
.setTargetNamespaceExtended(m_targetNamespace
);
839 parser
.setIncludedSchemas(m_includedSchemas
);
840 parser
.setImportedSchemas(m_importedSchemas
);
841 parser
.setRedefinedSchemas(m_redefinedSchemas
);
842 if (!parser
.parse(XsdSchemaParser::RedefineParser
))
849 XsdSimpleType::List contextSimpleTypes
= redefinedContext
->schema()->simpleTypes();
850 XsdComplexType::List contextComplexTypes
= redefinedContext
->schema()->complexTypes();
851 XsdModelGroup::List contextGroups
= redefinedContext
->schema()->elementGroups();
852 XsdAttributeGroup::List contextAttributeGroups
= redefinedContext
->schema()->attributeGroups();
854 // now we do the actual redefinition:
856 // iterate over all redefined simple types
857 for (int i
= 0; i
< redefinedSimpleTypes
.count(); ++i
) {
858 XsdSimpleType::Ptr redefinedType
= redefinedSimpleTypes
.at(i
);
860 //TODONEXT: validation
862 // search the definition they override in the context types
864 for (int j
= 0; j
< contextSimpleTypes
.count(); ++j
) {
865 XsdSimpleType::Ptr contextType
= contextSimpleTypes
.at(j
);
867 if (redefinedType
->name(m_namePool
) == contextType
->name(m_namePool
)) { // we found the right type
870 // 1) set name of context type to empty name
871 contextType
->setName(m_parserContext
->createAnonymousName(QString()));
873 // 2) set the context type as base type for the redefined type
874 redefinedType
->setWxsSuperType(contextType
);
876 // 3) remove the base type resolving job from the resolver as
877 // we have set the base type here explicitely
878 m_parserContext
->resolver()->removeSimpleRestrictionBase(redefinedType
);
880 // 4) add the redefined type to the schema
881 addType(redefinedType
);
883 // 5) add the context type as anonymous type, so the resolver
884 // can resolve it further.
885 addAnonymousType(contextType
);
887 // 6) remove the context type from the list
888 contextSimpleTypes
.removeAt(j
);
895 error(QString::fromLatin1("no matching type found to redefine simple type %1").arg(formatType(m_namePool
, redefinedType
)));
900 // add all remaining context simple types to the schema
901 for (int i
= 0; i
< contextSimpleTypes
.count(); ++i
) {
902 addType(contextSimpleTypes
.at(i
));
905 // iterate over all redefined complex types
906 for (int i
= 0; i
< redefinedComplexTypes
.count(); ++i
) {
907 XsdComplexType::Ptr redefinedType
= redefinedComplexTypes
.at(i
);
909 //TODONEXT: validation
911 // search the definition they override in the context types
913 for (int j
= 0; j
< contextComplexTypes
.count(); ++j
) {
914 XsdComplexType::Ptr contextType
= contextComplexTypes
.at(j
);
916 if (redefinedType
->name(m_namePool
) == contextType
->name(m_namePool
)) { // we found the right type
919 // 1) set name of context type to empty name
920 contextType
->setName(m_parserContext
->createAnonymousName(QString()));
922 // 2) set the context type as base type for the redefined type
923 redefinedType
->setWxsSuperType(contextType
);
925 // 3) remove the base type resolving job from the resolver as
926 // we have set the base type here explicitely
927 m_parserContext
->resolver()->removeComplexBaseType(redefinedType
);
929 // 4) add the redefined type to the schema
930 addType(redefinedType
);
932 // 5) add the context type as anonymous type, so the resolver
933 // can resolve its attribute uses etc.
934 addAnonymousType(contextType
);
936 // 6) remove the context type from the list
937 contextComplexTypes
.removeAt(j
);
944 error(QString::fromLatin1("no matching type found to redefine complex type %1").arg(formatType(m_namePool
, redefinedType
)));
949 // iterate over all redefined element groups
950 for (int i
= 0; i
< redefinedGroups
.count(); ++i
) {
951 const XsdModelGroup::Ptr
group(redefinedGroups
.at(i
));
953 // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
956 const XsdParticle::List particles
= collectGroupRef(group
);
957 XsdParticle::Ptr referencedParticle
;
958 int sameNameCounter
= 0;
959 for (int i
= 0; i
< particles
.count(); ++i
) {
960 const XsdReference::Ptr
ref(particles
.at(i
)->term());
961 if (ref
->referenceName() == group
->name(m_namePool
)) {
962 referencedParticle
= particles
.at(i
);
964 if (referencedParticle
->minimumOccurs() != 1 || referencedParticle
->maximumOccurs() != 1 || referencedParticle
->maximumOccursUnbounded()) { // 6.1.2
965 error(QString::fromLatin1("redefined group %1 can not contain reference to itself with minOccurs or maxOccurs != 1").arg(formatKeyword(group
->displayName(m_namePool
))));
973 if (sameNameCounter
> 1) {
974 error(QString::fromLatin1("redefined group %1 can not contain multiple references to itself").arg(formatKeyword(group
->displayName(m_namePool
))));
978 // search the group definition in the included schema (S2)
979 XsdModelGroup::Ptr contextGroup
;
980 for (int j
= 0; j
< contextGroups
.count(); ++j
) {
981 if (group
->name(m_namePool
) == contextGroups
.at(j
)->name(m_namePool
)) {
982 contextGroup
= contextGroups
.at(j
);
987 if (!contextGroup
) { // 6.2.1
988 error(QString::fromLatin1("redefined group %1 has no occurrence in included schema").arg(formatKeyword(group
->displayName(m_namePool
))));
992 if (sameNameCounter
== 1) {
993 // there was a self reference in the redefined group, so use the
994 // group from the included schema
996 // set a anonymous name to the group of the included schema
997 contextGroup
->setName(m_parserContext
->createAnonymousName(m_namePool
->stringForNamespace(contextGroup
->name(m_namePool
).namespaceURI())));
999 // replace the self-reference with the group from the included schema
1000 referencedParticle
->setTerm(contextGroup
);
1002 addElementGroup(group
);
1004 addElementGroup(contextGroup
);
1005 contextGroups
.removeAll(contextGroup
);
1007 // there was no self reference in the redefined group
1009 // just add the redefined group...
1010 addElementGroup(group
);
1012 // we have to add them, otherwise it is not resolved and we can't validate it later
1013 contextGroup
->setName(m_parserContext
->createAnonymousName(m_namePool
->stringForNamespace(contextGroup
->name(m_namePool
).namespaceURI())));
1014 addElementGroup(contextGroup
);
1016 m_schemaResolver
->addRedefinedGroups(group
, contextGroup
);
1018 // ...and forget about the group from the included schema
1019 contextGroups
.removeAll(contextGroup
);
1023 // iterate over all redefined attribute groups
1024 for (int i
= 0; i
< redefinedAttributeGroups
.count(); ++i
) {
1025 const XsdAttributeGroup::Ptr
group(redefinedAttributeGroups
.at(i
));
1027 // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
1032 int sameNameCounter
= 0;
1033 for (int j
= 0; j
< group
->attributeUses().count(); ++j
) {
1034 const XsdAttributeUse::Ptr
attributeUse(group
->attributeUses().at(j
));
1035 if (attributeUse
->isReference()) {
1036 const XsdAttributeReference::Ptr
reference(attributeUse
);
1037 if (reference
->type() == XsdAttributeReference::AttributeGroup
) {
1038 if (group
->name(m_namePool
) == reference
->referenceName())
1043 if (sameNameCounter
> 1) {
1044 error(QString::fromLatin1("redefined attribute group %1 can not contain multiple references to itself").arg(formatKeyword(group
->displayName(m_namePool
))));
1048 // search the attribute group definition in the included schema (S2)
1049 XsdAttributeGroup::Ptr baseGroup
;
1050 for (int j
= 0; j
< contextAttributeGroups
.count(); ++j
) {
1051 const XsdAttributeGroup::Ptr
contextGroup(contextAttributeGroups
.at(j
));
1052 if (group
->name(m_namePool
) == contextGroup
->name(m_namePool
)) {
1053 baseGroup
= contextGroup
;
1058 if (!baseGroup
) { // 7.2.1
1059 error(QString::fromLatin1("redefined attribute group %1 has no occurrence in included schema").arg(formatKeyword(group
->displayName(m_namePool
))));
1063 if (sameNameCounter
== 1) {
1065 // first set an anonymous name to the attribute group from the included
1067 baseGroup
->setName(m_parserContext
->createAnonymousName(m_namePool
->stringForNamespace(baseGroup
->name(m_namePool
).namespaceURI())));
1069 // iterate over the attribute uses of the redefined attribute group
1070 // and replace the self-reference with the attribute group from the
1072 for (int j
= 0; j
< group
->attributeUses().count(); ++j
) {
1073 const XsdAttributeUse::Ptr
attributeUse(group
->attributeUses().at(j
));
1074 if (attributeUse
->isReference()) {
1075 const XsdAttributeReference::Ptr
reference(attributeUse
);
1076 if (reference
->type() == XsdAttributeReference::AttributeGroup
) {
1077 if (group
->name(m_namePool
) == reference
->referenceName()) {
1078 reference
->setReferenceName(baseGroup
->name(m_namePool
));
1085 // add both groups to the target schema
1086 addAttributeGroup(baseGroup
);
1087 addAttributeGroup(group
);
1089 contextAttributeGroups
.removeAll(baseGroup
);
1092 if (sameNameCounter
== 0) { // 7.2
1094 // we have to add them, otherwise it is not resolved and we can't validate it later
1095 baseGroup
->setName(m_parserContext
->createAnonymousName(m_namePool
->stringForNamespace(baseGroup
->name(m_namePool
).namespaceURI())));
1096 addAttributeGroup(baseGroup
);
1098 m_schemaResolver
->addRedefinedAttributeGroups(group
, baseGroup
);
1100 // just add the redefined attribute group to the target schema...
1101 addAttributeGroup(group
);
1103 // ... and forget about the one from the included schema
1104 contextAttributeGroups
.removeAll(baseGroup
);
1108 // add all remaining context complex types to the schema
1109 for (int i
= 0; i
< contextComplexTypes
.count(); ++i
) {
1110 addType(contextComplexTypes
.at(i
));
1113 // add all remaining context element groups to the schema
1114 for (int i
= 0; i
< contextGroups
.count(); ++i
) {
1115 addElementGroup(contextGroups
.at(i
));
1118 // add all remaining context attribute groups to the schema
1119 for (int i
= 0; i
< contextAttributeGroups
.count(); ++i
) {
1120 addAttributeGroup(contextAttributeGroups
.at(i
));
1123 // copy all elements, attributes and notations
1124 const XsdElement::List contextElements
= redefinedContext
->schema()->elements();
1125 for (int i
= 0; i
< contextElements
.count(); ++i
) {
1126 addElement(contextElements
.at(i
));
1129 const XsdAttribute::List contextAttributes
= redefinedContext
->schema()->attributes();
1130 for (int i
= 0; i
< contextAttributes
.count(); ++i
) {
1131 addAttribute(contextAttributes
.at(i
));
1134 const XsdNotation::List contextNotations
= redefinedContext
->schema()->notations();
1135 for (int i
= 0; i
< contextNotations
.count(); ++i
) {
1136 addNotation(contextNotations
.at(i
));
1139 // push all data to resolve from the context resolver to our resolver
1140 redefinedContext
->resolver()->copyDataTo(m_parserContext
->resolver());
1142 tagValidator
.finalize();
1145 XsdAnnotation::Ptr
XsdSchemaParser::parseAnnotation()
1147 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Annotation
, this);
1149 validateElement(XsdTagScope::Annotation
);
1152 validateIdAttribute("annotation");
1154 TagValidationHandler
tagValidator(XsdTagScope::Annotation
, this, m_namePool
);
1156 const XsdAnnotation::Ptr
annotation(new XsdAnnotation());
1164 if (isStartElement()) {
1165 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1166 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1168 tagValidator
.validate(token
);
1170 if (isSchemaTag(XsdSchemaToken::Appinfo
, token
, namespaceToken
)) {
1171 const XsdApplicationInformation::Ptr info
= parseAppInfo();
1172 annotation
->addApplicationInformation(info
);
1173 } else if (isSchemaTag(XsdSchemaToken::Documentation
, token
, namespaceToken
)) {
1174 const XsdDocumentation::Ptr documentation
= parseDocumentation();
1175 annotation
->addDocumentation(documentation
);
1182 tagValidator
.finalize();
1187 XsdApplicationInformation::Ptr
XsdSchemaParser::parseAppInfo()
1189 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Appinfo
, this);
1191 validateElement(XsdTagScope::AppInfo
);
1193 const XsdApplicationInformation::Ptr
info(new XsdApplicationInformation());
1196 if (hasAttribute(QString::fromLatin1("source"))) {
1197 const QString value
= readAttribute(QString::fromLatin1("source"));
1199 if (!isValidUri(value
)) {
1200 attributeContentError("source", "appinfo", value
, BuiltinTypes::xsAnyURI
);
1204 if (!value
.isEmpty()) {
1205 const AnyURI::Ptr source
= AnyURI::fromLexical(value
);
1206 info
->setSource(source
);
1210 while (!atEnd()) { //EVAL: can be anything... what to do?
1216 if (isStartElement())
1217 parseUnknownDocumentation();
1223 XsdDocumentation::Ptr
XsdSchemaParser::parseDocumentation()
1225 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Documentation
, this);
1227 validateElement(XsdTagScope::Documentation
);
1229 const XsdDocumentation::Ptr
documentation(new XsdDocumentation());
1232 if (hasAttribute(QString::fromLatin1("source"))) {
1233 const QString value
= readAttribute(QString::fromLatin1("source"));
1235 if (!isValidUri(value
)) {
1236 attributeContentError("source", "documentation", value
, BuiltinTypes::xsAnyURI
);
1237 return documentation
;
1240 if (!value
.isEmpty()) {
1241 const AnyURI::Ptr source
= AnyURI::fromLexical(value
);
1242 documentation
->setSource(source
);
1246 if (hasAttribute(CommonNamespaces::XML
, QString::fromLatin1("lang"))) {
1247 const QString value
= readAttribute(QString::fromLatin1("lang"), CommonNamespaces::XML
);
1249 const QRegExp
exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*"));
1250 if (!exp
.exactMatch(value
)) {
1251 attributeContentError("xml:lang", "documentation", value
);
1252 return documentation
;
1256 while (!atEnd()) { //EVAL: can by any... what to do?
1262 if (isStartElement())
1263 parseUnknownDocumentation();
1266 return documentation
;
1269 void XsdSchemaParser::parseDefaultOpenContent()
1271 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::DefaultOpenContent
, this);
1273 validateElement(XsdTagScope::DefaultOpenContent
);
1275 m_defaultOpenContent
= XsdComplexType::OpenContent::Ptr(new XsdComplexType::OpenContent());
1277 if (hasAttribute(QString::fromLatin1("appliesToEmpty"))) {
1278 const QString value
= readAttribute(QString::fromLatin1("appliesToEmpty"));
1279 const Boolean::Ptr appliesToEmpty
= Boolean::fromLexical(value
);
1280 if (appliesToEmpty
->hasError()) {
1281 attributeContentError("appliesToEmpty", "defaultOpenContent", value
, BuiltinTypes::xsBoolean
);
1285 m_defaultOpenContentAppliesToEmpty
= appliesToEmpty
->as
<Boolean
>()->value();
1287 m_defaultOpenContentAppliesToEmpty
= false;
1290 if (hasAttribute(QString::fromLatin1("mode"))) {
1291 const QString mode
= readAttribute(QString::fromLatin1("mode"));
1293 if (mode
== QString::fromLatin1("interleave")) {
1294 m_defaultOpenContent
->setMode(XsdComplexType::OpenContent::Interleave
);
1295 } else if (mode
== QString::fromLatin1("suffix")) {
1296 m_defaultOpenContent
->setMode(XsdComplexType::OpenContent::Suffix
);
1298 attributeContentError("mode", "defaultOpenContent", mode
);
1302 m_defaultOpenContent
->setMode(XsdComplexType::OpenContent::Interleave
);
1305 validateIdAttribute("defaultOpenContent");
1307 TagValidationHandler
tagValidator(XsdTagScope::DefaultOpenContent
, this, m_namePool
);
1315 if (isStartElement()) {
1316 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1317 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1319 tagValidator
.validate(token
);
1321 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
1322 const XsdAnnotation::Ptr annotation
= parseAnnotation();
1323 m_defaultOpenContent
->addAnnotation(annotation
);
1324 } else if (isSchemaTag(XsdSchemaToken::Any
, token
, namespaceToken
)) {
1325 const XsdParticle::Ptr particle
;
1326 const XsdWildcard::Ptr wildcard
= parseAny(particle
);
1327 m_defaultOpenContent
->setWildcard(wildcard
);
1334 tagValidator
.finalize();
1337 XsdSimpleType::Ptr
XsdSchemaParser::parseGlobalSimpleType()
1339 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::SimpleType
, this);
1341 validateElement(XsdTagScope::GlobalSimpleType
);
1343 const XsdSimpleType::Ptr
simpleType(new XsdSimpleType());
1344 simpleType
->setCategory(XsdSimpleType::SimpleTypeAtomic
); // just to make sure it's not invalid
1347 const SchemaType::DerivationConstraints
allowedConstraints(SchemaType::ExtensionConstraint
| SchemaType::RestrictionConstraint
| SchemaType::ListConstraint
| SchemaType::UnionConstraint
);
1348 simpleType
->setDerivationConstraints(readDerivationConstraintAttribute(allowedConstraints
, "simpleType"));
1350 const QXmlName objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("simpleType"));
1351 simpleType
->setName(objectName
);
1353 validateIdAttribute("simpleType");
1355 TagValidationHandler
tagValidator(XsdTagScope::GlobalSimpleType
, this, m_namePool
);
1363 if (isStartElement()) {
1364 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1365 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1367 tagValidator
.validate(token
);
1369 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
1370 const XsdAnnotation::Ptr annotation
= parseAnnotation();
1371 simpleType
->addAnnotation(annotation
);
1372 } else if (isSchemaTag(XsdSchemaToken::Restriction
, token
, namespaceToken
)) {
1373 parseSimpleRestriction(simpleType
);
1374 } else if (isSchemaTag(XsdSchemaToken::List
, token
, namespaceToken
)) {
1375 parseList(simpleType
);
1376 } else if (isSchemaTag(XsdSchemaToken::Union
, token
, namespaceToken
)) {
1377 parseUnion(simpleType
);
1384 tagValidator
.finalize();
1389 XsdSimpleType::Ptr
XsdSchemaParser::parseLocalSimpleType()
1391 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::SimpleType
, this);
1393 validateElement(XsdTagScope::LocalSimpleType
);
1395 const XsdSimpleType::Ptr
simpleType(new XsdSimpleType());
1396 simpleType
->setCategory(XsdSimpleType::SimpleTypeAtomic
); // just to make sure it's not invalid
1397 simpleType
->setName(m_parserContext
->createAnonymousName(m_targetNamespace
));
1399 validateIdAttribute("simpleType");
1401 TagValidationHandler
tagValidator(XsdTagScope::LocalSimpleType
, this, m_namePool
);
1409 if (isStartElement()) {
1410 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1411 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1413 tagValidator
.validate(token
);
1415 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
1416 const XsdAnnotation::Ptr annotation
= parseAnnotation();
1417 simpleType
->addAnnotation(annotation
);
1418 } else if (isSchemaTag(XsdSchemaToken::Restriction
, token
, namespaceToken
)) {
1419 parseSimpleRestriction(simpleType
);
1420 } else if (isSchemaTag(XsdSchemaToken::List
, token
, namespaceToken
)) {
1421 parseList(simpleType
);
1422 } else if (isSchemaTag(XsdSchemaToken::Union
, token
, namespaceToken
)) {
1423 parseUnion(simpleType
);
1430 tagValidator
.finalize();
1435 void XsdSchemaParser::parseSimpleRestriction(const XsdSimpleType::Ptr
&ptr
)
1437 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Restriction
, this);
1439 validateElement(XsdTagScope::SimpleRestriction
);
1441 ptr
->setDerivationMethod(XsdSimpleType::DerivationRestriction
);
1443 // The base attribute and simpleType member are mutually exclusive,
1444 // so we keep track of that
1445 bool hasBaseAttribute
= false;
1446 bool hasBaseTypeSpecified
= false;
1449 if (hasAttribute(QString::fromLatin1("base"))) {
1450 const QString base
= readQNameAttribute(QString::fromLatin1("base"), "restriction");
1451 convertName(base
, NamespaceSupport::ElementName
, baseName
); // translate qualified name into QXmlName
1452 m_schemaResolver
->addSimpleRestrictionBase(ptr
, baseName
, currentSourceLocation()); // add to resolver
1454 hasBaseAttribute
= true;
1455 hasBaseTypeSpecified
= true;
1457 validateIdAttribute("restriction");
1459 XsdFacet::Hash facets
;
1460 QList
<XsdFacet::Ptr
> patternFacets
;
1461 QList
<XsdFacet::Ptr
> enumerationFacets
;
1462 QList
<XsdFacet::Ptr
> assertionFacets
;
1464 TagValidationHandler
tagValidator(XsdTagScope::SimpleRestriction
, this, m_namePool
);
1472 if (isStartElement()) {
1473 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1474 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1476 tagValidator
.validate(token
);
1478 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
1479 const XsdAnnotation::Ptr annotation
= parseAnnotation();
1480 ptr
->addAnnotation(annotation
);
1481 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
1482 if (hasBaseAttribute
) {
1483 error(QtXmlPatterns::tr("%1 element is not allowed inside %2 element if %3 attribute is present.")
1484 .arg(formatElement("simpleType"))
1485 .arg(formatElement("restriction"))
1486 .arg(formatAttribute("base")));
1490 const XsdSimpleType::Ptr type
= parseLocalSimpleType();
1491 type
->setContext(ptr
);
1492 ptr
->setWxsSuperType(type
);
1493 ptr
->setCategory(type
->category());
1494 hasBaseTypeSpecified
= true;
1496 // add it to list of anonymous types as well
1497 addAnonymousType(type
);
1498 } else if (isSchemaTag(XsdSchemaToken::MinExclusive
, token
, namespaceToken
)) {
1499 const XsdFacet::Ptr facet
= parseMinExclusiveFacet();
1500 addFacet(facet
, facets
, ptr
);
1501 } else if (isSchemaTag(XsdSchemaToken::MinInclusive
, token
, namespaceToken
)) {
1502 const XsdFacet::Ptr facet
= parseMinInclusiveFacet();
1503 addFacet(facet
, facets
, ptr
);
1504 } else if (isSchemaTag(XsdSchemaToken::MaxExclusive
, token
, namespaceToken
)) {
1505 const XsdFacet::Ptr facet
= parseMaxExclusiveFacet();
1506 addFacet(facet
, facets
, ptr
);
1507 } else if (isSchemaTag(XsdSchemaToken::MaxInclusive
, token
, namespaceToken
)) {
1508 const XsdFacet::Ptr facet
= parseMaxInclusiveFacet();
1509 addFacet(facet
, facets
, ptr
);
1510 } else if (isSchemaTag(XsdSchemaToken::TotalDigits
, token
, namespaceToken
)) {
1511 const XsdFacet::Ptr facet
= parseTotalDigitsFacet();
1512 addFacet(facet
, facets
, ptr
);
1513 } else if (isSchemaTag(XsdSchemaToken::FractionDigits
, token
, namespaceToken
)) {
1514 const XsdFacet::Ptr facet
= parseFractionDigitsFacet();
1515 addFacet(facet
, facets
, ptr
);
1516 } else if (isSchemaTag(XsdSchemaToken::Length
, token
, namespaceToken
)) {
1517 const XsdFacet::Ptr facet
= parseLengthFacet();
1518 addFacet(facet
, facets
, ptr
);
1519 } else if (isSchemaTag(XsdSchemaToken::MinLength
, token
, namespaceToken
)) {
1520 const XsdFacet::Ptr facet
= parseMinLengthFacet();
1521 addFacet(facet
, facets
, ptr
);
1522 } else if (isSchemaTag(XsdSchemaToken::MaxLength
, token
, namespaceToken
)) {
1523 const XsdFacet::Ptr facet
= parseMaxLengthFacet();
1524 addFacet(facet
, facets
, ptr
);
1525 } else if (isSchemaTag(XsdSchemaToken::Enumeration
, token
, namespaceToken
)) {
1526 const XsdFacet::Ptr facet
= parseEnumerationFacet();
1527 enumerationFacets
.append(facet
);
1528 } else if (isSchemaTag(XsdSchemaToken::WhiteSpace
, token
, namespaceToken
)) {
1529 const XsdFacet::Ptr facet
= parseWhiteSpaceFacet();
1530 addFacet(facet
, facets
, ptr
);
1531 } else if (isSchemaTag(XsdSchemaToken::Pattern
, token
, namespaceToken
)) {
1532 const XsdFacet::Ptr facet
= parsePatternFacet();
1533 patternFacets
.append(facet
);
1534 } else if (isSchemaTag(XsdSchemaToken::Assertion
, token
, namespaceToken
)) {
1535 const XsdFacet::Ptr facet
= parseAssertionFacet();
1536 assertionFacets
.append(facet
);
1543 if (!hasBaseTypeSpecified
) {
1544 error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element.")
1545 .arg(formatElement("restriction"))
1546 .arg(formatAttribute("base"))
1547 .arg(formatElement("simpleType")));
1551 // merge all pattern facets into one multi value facet
1552 if (!patternFacets
.isEmpty()) {
1553 const XsdFacet::Ptr
patternFacet(new XsdFacet());
1554 patternFacet
->setType(XsdFacet::Pattern
);
1556 AtomicValue::List multiValue
;
1557 for (int i
= 0; i
< patternFacets
.count(); ++i
)
1558 multiValue
<< patternFacets
.at(i
)->multiValue();
1560 patternFacet
->setMultiValue(multiValue
);
1561 addFacet(patternFacet
, facets
, ptr
);
1564 // merge all enumeration facets into one multi value facet
1565 if (!enumerationFacets
.isEmpty()) {
1566 const XsdFacet::Ptr
enumerationFacet(new XsdFacet());
1567 enumerationFacet
->setType(XsdFacet::Enumeration
);
1569 AtomicValue::List multiValue
;
1570 for (int i
= 0; i
< enumerationFacets
.count(); ++i
)
1571 multiValue
<< enumerationFacets
.at(i
)->multiValue();
1573 enumerationFacet
->setMultiValue(multiValue
);
1574 addFacet(enumerationFacet
, facets
, ptr
);
1577 // merge all assertion facets into one facet
1578 if (!assertionFacets
.isEmpty()) {
1579 const XsdFacet::Ptr
assertionFacet(new XsdFacet());
1580 assertionFacet
->setType(XsdFacet::Assertion
);
1582 XsdAssertion::List assertions
;
1583 for (int i
= 0; i
< assertionFacets
.count(); ++i
)
1584 assertions
<< assertionFacets
.at(i
)->assertions();
1586 assertionFacet
->setAssertions(assertions
);
1587 addFacet(assertionFacet
, facets
, ptr
);
1590 ptr
->setFacets(facets
);
1592 tagValidator
.finalize();
1595 void XsdSchemaParser::parseList(const XsdSimpleType::Ptr
&ptr
)
1597 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::List
, this);
1599 validateElement(XsdTagScope::List
);
1601 ptr
->setCategory(XsdSimpleType::SimpleTypeList
);
1602 ptr
->setDerivationMethod(XsdSimpleType::DerivationList
);
1603 ptr
->setWxsSuperType(BuiltinTypes::xsAnySimpleType
);
1605 // The itemType attribute and simpleType member are mutually exclusive,
1606 // so we keep track of that
1607 bool hasItemTypeAttribute
= false;
1608 bool hasItemTypeSpecified
= false;
1610 if (hasAttribute(QString::fromLatin1("itemType"))) {
1611 const QString itemType
= readQNameAttribute(QString::fromLatin1("itemType"), "list");
1613 convertName(itemType
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
1614 m_schemaResolver
->addSimpleListType(ptr
, typeName
, currentSourceLocation()); // add to resolver
1616 hasItemTypeAttribute
= true;
1617 hasItemTypeSpecified
= true;
1620 validateIdAttribute("list");
1622 TagValidationHandler
tagValidator(XsdTagScope::List
, this, m_namePool
);
1630 if (isStartElement()) {
1631 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1632 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1634 tagValidator
.validate(token
);
1636 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
1637 const XsdAnnotation::Ptr annotation
= parseAnnotation();
1638 ptr
->addAnnotation(annotation
);
1639 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
1640 if (hasItemTypeAttribute
) {
1641 error(QtXmlPatterns::tr("%1 element is not allowed inside %2 element if %3 attribute is present.")
1642 .arg(formatElement("simpleType"))
1643 .arg(formatElement("list"))
1644 .arg(formatAttribute("itemType")));
1648 const XsdSimpleType::Ptr type
= parseLocalSimpleType();
1649 type
->setContext(ptr
);
1650 ptr
->setItemType(type
);
1652 hasItemTypeSpecified
= true;
1654 // add it to list of anonymous types as well
1655 addAnonymousType(type
);
1662 if (!hasItemTypeSpecified
) {
1663 error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element.")
1664 .arg(formatElement("list"))
1665 .arg(formatAttribute("itemType"))
1666 .arg(formatElement("simpleType")));
1670 tagValidator
.finalize();
1672 // add the default white space facet that every simple type with list derivation has
1673 const XsdFacet::Ptr
defaultFacet(new XsdFacet());
1674 defaultFacet
->setType(XsdFacet::WhiteSpace
);
1675 defaultFacet
->setFixed(true);
1676 defaultFacet
->setValue(DerivedString
<TypeString
>::fromLexical(m_namePool
, XsdSchemaToken::toString(XsdSchemaToken::Collapse
)));
1677 XsdFacet::Hash facets
;
1678 facets
.insert(defaultFacet
->type(), defaultFacet
);
1679 ptr
->setFacets(facets
);
1682 void XsdSchemaParser::parseUnion(const XsdSimpleType::Ptr
&ptr
)
1684 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Union
, this);
1686 validateElement(XsdTagScope::Union
);
1688 ptr
->setCategory(XsdSimpleType::SimpleTypeUnion
);
1689 ptr
->setDerivationMethod(XsdSimpleType::DerivationUnion
);
1690 ptr
->setWxsSuperType(BuiltinTypes::xsAnySimpleType
);
1692 // The memberTypes attribute is not allowed to be empty,
1693 // so we keep track of that
1694 bool hasMemberTypesAttribute
= false;
1695 bool hasMemberTypesSpecified
= false;
1697 if (hasAttribute(QString::fromLatin1("memberTypes"))) {
1698 hasMemberTypesAttribute
= true;
1700 const QStringList memberTypes
= readAttribute(QString::fromLatin1("memberTypes")).split(QLatin1Char(' '), QString::SkipEmptyParts
);
1701 QList
<QXmlName
> typeNames
;
1703 for (int i
= 0; i
< memberTypes
.count(); ++i
) {
1705 convertName(memberTypes
.at(i
), NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
1706 typeNames
.append(typeName
);
1709 if (!typeNames
.isEmpty()) {
1710 m_schemaResolver
->addSimpleUnionTypes(ptr
, typeNames
, currentSourceLocation()); // add to resolver
1711 hasMemberTypesSpecified
= true;
1715 validateIdAttribute("union");
1717 AnySimpleType::List memberTypes
;
1719 TagValidationHandler
tagValidator(XsdTagScope::Union
, this, m_namePool
);
1727 if (isStartElement()) {
1728 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1729 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1731 tagValidator
.validate(token
);
1733 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
1734 const XsdAnnotation::Ptr annotation
= parseAnnotation();
1735 ptr
->addAnnotation(annotation
);
1736 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
1737 const XsdSimpleType::Ptr type
= parseLocalSimpleType();
1738 type
->setContext(ptr
);
1739 memberTypes
.append(type
);
1741 // add it to list of anonymous types as well
1742 addAnonymousType(type
);
1749 if (!memberTypes
.isEmpty()) {
1750 ptr
->setMemberTypes(memberTypes
);
1751 hasMemberTypesSpecified
= true;
1754 if (!hasMemberTypesSpecified
) {
1755 error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element.")
1756 .arg(formatElement("union"))
1757 .arg(formatAttribute("memberTypes"))
1758 .arg(formatElement("simpleType")));
1762 tagValidator
.finalize();
1765 XsdFacet::Ptr
XsdSchemaParser::parseMinExclusiveFacet()
1767 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::MinExclusive
, this);
1769 validateElement(XsdTagScope::MinExclusiveFacet
);
1771 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
1772 facet
->setType(XsdFacet::MinimumExclusive
);
1775 if (hasAttribute(QString::fromLatin1("fixed"))) {
1776 const QString value
= readAttribute(QString::fromLatin1("fixed"));
1777 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
1778 if (fixed
->hasError()) {
1779 attributeContentError("fixed", "minExclusive", value
, BuiltinTypes::xsBoolean
);
1783 facet
->setFixed(fixed
->as
<Boolean
>()->value());
1785 facet
->setFixed(false); // the default value
1788 // as minExclusive can have a value of type anySimpleType, we just read
1789 // the string here and store it for later intepretation
1790 const QString value
= readAttribute(QString::fromLatin1("value"));
1791 DerivedString
<TypeString
>::Ptr string
= DerivedString
<TypeString
>::fromLexical(m_namePool
, value
);
1792 if (string
->hasError()) {
1793 attributeContentError("value", "minExclusive", value
, BuiltinTypes::xsAnySimpleType
);
1796 facet
->setValue(string
);
1799 validateIdAttribute("minExclusive");
1801 TagValidationHandler
tagValidator(XsdTagScope::MinExclusiveFacet
, this, m_namePool
);
1809 if (isStartElement()) {
1810 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1811 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1813 tagValidator
.validate(token
);
1815 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
1816 const XsdAnnotation::Ptr annotation
= parseAnnotation();
1817 facet
->addAnnotation(annotation
);
1824 tagValidator
.finalize();
1829 XsdFacet::Ptr
XsdSchemaParser::parseMinInclusiveFacet()
1831 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::MinInclusive
, this);
1833 validateElement(XsdTagScope::MinInclusiveFacet
);
1835 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
1836 facet
->setType(XsdFacet::MinimumInclusive
);
1839 if (hasAttribute(QString::fromLatin1("fixed"))) {
1840 const QString value
= readAttribute(QString::fromLatin1("fixed"));
1841 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
1842 if (fixed
->hasError()) {
1843 attributeContentError("fixed", "minInclusive", value
, BuiltinTypes::xsBoolean
);
1847 facet
->setFixed(fixed
->as
<Boolean
>()->value());
1849 facet
->setFixed(false); // the default value
1852 // as minInclusive can have a value of type anySimpleType, we just read
1853 // the string here and store it for later intepretation
1854 const QString value
= readAttribute(QString::fromLatin1("value"));
1855 DerivedString
<TypeString
>::Ptr string
= DerivedString
<TypeString
>::fromLexical(m_namePool
, value
);
1856 if (string
->hasError()) {
1857 attributeContentError("value", "minInclusive", value
, BuiltinTypes::xsAnySimpleType
);
1860 facet
->setValue(string
);
1863 validateIdAttribute("minInclusive");
1865 TagValidationHandler
tagValidator(XsdTagScope::MinInclusiveFacet
, this, m_namePool
);
1873 if (isStartElement()) {
1874 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1875 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1877 tagValidator
.validate(token
);
1879 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
1880 const XsdAnnotation::Ptr annotation
= parseAnnotation();
1881 facet
->addAnnotation(annotation
);
1888 tagValidator
.finalize();
1893 XsdFacet::Ptr
XsdSchemaParser::parseMaxExclusiveFacet()
1895 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::MaxExclusive
, this);
1897 validateElement(XsdTagScope::MaxExclusiveFacet
);
1899 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
1900 facet
->setType(XsdFacet::MaximumExclusive
);
1903 if (hasAttribute(QString::fromLatin1("fixed"))) {
1904 const QString value
= readAttribute(QString::fromLatin1("fixed"));
1905 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
1906 if (fixed
->hasError()) {
1907 attributeContentError("fixed", "maxExclusive", value
, BuiltinTypes::xsBoolean
);
1911 facet
->setFixed(fixed
->as
<Boolean
>()->value());
1913 facet
->setFixed(false); // the default value
1916 // as maxExclusive can have a value of type anySimpleType, we just read
1917 // the string here and store it for later intepretation
1918 const QString value
= readAttribute(QString::fromLatin1("value"));
1919 DerivedString
<TypeString
>::Ptr string
= DerivedString
<TypeString
>::fromLexical(m_namePool
, value
);
1920 if (string
->hasError()) {
1921 attributeContentError("value", "maxExclusive", value
, BuiltinTypes::xsAnySimpleType
);
1924 facet
->setValue(string
);
1927 validateIdAttribute("maxExclusive");
1929 TagValidationHandler
tagValidator(XsdTagScope::MaxExclusiveFacet
, this, m_namePool
);
1937 if (isStartElement()) {
1938 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
1939 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
1941 tagValidator
.validate(token
);
1943 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
1944 const XsdAnnotation::Ptr annotation
= parseAnnotation();
1945 facet
->addAnnotation(annotation
);
1952 tagValidator
.finalize();
1957 XsdFacet::Ptr
XsdSchemaParser::parseMaxInclusiveFacet()
1959 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::MaxInclusive
, this);
1961 validateElement(XsdTagScope::MaxInclusiveFacet
);
1963 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
1964 facet
->setType(XsdFacet::MaximumInclusive
);
1967 if (hasAttribute(QString::fromLatin1("fixed"))) {
1968 const QString value
= readAttribute(QString::fromLatin1("fixed"));
1969 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
1970 if (fixed
->hasError()) {
1971 attributeContentError("fixed", "maxInclusive", value
, BuiltinTypes::xsBoolean
);
1975 facet
->setFixed(fixed
->as
<Boolean
>()->value());
1977 facet
->setFixed(false); // the default value
1980 // as maxInclusive can have a value of type anySimpleType, we just read
1981 // the string here and store it for later intepretation
1982 const QString value
= readAttribute(QString::fromLatin1("value"));
1983 DerivedString
<TypeString
>::Ptr string
= DerivedString
<TypeString
>::fromLexical(m_namePool
, value
);
1984 if (string
->hasError()) {
1985 attributeContentError("value", "maxInclusive", value
, BuiltinTypes::xsAnySimpleType
);
1988 facet
->setValue(string
);
1991 validateIdAttribute("maxInclusive");
1993 TagValidationHandler
tagValidator(XsdTagScope::MaxInclusiveFacet
, this, m_namePool
);
2001 if (isStartElement()) {
2002 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2003 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2005 tagValidator
.validate(token
);
2007 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2008 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2009 facet
->addAnnotation(annotation
);
2016 tagValidator
.finalize();
2021 XsdFacet::Ptr
XsdSchemaParser::parseTotalDigitsFacet()
2023 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::TotalDigits
, this);
2025 validateElement(XsdTagScope::TotalDigitsFacet
);
2027 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
2028 facet
->setType(XsdFacet::TotalDigits
);
2031 if (hasAttribute(QString::fromLatin1("fixed"))) {
2032 const QString value
= readAttribute(QString::fromLatin1("fixed"));
2033 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
2034 if (fixed
->hasError()) {
2035 attributeContentError("fixed", "totalDigits", value
, BuiltinTypes::xsBoolean
);
2039 facet
->setFixed(fixed
->as
<Boolean
>()->value());
2041 facet
->setFixed(false); // the default value
2044 const QString value
= readAttribute(QString::fromLatin1("value"));
2045 DerivedInteger
<TypePositiveInteger
>::Ptr integer
= DerivedInteger
<TypePositiveInteger
>::fromLexical(m_namePool
, value
);
2046 if (integer
->hasError()) {
2047 attributeContentError("value", "totalDigits", value
, BuiltinTypes::xsPositiveInteger
);
2050 facet
->setValue(integer
);
2053 validateIdAttribute("totalDigits");
2055 TagValidationHandler
tagValidator(XsdTagScope::TotalDigitsFacet
, this, m_namePool
);
2063 if (isStartElement()) {
2064 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2065 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2067 tagValidator
.validate(token
);
2069 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2070 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2071 facet
->addAnnotation(annotation
);
2078 tagValidator
.finalize();
2083 XsdFacet::Ptr
XsdSchemaParser::parseFractionDigitsFacet()
2085 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::FractionDigits
, this);
2087 validateElement(XsdTagScope::FractionDigitsFacet
);
2089 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
2090 facet
->setType(XsdFacet::FractionDigits
);
2093 if (hasAttribute(QString::fromLatin1("fixed"))) {
2094 const QString value
= readAttribute(QString::fromLatin1("fixed"));
2095 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
2096 if (fixed
->hasError()) {
2097 attributeContentError("fixed", "fractionDigits", value
, BuiltinTypes::xsBoolean
);
2101 facet
->setFixed(fixed
->as
<Boolean
>()->value());
2103 facet
->setFixed(false); // the default value
2106 const QString value
= readAttribute(QString::fromLatin1("value"));
2107 DerivedInteger
<TypeNonNegativeInteger
>::Ptr integer
= DerivedInteger
<TypeNonNegativeInteger
>::fromLexical(m_namePool
, value
);
2108 if (integer
->hasError()) {
2109 attributeContentError("value", "fractionDigits", value
, BuiltinTypes::xsNonNegativeInteger
);
2112 facet
->setValue(integer
);
2115 validateIdAttribute("fractionDigits");
2117 TagValidationHandler
tagValidator(XsdTagScope::FractionDigitsFacet
, this, m_namePool
);
2125 if (isStartElement()) {
2126 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2127 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2129 tagValidator
.validate(token
);
2131 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2132 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2133 facet
->addAnnotation(annotation
);
2140 tagValidator
.finalize();
2145 XsdFacet::Ptr
XsdSchemaParser::parseLengthFacet()
2147 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Length
, this);
2149 validateElement(XsdTagScope::LengthFacet
);
2151 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
2152 facet
->setType(XsdFacet::Length
);
2155 if (hasAttribute(QString::fromLatin1("fixed"))) {
2156 const QString value
= readAttribute(QString::fromLatin1("fixed"));
2157 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
2158 if (fixed
->hasError()) {
2159 attributeContentError("fixed", "length", value
, BuiltinTypes::xsBoolean
);
2163 facet
->setFixed(fixed
->as
<Boolean
>()->value());
2165 facet
->setFixed(false); // the default value
2168 const QString value
= readAttribute(QString::fromLatin1("value"));
2169 DerivedInteger
<TypeNonNegativeInteger
>::Ptr integer
= DerivedInteger
<TypeNonNegativeInteger
>::fromLexical(m_namePool
, value
);
2170 if (integer
->hasError()) {
2171 attributeContentError("value", "length", value
, BuiltinTypes::xsNonNegativeInteger
);
2174 facet
->setValue(integer
);
2177 validateIdAttribute("length");
2179 TagValidationHandler
tagValidator(XsdTagScope::LengthFacet
, this, m_namePool
);
2187 if (isStartElement()) {
2188 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2189 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2191 tagValidator
.validate(token
);
2193 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2194 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2195 facet
->addAnnotation(annotation
);
2202 tagValidator
.finalize();
2207 XsdFacet::Ptr
XsdSchemaParser::parseMinLengthFacet()
2209 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::MinLength
, this);
2211 validateElement(XsdTagScope::MinLengthFacet
);
2213 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
2214 facet
->setType(XsdFacet::MinimumLength
);
2217 if (hasAttribute(QString::fromLatin1("fixed"))) {
2218 const QString value
= readAttribute(QString::fromLatin1("fixed"));
2219 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
2220 if (fixed
->hasError()) {
2221 attributeContentError("fixed", "minLength", value
, BuiltinTypes::xsBoolean
);
2225 facet
->setFixed(fixed
->as
<Boolean
>()->value());
2227 facet
->setFixed(false); // the default value
2230 const QString value
= readAttribute(QString::fromLatin1("value"));
2231 DerivedInteger
<TypeNonNegativeInteger
>::Ptr integer
= DerivedInteger
<TypeNonNegativeInteger
>::fromLexical(m_namePool
, value
);
2232 if (integer
->hasError()) {
2233 attributeContentError("value", "minLength", value
, BuiltinTypes::xsNonNegativeInteger
);
2236 facet
->setValue(integer
);
2239 validateIdAttribute("minLength");
2241 TagValidationHandler
tagValidator(XsdTagScope::MinLengthFacet
, this, m_namePool
);
2249 if (isStartElement()) {
2250 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2251 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2253 tagValidator
.validate(token
);
2255 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2256 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2257 facet
->addAnnotation(annotation
);
2264 tagValidator
.finalize();
2269 XsdFacet::Ptr
XsdSchemaParser::parseMaxLengthFacet()
2271 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::MaxLength
, this);
2273 validateElement(XsdTagScope::MaxLengthFacet
);
2275 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
2276 facet
->setType(XsdFacet::MaximumLength
);
2279 if (hasAttribute(QString::fromLatin1("fixed"))) {
2280 const QString value
= readAttribute(QString::fromLatin1("fixed"));
2281 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
2282 if (fixed
->hasError()) {
2283 attributeContentError("fixed", "maxLength", value
, BuiltinTypes::xsBoolean
);
2287 facet
->setFixed(fixed
->as
<Boolean
>()->value());
2289 facet
->setFixed(false); // the default value
2292 const QString value
= readAttribute(QString::fromLatin1("value"));
2293 DerivedInteger
<TypeNonNegativeInteger
>::Ptr integer
= DerivedInteger
<TypeNonNegativeInteger
>::fromLexical(m_namePool
, value
);
2294 if (integer
->hasError()) {
2295 attributeContentError("value", "maxLength", value
, BuiltinTypes::xsNonNegativeInteger
);
2298 facet
->setValue(integer
);
2301 validateIdAttribute("maxLength");
2303 TagValidationHandler
tagValidator(XsdTagScope::MaxLengthFacet
, this, m_namePool
);
2311 if (isStartElement()) {
2312 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2313 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2315 tagValidator
.validate(token
);
2317 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2318 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2319 facet
->addAnnotation(annotation
);
2326 tagValidator
.finalize();
2331 XsdFacet::Ptr
XsdSchemaParser::parseEnumerationFacet()
2333 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Enumeration
, this);
2335 validateElement(XsdTagScope::EnumerationFacet
);
2337 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
2338 facet
->setType(XsdFacet::Enumeration
);
2341 facet
->setFixed(false); // not defined in schema, but can't hurt
2343 const QString value
= readAttribute(QString::fromLatin1("value"));
2345 // as enumeration can have a value of type anySimpleType, we just read
2346 // the string here and store it for later intepretation
2347 DerivedString
<TypeString
>::Ptr string
= DerivedString
<TypeString
>::fromLexical(m_namePool
, value
);
2348 if (string
->hasError()) {
2349 attributeContentError("value", "enumeration", value
);
2352 AtomicValue::List multiValue
;
2353 multiValue
<< string
;
2354 facet
->setMultiValue(multiValue
);
2356 m_schemaResolver
->addEnumerationFacetValue(string
, m_namespaceSupport
);
2358 validateIdAttribute("enumeration");
2360 TagValidationHandler
tagValidator(XsdTagScope::EnumerationFacet
, this, m_namePool
);
2368 if (isStartElement()) {
2369 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2370 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2372 tagValidator
.validate(token
);
2374 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2375 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2376 facet
->addAnnotation(annotation
);
2383 tagValidator
.finalize();
2388 XsdFacet::Ptr
XsdSchemaParser::parseWhiteSpaceFacet()
2390 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::WhiteSpace
, this);
2392 validateElement(XsdTagScope::WhiteSpaceFacet
);
2394 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
2395 facet
->setType(XsdFacet::WhiteSpace
);
2398 if (hasAttribute(QString::fromLatin1("fixed"))) {
2399 const QString value
= readAttribute(QString::fromLatin1("fixed"));
2400 const Boolean::Ptr fixed
= Boolean::fromLexical(value
);
2401 if (fixed
->hasError()) {
2402 attributeContentError("fixed", "whiteSpace", value
, BuiltinTypes::xsBoolean
);
2406 facet
->setFixed(fixed
->as
<Boolean
>()->value());
2408 facet
->setFixed(false); // the default value
2411 const QString value
= readAttribute(QString::fromLatin1("value"));
2412 if (value
!= XsdSchemaToken::toString(XsdSchemaToken::Collapse
) &&
2413 value
!= XsdSchemaToken::toString(XsdSchemaToken::Preserve
) &&
2414 value
!= XsdSchemaToken::toString(XsdSchemaToken::Replace
)) {
2415 attributeContentError("value", "whiteSpace", value
);
2418 DerivedString
<TypeString
>::Ptr string
= DerivedString
<TypeString
>::fromLexical(m_namePool
, value
);
2419 if (string
->hasError()) {
2420 attributeContentError("value", "whiteSpace", value
);
2423 facet
->setValue(string
);
2427 validateIdAttribute("whiteSpace");
2429 TagValidationHandler
tagValidator(XsdTagScope::WhiteSpaceFacet
, this, m_namePool
);
2437 if (isStartElement()) {
2438 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2439 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2441 tagValidator
.validate(token
);
2443 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2444 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2445 facet
->addAnnotation(annotation
);
2452 tagValidator
.finalize();
2457 XsdFacet::Ptr
XsdSchemaParser::parsePatternFacet()
2459 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Pattern
, this);
2461 validateElement(XsdTagScope::PatternFacet
);
2463 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
2464 facet
->setType(XsdFacet::Pattern
);
2468 // as pattern can have a value of type anySimpleType, we just read
2469 // the string here and store it for later intepretation
2470 const QString value
= readAttribute(QString::fromLatin1("value"));
2471 DerivedString
<TypeString
>::Ptr string
= DerivedString
<TypeString
>::fromLexical(m_namePool
, value
);
2472 if (string
->hasError()) {
2473 attributeContentError("value", "pattern", value
);
2476 AtomicValue::List multiValue
;
2477 multiValue
<< string
;
2478 facet
->setMultiValue(multiValue
);
2481 validateIdAttribute("pattern");
2483 TagValidationHandler
tagValidator(XsdTagScope::PatternFacet
, this, m_namePool
);
2491 if (isStartElement()) {
2492 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2493 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2495 tagValidator
.validate(token
);
2497 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2498 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2499 facet
->addAnnotation(annotation
);
2506 tagValidator
.finalize();
2511 XsdFacet::Ptr
XsdSchemaParser::parseAssertionFacet()
2513 // this is just a wrapper function around the parseAssertion() method
2515 const XsdAssertion::Ptr assertion
= parseAssertion(XsdSchemaToken::Assertion
, XsdTagScope::Assertion
);
2517 const XsdFacet::Ptr facet
= XsdFacet::Ptr(new XsdFacet());
2518 facet
->setType(XsdFacet::Assertion
);
2519 facet
->setAssertions(XsdAssertion::List() << assertion
);
2524 XsdComplexType::Ptr
XsdSchemaParser::parseGlobalComplexType()
2526 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::ComplexType
, this);
2528 validateElement(XsdTagScope::GlobalComplexType
);
2530 bool hasTypeSpecified
= false;
2531 bool hasComplexContent
= false;
2533 const XsdComplexType::Ptr
complexType(new XsdComplexType());
2536 if (hasAttribute(QString::fromLatin1("abstract"))) {
2537 const QString abstract
= readAttribute(QString::fromLatin1("abstract"));
2539 const Boolean::Ptr value
= Boolean::fromLexical(abstract
);
2540 if (value
->hasError()) {
2541 attributeContentError("abstract", "complexType", abstract
, BuiltinTypes::xsBoolean
);
2545 complexType
->setIsAbstract(value
->as
<Boolean
>()->value());
2547 complexType
->setIsAbstract(false); // default value
2550 complexType
->setProhibitedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint
| NamedSchemaComponent::RestrictionConstraint
, "complexType"));
2551 complexType
->setDerivationConstraints(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint
| SchemaType::RestrictionConstraint
, "complexType"));
2553 const QXmlName objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("complexType"));
2554 complexType
->setName(objectName
);
2556 bool effectiveMixed
= false;
2557 if (hasAttribute(QString::fromLatin1("mixed"))) {
2558 const QString mixed
= readAttribute(QString::fromLatin1("mixed"));
2560 const Boolean::Ptr value
= Boolean::fromLexical(mixed
);
2561 if (value
->hasError()) {
2562 attributeContentError("mixed", "complexType", mixed
, BuiltinTypes::xsBoolean
);
2566 effectiveMixed
= value
->as
<Boolean
>()->value();
2569 validateIdAttribute("complexType");
2571 TagValidationHandler
tagValidator(XsdTagScope::GlobalComplexType
, this, m_namePool
);
2579 if (isStartElement()) {
2580 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2581 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2583 tagValidator
.validate(token
);
2585 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2586 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2587 complexType
->addAnnotation(annotation
);
2588 } else if (isSchemaTag(XsdSchemaToken::SimpleContent
, token
, namespaceToken
)) {
2589 if (effectiveMixed
) {
2590 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
2591 .arg(formatElement("complexType"))
2592 .arg(formatElement("simpleContent"))
2593 .arg(formatAttribute("mixed")));
2597 parseSimpleContent(complexType
);
2598 hasTypeSpecified
= true;
2599 } else if (isSchemaTag(XsdSchemaToken::ComplexContent
, token
, namespaceToken
)) {
2601 parseComplexContent(complexType
, &mixed
);
2602 hasTypeSpecified
= true;
2604 effectiveMixed
= (effectiveMixed
|| mixed
);
2605 hasComplexContent
= true;
2606 } else if (isSchemaTag(XsdSchemaToken::OpenContent
, token
, namespaceToken
)) {
2607 const XsdComplexType::OpenContent::Ptr openContent
= parseOpenContent();
2608 complexType
->contentType()->setOpenContent(openContent
);
2609 hasComplexContent
= true;
2610 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
2611 const XsdParticle::Ptr
particle(new XsdParticle());
2612 const XsdTerm::Ptr term
= parseReferredGroup(particle
);
2613 particle
->setTerm(term
);
2614 complexType
->contentType()->setParticle(particle
);
2616 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2617 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2618 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2619 hasComplexContent
= true;
2620 } else if (isSchemaTag(XsdSchemaToken::All
, token
, namespaceToken
)) {
2621 const XsdParticle::Ptr
particle(new XsdParticle());
2622 const XsdTerm::Ptr term
= parseLocalAll(particle
, complexType
);
2623 particle
->setTerm(term
);
2624 complexType
->contentType()->setParticle(particle
);
2626 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2627 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2628 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2629 hasComplexContent
= true;
2630 } else if (isSchemaTag(XsdSchemaToken::Choice
, token
, namespaceToken
)) {
2631 const XsdParticle::Ptr
particle(new XsdParticle());
2632 const XsdTerm::Ptr term
= parseLocalChoice(particle
, complexType
);
2633 particle
->setTerm(term
);
2634 complexType
->contentType()->setParticle(particle
);
2636 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2637 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2638 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2639 hasComplexContent
= true;
2640 } else if (isSchemaTag(XsdSchemaToken::Sequence
, token
, namespaceToken
)) {
2641 const XsdParticle::Ptr
particle(new XsdParticle());
2642 const XsdTerm::Ptr term
= parseLocalSequence(particle
, complexType
);
2643 particle
->setTerm(term
);
2644 complexType
->contentType()->setParticle(particle
);
2646 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2647 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2648 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2649 hasComplexContent
= true;
2650 } else if (isSchemaTag(XsdSchemaToken::Attribute
, token
, namespaceToken
)) {
2651 const XsdAttributeUse::Ptr attributeUse
= parseLocalAttribute(complexType
);
2652 complexType
->addAttributeUse(attributeUse
);
2654 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2655 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2656 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2657 hasComplexContent
= true;
2658 } else if (isSchemaTag(XsdSchemaToken::AttributeGroup
, token
, namespaceToken
)) {
2659 const XsdAttributeUse::Ptr attributeUse
= parseReferredAttributeGroup();
2660 complexType
->addAttributeUse(attributeUse
);
2662 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2663 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2664 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2665 hasComplexContent
= true;
2666 } else if (isSchemaTag(XsdSchemaToken::AnyAttribute
, token
, namespaceToken
)) {
2667 const XsdWildcard::Ptr wildcard
= parseAnyAttribute();
2668 complexType
->setAttributeWildcard(wildcard
);
2670 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2671 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2672 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2673 hasComplexContent
= true;
2674 } else if (isSchemaTag(XsdSchemaToken::Assert
, token
, namespaceToken
)) {
2675 const XsdAssertion::Ptr assertion
= parseAssertion(XsdSchemaToken::Assert
, XsdTagScope::Assert
);
2676 complexType
->addAssertion(assertion
);
2683 tagValidator
.finalize();
2685 if (!hasTypeSpecified
) {
2686 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2687 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2688 hasComplexContent
= true;
2691 if (hasComplexContent
== true) {
2692 resolveComplexContentType(complexType
, effectiveMixed
);
2698 XsdComplexType::Ptr
XsdSchemaParser::parseLocalComplexType()
2700 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::ComplexType
, this);
2702 validateElement(XsdTagScope::LocalComplexType
);
2704 bool hasTypeSpecified
= false;
2705 bool hasComplexContent
= true;
2707 const XsdComplexType::Ptr
complexType(new XsdComplexType());
2708 complexType
->setName(m_parserContext
->createAnonymousName(m_targetNamespace
));
2711 bool effectiveMixed
= false;
2712 if (hasAttribute(QString::fromLatin1("mixed"))) {
2713 const QString mixed
= readAttribute(QString::fromLatin1("mixed"));
2715 const Boolean::Ptr value
= Boolean::fromLexical(mixed
);
2716 if (value
->hasError()) {
2717 attributeContentError("mixed", "complexType", mixed
, BuiltinTypes::xsBoolean
);
2721 effectiveMixed
= value
->as
<Boolean
>()->value();
2724 validateIdAttribute("complexType");
2726 TagValidationHandler
tagValidator(XsdTagScope::LocalComplexType
, this, m_namePool
);
2734 if (isStartElement()) {
2735 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2736 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2738 tagValidator
.validate(token
);
2740 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2741 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2742 complexType
->addAnnotation(annotation
);
2743 } else if (isSchemaTag(XsdSchemaToken::SimpleContent
, token
, namespaceToken
)) {
2744 parseSimpleContent(complexType
);
2745 hasTypeSpecified
= true;
2746 } else if (isSchemaTag(XsdSchemaToken::ComplexContent
, token
, namespaceToken
)) {
2748 parseComplexContent(complexType
, &mixed
);
2749 hasTypeSpecified
= true;
2751 effectiveMixed
= (effectiveMixed
|| mixed
);
2752 hasComplexContent
= true;
2753 } else if (isSchemaTag(XsdSchemaToken::OpenContent
, token
, namespaceToken
)) {
2754 const XsdComplexType::OpenContent::Ptr openContent
= parseOpenContent();
2755 complexType
->contentType()->setOpenContent(openContent
);
2756 hasComplexContent
= true;
2757 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
2758 const XsdParticle::Ptr
particle(new XsdParticle());
2759 const XsdTerm::Ptr term
= parseReferredGroup(particle
);
2760 particle
->setTerm(term
);
2761 complexType
->contentType()->setParticle(particle
);
2763 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2764 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2765 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2766 hasComplexContent
= true;
2767 } else if (isSchemaTag(XsdSchemaToken::All
, token
, namespaceToken
)) {
2768 const XsdParticle::Ptr
particle(new XsdParticle());
2769 const XsdTerm::Ptr term
= parseLocalAll(particle
, complexType
);
2770 particle
->setTerm(term
);
2771 complexType
->contentType()->setParticle(particle
);
2773 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2774 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2775 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2776 hasComplexContent
= true;
2777 } else if (isSchemaTag(XsdSchemaToken::Choice
, token
, namespaceToken
)) {
2778 const XsdParticle::Ptr
particle(new XsdParticle());
2779 const XsdTerm::Ptr term
= parseLocalChoice(particle
, complexType
);
2780 particle
->setTerm(term
);
2781 complexType
->contentType()->setParticle(particle
);
2783 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2784 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2785 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2786 hasComplexContent
= true;
2787 } else if (isSchemaTag(XsdSchemaToken::Sequence
, token
, namespaceToken
)) {
2788 const XsdParticle::Ptr
particle(new XsdParticle());
2789 const XsdTerm::Ptr term
= parseLocalSequence(particle
, complexType
);
2790 particle
->setTerm(term
);
2791 complexType
->contentType()->setParticle(particle
);
2793 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2794 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2795 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2796 hasComplexContent
= true;
2797 } else if (isSchemaTag(XsdSchemaToken::Attribute
, token
, namespaceToken
)) {
2798 const XsdAttributeUse::Ptr attributeUse
= parseLocalAttribute(complexType
);
2799 complexType
->addAttributeUse(attributeUse
);
2801 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2802 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2803 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2804 hasComplexContent
= true;
2805 } else if (isSchemaTag(XsdSchemaToken::AttributeGroup
, token
, namespaceToken
)) {
2806 const XsdAttributeUse::Ptr attributeUse
= parseReferredAttributeGroup();
2807 complexType
->addAttributeUse(attributeUse
);
2809 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2810 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2811 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2812 hasComplexContent
= true;
2813 } else if (isSchemaTag(XsdSchemaToken::AnyAttribute
, token
, namespaceToken
)) {
2814 const XsdWildcard::Ptr wildcard
= parseAnyAttribute();
2815 complexType
->setAttributeWildcard(wildcard
);
2817 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2818 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
2819 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2820 hasComplexContent
= true;
2821 } else if (isSchemaTag(XsdSchemaToken::Assert
, token
, namespaceToken
)) {
2822 const XsdAssertion::Ptr assertion
= parseAssertion(XsdSchemaToken::Assert
, XsdTagScope::Assert
);
2823 complexType
->addAssertion(assertion
);
2830 tagValidator
.finalize();
2832 if (!hasTypeSpecified
) {
2833 complexType
->setWxsSuperType(BuiltinTypes::xsAnyType
);
2834 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2835 hasComplexContent
= true;
2838 if (hasComplexContent
== true) {
2839 resolveComplexContentType(complexType
, effectiveMixed
);
2845 void XsdSchemaParser::resolveComplexContentType(const XsdComplexType::Ptr
&complexType
, bool effectiveMixed
)
2847 // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctcc.common
2850 // the effectiveMixed contains the effective mixed value
2853 bool hasEmptyContent
= false;
2854 if (!complexType
->contentType()->particle()) {
2855 hasEmptyContent
= true; // 2.1.1
2857 if (complexType
->contentType()->particle()->term()->isModelGroup()) {
2858 const XsdModelGroup::Ptr group
= complexType
->contentType()->particle()->term();
2859 if (group
->compositor() == XsdModelGroup::SequenceCompositor
|| group
->compositor() == XsdModelGroup::AllCompositor
) {
2860 if (group
->particles().isEmpty())
2861 hasEmptyContent
= true; // 2.1.2
2862 } else if (group
->compositor() == XsdModelGroup::ChoiceCompositor
) {
2863 if ((complexType
->contentType()->particle()->minimumOccurs() == 0) && group
->particles().isEmpty())
2864 hasEmptyContent
= true; // 2.1.3
2867 if ((complexType
->contentType()->particle()->maximumOccursUnbounded() == false) && (complexType
->contentType()->particle()->maximumOccurs() == 0))
2868 hasEmptyContent
= true; // 2.1.4
2872 const XsdParticle::Ptr explicitContent
= (hasEmptyContent
? XsdParticle::Ptr() : complexType
->contentType()->particle());
2874 // do all the other work (3, 4, 5 and 6) in the resolver, as they need access to the base type object
2875 m_schemaResolver
->addComplexContentType(complexType
, explicitContent
, effectiveMixed
);
2878 void XsdSchemaParser::parseSimpleContent(const XsdComplexType::Ptr
&complexType
)
2880 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::SimpleContent
, this);
2882 validateElement(XsdTagScope::SimpleContent
);
2884 complexType
->contentType()->setVariety(XsdComplexType::ContentType::Simple
);
2887 validateIdAttribute("simpleContent");
2889 TagValidationHandler
tagValidator(XsdTagScope::SimpleContent
, this, m_namePool
);
2897 if (isStartElement()) {
2898 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2899 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2901 tagValidator
.validate(token
);
2903 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2904 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2905 complexType
->addAnnotation(annotation
);
2906 } else if (isSchemaTag(XsdSchemaToken::Restriction
, token
, namespaceToken
)) {
2907 parseSimpleContentRestriction(complexType
);
2908 } else if (isSchemaTag(XsdSchemaToken::Extension
, token
, namespaceToken
)) {
2909 parseSimpleContentExtension(complexType
);
2916 tagValidator
.finalize();
2919 void XsdSchemaParser::parseSimpleContentRestriction(const XsdComplexType::Ptr
&complexType
)
2921 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Restriction
, this);
2923 validateElement(XsdTagScope::SimpleContentRestriction
);
2925 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
2928 const QString baseType
= readQNameAttribute(QString::fromLatin1("base"), "restriction");
2930 convertName(baseType
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
2932 validateIdAttribute("restriction");
2934 XsdFacet::Hash facets
;
2935 QList
<XsdFacet::Ptr
> patternFacets
;
2936 QList
<XsdFacet::Ptr
> enumerationFacets
;
2937 QList
<XsdFacet::Ptr
> assertionFacets
;
2939 TagValidationHandler
tagValidator(XsdTagScope::SimpleContentRestriction
, this, m_namePool
);
2947 if (isStartElement()) {
2948 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
2949 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
2951 tagValidator
.validate(token
);
2953 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
2954 const XsdAnnotation::Ptr annotation
= parseAnnotation();
2955 complexType
->addAnnotation(annotation
);
2956 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
2957 const XsdSimpleType::Ptr type
= parseLocalSimpleType();
2958 type
->setContext(complexType
); //TODO: investigate what the schema spec really wants here?!?
2959 complexType
->contentType()->setSimpleType(type
);
2961 // add it to list of anonymous types as well
2962 addAnonymousType(type
);
2963 } else if (isSchemaTag(XsdSchemaToken::MinExclusive
, token
, namespaceToken
)) {
2964 const XsdFacet::Ptr facet
= parseMinExclusiveFacet();
2965 addFacet(facet
, facets
, complexType
);
2966 } else if (isSchemaTag(XsdSchemaToken::MinInclusive
, token
, namespaceToken
)) {
2967 const XsdFacet::Ptr facet
= parseMinInclusiveFacet();
2968 addFacet(facet
, facets
, complexType
);
2969 } else if (isSchemaTag(XsdSchemaToken::MaxExclusive
, token
, namespaceToken
)) {
2970 const XsdFacet::Ptr facet
= parseMaxExclusiveFacet();
2971 addFacet(facet
, facets
, complexType
);
2972 } else if (isSchemaTag(XsdSchemaToken::MaxInclusive
, token
, namespaceToken
)) {
2973 const XsdFacet::Ptr facet
= parseMaxInclusiveFacet();
2974 addFacet(facet
, facets
, complexType
);
2975 } else if (isSchemaTag(XsdSchemaToken::TotalDigits
, token
, namespaceToken
)) {
2976 const XsdFacet::Ptr facet
= parseTotalDigitsFacet();
2977 addFacet(facet
, facets
, complexType
);
2978 } else if (isSchemaTag(XsdSchemaToken::FractionDigits
, token
, namespaceToken
)) {
2979 const XsdFacet::Ptr facet
= parseFractionDigitsFacet();
2980 addFacet(facet
, facets
, complexType
);
2981 } else if (isSchemaTag(XsdSchemaToken::Length
, token
, namespaceToken
)) {
2982 const XsdFacet::Ptr facet
= parseLengthFacet();
2983 addFacet(facet
, facets
, complexType
);
2984 } else if (isSchemaTag(XsdSchemaToken::MinLength
, token
, namespaceToken
)) {
2985 const XsdFacet::Ptr facet
= parseMinLengthFacet();
2986 addFacet(facet
, facets
, complexType
);
2987 } else if (isSchemaTag(XsdSchemaToken::MaxLength
, token
, namespaceToken
)) {
2988 const XsdFacet::Ptr facet
= parseMaxLengthFacet();
2989 addFacet(facet
, facets
, complexType
);
2990 } else if (isSchemaTag(XsdSchemaToken::Enumeration
, token
, namespaceToken
)) {
2991 const XsdFacet::Ptr facet
= parseEnumerationFacet();
2992 enumerationFacets
.append(facet
);
2993 } else if (isSchemaTag(XsdSchemaToken::WhiteSpace
, token
, namespaceToken
)) {
2994 const XsdFacet::Ptr facet
= parseWhiteSpaceFacet();
2995 addFacet(facet
, facets
, complexType
);
2996 } else if (isSchemaTag(XsdSchemaToken::Pattern
, token
, namespaceToken
)) {
2997 const XsdFacet::Ptr facet
= parsePatternFacet();
2998 patternFacets
.append(facet
);
2999 } else if (isSchemaTag(XsdSchemaToken::Assertion
, token
, namespaceToken
)) {
3000 const XsdFacet::Ptr facet
= parseAssertionFacet();
3001 assertionFacets
.append(facet
);
3002 } else if (isSchemaTag(XsdSchemaToken::Attribute
, token
, namespaceToken
)) {
3003 const XsdAttributeUse::Ptr attributeUse
= parseLocalAttribute(complexType
);
3004 complexType
->addAttributeUse(attributeUse
);
3005 } else if (isSchemaTag(XsdSchemaToken::AttributeGroup
, token
, namespaceToken
)) {
3006 const XsdAttributeUse::Ptr attributeUse
= parseReferredAttributeGroup();
3007 complexType
->addAttributeUse(attributeUse
);
3008 } else if (isSchemaTag(XsdSchemaToken::AnyAttribute
, token
, namespaceToken
)) {
3009 const XsdWildcard::Ptr wildcard
= parseAnyAttribute();
3010 complexType
->setAttributeWildcard(wildcard
);
3011 } else if (isSchemaTag(XsdSchemaToken::Assert
, token
, namespaceToken
)) {
3012 const XsdAssertion::Ptr assertion
= parseAssertion(XsdSchemaToken::Assert
, XsdTagScope::Assert
);
3013 complexType
->addAssertion(assertion
);
3020 tagValidator
.finalize();
3022 // merge all pattern facets into one multi value facet
3023 if (!patternFacets
.isEmpty()) {
3024 const XsdFacet::Ptr
patternFacet(new XsdFacet());
3025 patternFacet
->setType(XsdFacet::Pattern
);
3027 AtomicValue::List multiValue
;
3028 for (int i
= 0; i
< patternFacets
.count(); ++i
)
3029 multiValue
<< patternFacets
.at(i
)->multiValue();
3031 patternFacet
->setMultiValue(multiValue
);
3032 addFacet(patternFacet
, facets
, complexType
);
3035 // merge all enumeration facets into one multi value facet
3036 if (!enumerationFacets
.isEmpty()) {
3037 const XsdFacet::Ptr
enumerationFacet(new XsdFacet());
3038 enumerationFacet
->setType(XsdFacet::Enumeration
);
3040 AtomicValue::List multiValue
;
3041 for (int i
= 0; i
< enumerationFacets
.count(); ++i
)
3042 multiValue
<< enumerationFacets
.at(i
)->multiValue();
3044 enumerationFacet
->setMultiValue(multiValue
);
3045 addFacet(enumerationFacet
, facets
, complexType
);
3048 // merge all assertion facets into one facet
3049 if (!assertionFacets
.isEmpty()) {
3050 const XsdFacet::Ptr
assertionFacet(new XsdFacet());
3051 assertionFacet
->setType(XsdFacet::Assertion
);
3053 XsdAssertion::List assertions
;
3054 for (int i
= 0; i
< assertionFacets
.count(); ++i
)
3055 assertions
<< assertionFacets
.at(i
)->assertions();
3057 assertionFacet
->setAssertions(assertions
);
3058 addFacet(assertionFacet
, facets
, complexType
);
3061 m_schemaResolver
->addComplexBaseType(complexType
, typeName
, currentSourceLocation(), facets
); // add to resolver
3064 void XsdSchemaParser::parseSimpleContentExtension(const XsdComplexType::Ptr
&complexType
)
3066 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Extension
, this);
3068 validateElement(XsdTagScope::SimpleContentExtension
);
3070 complexType
->setDerivationMethod(XsdComplexType::DerivationExtension
);
3073 const QString baseType
= readQNameAttribute(QString::fromLatin1("base"), "extension");
3075 convertName(baseType
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
3076 m_schemaResolver
->addComplexBaseType(complexType
, typeName
, currentSourceLocation()); // add to resolver
3078 validateIdAttribute("extension");
3080 TagValidationHandler
tagValidator(XsdTagScope::SimpleContentExtension
, this, m_namePool
);
3088 if (isStartElement()) {
3089 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3090 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3092 tagValidator
.validate(token
);
3094 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3095 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3096 complexType
->addAnnotation(annotation
);
3097 } else if (isSchemaTag(XsdSchemaToken::Attribute
, token
, namespaceToken
)) {
3098 const XsdAttributeUse::Ptr attributeUse
= parseLocalAttribute(complexType
);
3099 complexType
->addAttributeUse(attributeUse
);
3100 } else if (isSchemaTag(XsdSchemaToken::AttributeGroup
, token
, namespaceToken
)) {
3101 const XsdAttributeUse::Ptr attributeUse
= parseReferredAttributeGroup();
3102 complexType
->addAttributeUse(attributeUse
);
3103 } else if (isSchemaTag(XsdSchemaToken::AnyAttribute
, token
, namespaceToken
)) {
3104 const XsdWildcard::Ptr wildcard
= parseAnyAttribute();
3105 complexType
->setAttributeWildcard(wildcard
);
3106 } else if (isSchemaTag(XsdSchemaToken::Assert
, token
, namespaceToken
)) {
3107 const XsdAssertion::Ptr assertion
= parseAssertion(XsdSchemaToken::Assert
, XsdTagScope::Assert
);
3108 complexType
->addAssertion(assertion
);
3115 tagValidator
.finalize();
3118 void XsdSchemaParser::parseComplexContent(const XsdComplexType::Ptr
&complexType
, bool *mixed
)
3120 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::ComplexContent
, this);
3122 validateElement(XsdTagScope::ComplexContent
);
3124 complexType
->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly
);
3127 if (hasAttribute(QString::fromLatin1("mixed"))) {
3128 const QString mixedStr
= readAttribute(QString::fromLatin1("mixed"));
3130 const Boolean::Ptr value
= Boolean::fromLexical(mixedStr
);
3131 if (value
->hasError()) {
3132 attributeContentError("mixed", "complexType", mixedStr
, BuiltinTypes::xsBoolean
);
3136 *mixed
= value
->as
<Boolean
>()->value();
3141 validateIdAttribute("complexContent");
3143 TagValidationHandler
tagValidator(XsdTagScope::ComplexContent
, this, m_namePool
);
3151 if (isStartElement()) {
3152 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3153 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3155 tagValidator
.validate(token
);
3157 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3158 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3159 complexType
->addAnnotation(annotation
);
3160 } else if (isSchemaTag(XsdSchemaToken::Restriction
, token
, namespaceToken
)) {
3161 parseComplexContentRestriction(complexType
);
3162 } else if (isSchemaTag(XsdSchemaToken::Extension
, token
, namespaceToken
)) {
3163 parseComplexContentExtension(complexType
);
3170 tagValidator
.finalize();
3173 void XsdSchemaParser::parseComplexContentRestriction(const XsdComplexType::Ptr
&complexType
)
3175 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Restriction
, this);
3177 validateElement(XsdTagScope::ComplexContentRestriction
);
3179 complexType
->setDerivationMethod(XsdComplexType::DerivationRestriction
);
3182 const QString baseType
= readQNameAttribute(QString::fromLatin1("base"), "restriction");
3184 convertName(baseType
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
3185 m_schemaResolver
->addComplexBaseType(complexType
, typeName
, currentSourceLocation()); // add to resolver
3187 validateIdAttribute("restriction");
3189 TagValidationHandler
tagValidator(XsdTagScope::ComplexContentRestriction
, this, m_namePool
);
3191 bool hasContent
= false;
3198 if (isStartElement()) {
3199 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3200 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3202 tagValidator
.validate(token
);
3204 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3205 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3206 complexType
->addAnnotation(annotation
);
3207 } else if (isSchemaTag(XsdSchemaToken::OpenContent
, token
, namespaceToken
)) {
3208 const XsdComplexType::OpenContent::Ptr openContent
= parseOpenContent();
3209 complexType
->contentType()->setOpenContent(openContent
);
3211 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
3212 const XsdParticle::Ptr
particle(new XsdParticle());
3213 const XsdTerm::Ptr term
= parseReferredGroup(particle
);
3214 particle
->setTerm(term
);
3215 complexType
->contentType()->setParticle(particle
);
3217 } else if (isSchemaTag(XsdSchemaToken::All
, token
, namespaceToken
)) {
3218 const XsdParticle::Ptr
particle(new XsdParticle());
3219 const XsdTerm::Ptr term
= parseLocalAll(particle
, complexType
);
3220 particle
->setTerm(term
);
3221 complexType
->contentType()->setParticle(particle
);
3223 } else if (isSchemaTag(XsdSchemaToken::Choice
, token
, namespaceToken
)) {
3224 const XsdParticle::Ptr
particle(new XsdParticle());
3225 const XsdTerm::Ptr term
= parseLocalChoice(particle
, complexType
);
3226 particle
->setTerm(term
);
3227 complexType
->contentType()->setParticle(particle
);
3229 } else if (isSchemaTag(XsdSchemaToken::Sequence
, token
, namespaceToken
)) {
3230 const XsdParticle::Ptr
particle(new XsdParticle());
3231 const XsdTerm::Ptr term
= parseLocalSequence(particle
, complexType
);
3232 particle
->setTerm(term
);
3233 complexType
->contentType()->setParticle(particle
);
3235 } else if (isSchemaTag(XsdSchemaToken::Attribute
, token
, namespaceToken
)) {
3236 const XsdAttributeUse::Ptr attributeUse
= parseLocalAttribute(complexType
);
3237 complexType
->addAttributeUse(attributeUse
);
3238 } else if (isSchemaTag(XsdSchemaToken::AttributeGroup
, token
, namespaceToken
)) {
3239 const XsdAttributeUse::Ptr attributeUse
= parseReferredAttributeGroup();
3240 complexType
->addAttributeUse(attributeUse
);
3241 } else if (isSchemaTag(XsdSchemaToken::AnyAttribute
, token
, namespaceToken
)) {
3242 const XsdWildcard::Ptr wildcard
= parseAnyAttribute();
3243 complexType
->setAttributeWildcard(wildcard
);
3244 } else if (isSchemaTag(XsdSchemaToken::Assert
, token
, namespaceToken
)) {
3245 const XsdAssertion::Ptr assertion
= parseAssertion(XsdSchemaToken::Assert
, XsdTagScope::Assert
);
3246 complexType
->addAssertion(assertion
);
3254 complexType
->contentType()->setVariety(XsdComplexType::ContentType::Empty
);
3256 tagValidator
.finalize();
3259 void XsdSchemaParser::parseComplexContentExtension(const XsdComplexType::Ptr
&complexType
)
3261 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Extension
, this);
3263 validateElement(XsdTagScope::ComplexContentExtension
);
3265 complexType
->setDerivationMethod(XsdComplexType::DerivationExtension
);
3268 const QString baseType
= readQNameAttribute(QString::fromLatin1("base"), "extension");
3270 convertName(baseType
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
3271 m_schemaResolver
->addComplexBaseType(complexType
, typeName
, currentSourceLocation()); // add to resolver
3273 validateIdAttribute("extension");
3275 TagValidationHandler
tagValidator(XsdTagScope::ComplexContentExtension
, this, m_namePool
);
3277 bool hasContent
= false;
3284 if (isStartElement()) {
3285 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3286 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3288 tagValidator
.validate(token
);
3290 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3291 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3292 complexType
->addAnnotation(annotation
);
3293 } else if (isSchemaTag(XsdSchemaToken::OpenContent
, token
, namespaceToken
)) {
3294 const XsdComplexType::OpenContent::Ptr openContent
= parseOpenContent();
3295 complexType
->contentType()->setOpenContent(openContent
);
3297 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
3298 const XsdParticle::Ptr
particle(new XsdParticle());
3299 const XsdTerm::Ptr term
= parseReferredGroup(particle
);
3300 particle
->setTerm(term
);
3301 complexType
->contentType()->setParticle(particle
);
3303 } else if (isSchemaTag(XsdSchemaToken::All
, token
, namespaceToken
)) {
3304 const XsdParticle::Ptr
particle(new XsdParticle());
3305 const XsdTerm::Ptr term
= parseLocalAll(particle
, complexType
);
3306 particle
->setTerm(term
);
3307 complexType
->contentType()->setParticle(particle
);
3309 } else if (isSchemaTag(XsdSchemaToken::Choice
, token
, namespaceToken
)) {
3310 const XsdParticle::Ptr
particle(new XsdParticle());
3311 const XsdTerm::Ptr term
= parseLocalChoice(particle
, complexType
);
3312 particle
->setTerm(term
);
3313 complexType
->contentType()->setParticle(particle
);
3315 } else if (isSchemaTag(XsdSchemaToken::Sequence
, token
, namespaceToken
)) {
3316 const XsdParticle::Ptr
particle(new XsdParticle());
3317 const XsdTerm::Ptr term
= parseLocalSequence(particle
, complexType
);
3318 particle
->setTerm(term
);
3319 complexType
->contentType()->setParticle(particle
);
3321 } else if (isSchemaTag(XsdSchemaToken::Attribute
, token
, namespaceToken
)) {
3322 const XsdAttributeUse::Ptr attributeUse
= parseLocalAttribute(complexType
);
3323 complexType
->addAttributeUse(attributeUse
);
3324 } else if (isSchemaTag(XsdSchemaToken::AttributeGroup
, token
, namespaceToken
)) {
3325 const XsdAttributeUse::Ptr attributeUse
= parseReferredAttributeGroup();
3326 complexType
->addAttributeUse(attributeUse
);
3327 } else if (isSchemaTag(XsdSchemaToken::AnyAttribute
, token
, namespaceToken
)) {
3328 const XsdWildcard::Ptr wildcard
= parseAnyAttribute();
3329 complexType
->setAttributeWildcard(wildcard
);
3330 } else if (isSchemaTag(XsdSchemaToken::Assert
, token
, namespaceToken
)) {
3331 const XsdAssertion::Ptr assertion
= parseAssertion(XsdSchemaToken::Assert
, XsdTagScope::Assert
);
3332 complexType
->addAssertion(assertion
);
3340 complexType
->contentType()->setVariety(XsdComplexType::ContentType::Empty
);
3342 tagValidator
.finalize();
3346 XsdAssertion::Ptr
XsdSchemaParser::parseAssertion(const XsdSchemaToken::NodeName
&nodeName
, const XsdTagScope::Type
&tag
)
3348 const ElementNamespaceHandler
namespaceHandler(nodeName
, this);
3350 validateElement(tag
);
3352 const XsdAssertion::Ptr
assertion(new XsdAssertion());
3356 const XsdXPathExpression::Ptr expression
= readXPathExpression("assertion");
3357 assertion
->setTest(expression
);
3359 const QString test
= readXPathAttribute(QString::fromLatin1("test"), XPath20
, "assertion");
3360 expression
->setExpression(test
);
3362 validateIdAttribute("assertion");
3364 TagValidationHandler
tagValidator(tag
, this, m_namePool
);
3372 if (isStartElement()) {
3373 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3374 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3376 tagValidator
.validate(token
);
3378 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3379 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3380 assertion
->addAnnotation(annotation
);
3387 tagValidator
.finalize();
3392 XsdComplexType::OpenContent::Ptr
XsdSchemaParser::parseOpenContent()
3394 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::OpenContent
, this);
3396 validateElement(XsdTagScope::OpenContent
);
3398 const XsdComplexType::OpenContent::Ptr
openContent(new XsdComplexType::OpenContent());
3400 if (hasAttribute(QString::fromLatin1("mode"))) {
3401 const QString mode
= readAttribute(QString::fromLatin1("mode"));
3403 if (mode
== QString::fromLatin1("none")) {
3404 m_defaultOpenContent
->setMode(XsdComplexType::OpenContent::None
);
3405 } else if (mode
== QString::fromLatin1("interleave")) {
3406 m_defaultOpenContent
->setMode(XsdComplexType::OpenContent::Interleave
);
3407 } else if (mode
== QString::fromLatin1("suffix")) {
3408 m_defaultOpenContent
->setMode(XsdComplexType::OpenContent::Suffix
);
3410 attributeContentError("mode", "openContent", mode
);
3414 openContent
->setMode(XsdComplexType::OpenContent::Interleave
);
3417 validateIdAttribute("openContent");
3419 TagValidationHandler
tagValidator(XsdTagScope::OpenContent
, this, m_namePool
);
3427 if (isStartElement()) {
3428 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3429 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3431 tagValidator
.validate(token
);
3433 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3434 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3435 openContent
->addAnnotation(annotation
);
3436 } else if (isSchemaTag(XsdSchemaToken::Any
, token
, namespaceToken
)) {
3437 const XsdParticle::Ptr particle
;
3438 const XsdWildcard::Ptr wildcard
= parseAny(particle
);
3439 openContent
->setWildcard(wildcard
);
3446 tagValidator
.finalize();
3451 XsdModelGroup::Ptr
XsdSchemaParser::parseNamedGroup()
3453 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Group
, this);
3455 validateElement(XsdTagScope::NamedGroup
);
3457 const XsdModelGroup::Ptr
modelGroup(new XsdModelGroup());
3458 XsdModelGroup::Ptr group
;
3460 QXmlName objectName
;
3461 if (hasAttribute(QString::fromLatin1("name"))) {
3462 objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("group"));
3465 validateIdAttribute("group");
3467 TagValidationHandler
tagValidator(XsdTagScope::NamedGroup
, this, m_namePool
);
3469 XsdAnnotation::Ptr annotation
;
3477 if (isStartElement()) {
3478 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3479 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3481 tagValidator
.validate(token
);
3483 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3484 annotation
= parseAnnotation();
3485 } else if (isSchemaTag(XsdSchemaToken::All
, token
, namespaceToken
)) {
3486 group
= parseAll(modelGroup
);
3487 } else if (isSchemaTag(XsdSchemaToken::Choice
, token
, namespaceToken
)) {
3488 group
= parseChoice(modelGroup
);
3489 } else if (isSchemaTag(XsdSchemaToken::Sequence
, token
, namespaceToken
)) {
3490 group
= parseSequence(modelGroup
);
3497 tagValidator
.finalize();
3499 group
->setName(objectName
);
3502 group
->addAnnotation(annotation
);
3507 XsdTerm::Ptr
XsdSchemaParser::parseReferredGroup(const XsdParticle::Ptr
&particle
)
3509 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Group
, this);
3511 validateElement(XsdTagScope::ReferredGroup
);
3513 const XsdReference::Ptr
reference(new XsdReference());
3514 reference
->setType(XsdReference::ModelGroup
);
3515 reference
->setSourceLocation(currentSourceLocation());
3518 if (!parseMinMaxConstraint(particle
, "group")) {
3522 const QString value
= readQNameAttribute(QString::fromLatin1("ref"), "group");
3523 QXmlName referenceName
;
3524 convertName(value
, NamespaceSupport::ElementName
, referenceName
); // translate qualified name into QXmlName
3525 reference
->setReferenceName(referenceName
);
3527 validateIdAttribute("group");
3529 TagValidationHandler
tagValidator(XsdTagScope::ReferredGroup
, this, m_namePool
);
3537 if (isStartElement()) {
3538 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3539 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3541 tagValidator
.validate(token
);
3543 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3544 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3545 reference
->addAnnotation(annotation
);
3552 tagValidator
.finalize();
3557 XsdModelGroup::Ptr
XsdSchemaParser::parseAll(const NamedSchemaComponent::Ptr
&parent
)
3559 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::All
, this);
3561 validateElement(XsdTagScope::All
);
3563 const XsdModelGroup::Ptr
modelGroup(new XsdModelGroup());
3564 modelGroup
->setCompositor(XsdModelGroup::AllCompositor
);
3566 validateIdAttribute("all");
3568 TagValidationHandler
tagValidator(XsdTagScope::All
, this, m_namePool
);
3570 XsdParticle::List particles
;
3577 if (isStartElement()) {
3578 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3579 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3581 tagValidator
.validate(token
);
3583 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3584 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3585 modelGroup
->addAnnotation(annotation
);
3586 } else if (isSchemaTag(XsdSchemaToken::Element
, token
, namespaceToken
)) {
3587 const XsdParticle::Ptr
particle(new XsdParticle());
3588 const XsdTerm::Ptr term
= parseLocalElement(particle
, parent
);
3589 particle
->setTerm(term
);
3591 if (particle
->maximumOccursUnbounded() || particle
->maximumOccurs() > 1) {
3592 error(QtXmlPatterns::tr("%1 attribute of %2 element must be %3 or %4.")
3593 .arg(formatAttribute("maxOccurs"))
3594 .arg(formatElement("all"))
3595 .arg(formatData("0"))
3596 .arg(formatData("1")));
3600 particles
.append(particle
);
3607 modelGroup
->setParticles(particles
);
3609 tagValidator
.finalize();
3614 XsdModelGroup::Ptr
XsdSchemaParser::parseLocalAll(const XsdParticle::Ptr
&particle
, const NamedSchemaComponent::Ptr
&parent
)
3616 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::All
, this);
3618 validateElement(XsdTagScope::LocalAll
);
3620 const XsdModelGroup::Ptr
modelGroup(new XsdModelGroup());
3621 modelGroup
->setCompositor(XsdModelGroup::AllCompositor
);
3624 if (!parseMinMaxConstraint(particle
, "all")) {
3627 if (particle
->maximumOccursUnbounded() || particle
->maximumOccurs() != 1) {
3628 error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3.")
3629 .arg(formatAttribute("maxOccurs"))
3630 .arg(formatElement("all"))
3631 .arg(formatData("1")));
3634 if (particle
->minimumOccurs() != 0 && particle
->minimumOccurs() != 1) {
3635 error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4.")
3636 .arg(formatAttribute("minOccurs"))
3637 .arg(formatElement("all"))
3638 .arg(formatData("0"))
3639 .arg(formatData("1")));
3643 validateIdAttribute("all");
3645 TagValidationHandler
tagValidator(XsdTagScope::LocalAll
, this, m_namePool
);
3647 XsdParticle::List particles
;
3654 if (isStartElement()) {
3655 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3656 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3658 tagValidator
.validate(token
);
3660 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3661 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3662 modelGroup
->addAnnotation(annotation
);
3663 } else if (isSchemaTag(XsdSchemaToken::Element
, token
, namespaceToken
)) {
3664 const XsdParticle::Ptr
particle(new XsdParticle());
3665 const XsdTerm::Ptr term
= parseLocalElement(particle
, parent
);
3666 particle
->setTerm(term
);
3668 if (particle
->maximumOccursUnbounded() || particle
->maximumOccurs() > 1) {
3669 error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4.")
3670 .arg(formatAttribute("maxOccurs"))
3671 .arg(formatElement("all"))
3672 .arg(formatData("0"))
3673 .arg(formatData("1")));
3677 particles
.append(particle
);
3684 modelGroup
->setParticles(particles
);
3686 tagValidator
.finalize();
3691 XsdModelGroup::Ptr
XsdSchemaParser::parseChoice(const NamedSchemaComponent::Ptr
&parent
)
3693 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Choice
, this);
3695 validateElement(XsdTagScope::Choice
);
3697 const XsdModelGroup::Ptr
modelGroup(new XsdModelGroup());
3698 modelGroup
->setCompositor(XsdModelGroup::ChoiceCompositor
);
3700 validateIdAttribute("choice");
3702 XsdParticle::List particles
;
3704 TagValidationHandler
tagValidator(XsdTagScope::Choice
, this, m_namePool
);
3712 if (isStartElement()) {
3713 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3714 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3716 tagValidator
.validate(token
);
3718 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3719 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3720 modelGroup
->addAnnotation(annotation
);
3721 } else if (isSchemaTag(XsdSchemaToken::Element
, token
, namespaceToken
)) {
3722 const XsdParticle::Ptr
particle(new XsdParticle());
3723 const XsdTerm::Ptr term
= parseLocalElement(particle
, parent
);
3724 particle
->setTerm(term
);
3725 particles
.append(particle
);
3726 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
3727 const XsdParticle::Ptr
particle(new XsdParticle());
3728 const XsdTerm::Ptr term
= parseReferredGroup(particle
);
3729 m_schemaResolver
->addAllGroupCheck(term
);
3730 particle
->setTerm(term
);
3731 particles
.append(particle
);
3732 } else if (isSchemaTag(XsdSchemaToken::Choice
, token
, namespaceToken
)) {
3733 const XsdParticle::Ptr
particle(new XsdParticle());
3734 const XsdTerm::Ptr term
= parseLocalChoice(particle
, parent
);
3735 particle
->setTerm(term
);
3736 particles
.append(particle
);
3737 } else if (isSchemaTag(XsdSchemaToken::Sequence
, token
, namespaceToken
)) {
3738 const XsdParticle::Ptr
particle(new XsdParticle());
3739 const XsdTerm::Ptr term
= parseLocalSequence(particle
, parent
);
3740 particle
->setTerm(term
);
3741 particles
.append(particle
);
3742 } else if (isSchemaTag(XsdSchemaToken::Any
, token
, namespaceToken
)) {
3743 const XsdParticle::Ptr
particle(new XsdParticle());
3744 const XsdTerm::Ptr term
= parseAny(particle
);
3745 particle
->setTerm(term
);
3746 particles
.append(particle
);
3753 modelGroup
->setParticles(particles
);
3755 tagValidator
.finalize();
3760 XsdModelGroup::Ptr
XsdSchemaParser::parseLocalChoice(const XsdParticle::Ptr
&particle
, const NamedSchemaComponent::Ptr
&parent
)
3762 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Choice
, this);
3764 validateElement(XsdTagScope::LocalChoice
);
3766 const XsdModelGroup::Ptr
modelGroup(new XsdModelGroup());
3767 modelGroup
->setCompositor(XsdModelGroup::ChoiceCompositor
);
3770 if (!parseMinMaxConstraint(particle
, "choice")) {
3774 validateIdAttribute("choice");
3776 XsdParticle::List particles
;
3778 TagValidationHandler
tagValidator(XsdTagScope::LocalChoice
, this, m_namePool
);
3786 if (isStartElement()) {
3787 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3788 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3790 tagValidator
.validate(token
);
3792 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3793 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3794 modelGroup
->addAnnotation(annotation
);
3795 } else if (isSchemaTag(XsdSchemaToken::Element
, token
, namespaceToken
)) {
3796 const XsdParticle::Ptr
particle(new XsdParticle());
3797 const XsdTerm::Ptr term
= parseLocalElement(particle
, parent
);
3798 particle
->setTerm(term
);
3799 particles
.append(particle
);
3800 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
3801 const XsdParticle::Ptr
particle(new XsdParticle());
3802 const XsdTerm::Ptr term
= parseReferredGroup(particle
);
3803 m_schemaResolver
->addAllGroupCheck(term
);
3804 particle
->setTerm(term
);
3805 particles
.append(particle
);
3806 } else if (isSchemaTag(XsdSchemaToken::Choice
, token
, namespaceToken
)) {
3807 const XsdParticle::Ptr
particle(new XsdParticle());
3808 const XsdTerm::Ptr term
= parseLocalChoice(particle
, parent
);
3809 particle
->setTerm(term
);
3810 particles
.append(particle
);
3811 } else if (isSchemaTag(XsdSchemaToken::Sequence
, token
, namespaceToken
)) {
3812 const XsdParticle::Ptr
particle(new XsdParticle());
3813 const XsdTerm::Ptr term
= parseLocalSequence(particle
, parent
);
3814 particle
->setTerm(term
);
3815 particles
.append(particle
);
3816 } else if (isSchemaTag(XsdSchemaToken::Any
, token
, namespaceToken
)) {
3817 const XsdParticle::Ptr
particle(new XsdParticle());
3818 const XsdTerm::Ptr term
= parseAny(particle
);
3819 particle
->setTerm(term
);
3820 particles
.append(particle
);
3827 modelGroup
->setParticles(particles
);
3829 tagValidator
.finalize();
3834 XsdModelGroup::Ptr
XsdSchemaParser::parseSequence(const NamedSchemaComponent::Ptr
&parent
)
3836 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Sequence
, this);
3838 validateElement(XsdTagScope::Sequence
);
3840 const XsdModelGroup::Ptr
modelGroup(new XsdModelGroup());
3841 modelGroup
->setCompositor(XsdModelGroup::SequenceCompositor
);
3843 validateIdAttribute("sequence");
3845 XsdParticle::List particles
;
3847 TagValidationHandler
tagValidator(XsdTagScope::Sequence
, this, m_namePool
);
3855 if (isStartElement()) {
3856 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3857 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3859 tagValidator
.validate(token
);
3861 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3862 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3863 modelGroup
->addAnnotation(annotation
);
3864 } else if (isSchemaTag(XsdSchemaToken::Element
, token
, namespaceToken
)) {
3865 const XsdParticle::Ptr
particle(new XsdParticle());
3866 const XsdTerm::Ptr term
= parseLocalElement(particle
, parent
);
3867 particle
->setTerm(term
);
3868 particles
.append(particle
);
3869 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
3870 const XsdParticle::Ptr
particle(new XsdParticle());
3871 const XsdTerm::Ptr term
= parseReferredGroup(particle
);
3872 m_schemaResolver
->addAllGroupCheck(term
);
3873 particle
->setTerm(term
);
3874 particles
.append(particle
);
3875 } else if (isSchemaTag(XsdSchemaToken::Choice
, token
, namespaceToken
)) {
3876 const XsdParticle::Ptr
particle(new XsdParticle());
3877 const XsdTerm::Ptr term
= parseLocalChoice(particle
, parent
);
3878 particle
->setTerm(term
);
3879 particles
.append(particle
);
3880 } else if (isSchemaTag(XsdSchemaToken::Sequence
, token
, namespaceToken
)) {
3881 const XsdParticle::Ptr
particle(new XsdParticle());
3882 const XsdTerm::Ptr term
= parseLocalSequence(particle
, parent
);
3883 particle
->setTerm(term
);
3884 particles
.append(particle
);
3885 } else if (isSchemaTag(XsdSchemaToken::Any
, token
, namespaceToken
)) {
3886 const XsdParticle::Ptr
particle(new XsdParticle());
3887 const XsdTerm::Ptr term
= parseAny(particle
);
3888 particle
->setTerm(term
);
3889 particles
.append(particle
);
3896 modelGroup
->setParticles(particles
);
3898 tagValidator
.finalize();
3903 XsdModelGroup::Ptr
XsdSchemaParser::parseLocalSequence(const XsdParticle::Ptr
&particle
, const NamedSchemaComponent::Ptr
&parent
)
3905 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Sequence
, this);
3907 validateElement(XsdTagScope::LocalSequence
);
3909 const XsdModelGroup::Ptr
modelGroup(new XsdModelGroup());
3910 modelGroup
->setCompositor(XsdModelGroup::SequenceCompositor
);
3913 if (!parseMinMaxConstraint(particle
, "sequence")) {
3917 validateIdAttribute("sequence");
3919 XsdParticle::List particles
;
3921 TagValidationHandler
tagValidator(XsdTagScope::LocalSequence
, this, m_namePool
);
3929 if (isStartElement()) {
3930 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
3931 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
3933 tagValidator
.validate(token
);
3935 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
3936 const XsdAnnotation::Ptr annotation
= parseAnnotation();
3937 modelGroup
->addAnnotation(annotation
);
3938 } else if (isSchemaTag(XsdSchemaToken::Element
, token
, namespaceToken
)) {
3939 const XsdParticle::Ptr
particle(new XsdParticle());
3940 const XsdTerm::Ptr term
= parseLocalElement(particle
, parent
);
3941 particle
->setTerm(term
);
3942 particles
.append(particle
);
3943 } else if (isSchemaTag(XsdSchemaToken::Group
, token
, namespaceToken
)) {
3944 const XsdParticle::Ptr
particle(new XsdParticle());
3945 const XsdTerm::Ptr term
= parseReferredGroup(particle
);
3946 m_schemaResolver
->addAllGroupCheck(term
);
3947 particle
->setTerm(term
);
3948 particles
.append(particle
);
3949 } else if (isSchemaTag(XsdSchemaToken::Choice
, token
, namespaceToken
)) {
3950 const XsdParticle::Ptr
particle(new XsdParticle());
3951 const XsdTerm::Ptr term
= parseLocalChoice(particle
, parent
);
3952 particle
->setTerm(term
);
3953 particles
.append(particle
);
3954 } else if (isSchemaTag(XsdSchemaToken::Sequence
, token
, namespaceToken
)) {
3955 const XsdParticle::Ptr
particle(new XsdParticle());
3956 const XsdTerm::Ptr term
= parseLocalSequence(particle
, parent
);
3957 particle
->setTerm(term
);
3958 particles
.append(particle
);
3959 } else if (isSchemaTag(XsdSchemaToken::Any
, token
, namespaceToken
)) {
3960 const XsdParticle::Ptr
particle(new XsdParticle());
3961 const XsdTerm::Ptr term
= parseAny(particle
);
3962 particle
->setTerm(term
);
3963 particles
.append(particle
);
3970 modelGroup
->setParticles(particles
);
3972 tagValidator
.finalize();
3977 XsdAttribute::Ptr
XsdSchemaParser::parseGlobalAttribute()
3979 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Attribute
, this);
3981 validateElement(XsdTagScope::GlobalAttribute
);
3983 const XsdAttribute::Ptr
attribute(new XsdAttribute());
3984 attribute
->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
3985 attribute
->scope()->setVariety(XsdAttribute::Scope::Global
);
3987 if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
3988 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
3989 .arg(formatElement("attribute"))
3990 .arg(formatAttribute("default"))
3991 .arg(formatAttribute("fixed")));
3996 if (hasAttribute(QString::fromLatin1("default"))) {
3997 const QString value
= readAttribute(QString::fromLatin1("default"));
3998 attribute
->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
3999 attribute
->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Default
);
4000 attribute
->valueConstraint()->setValue(value
);
4001 } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4002 const QString value
= readAttribute(QString::fromLatin1("fixed"));
4003 attribute
->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
4004 attribute
->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Fixed
);
4005 attribute
->valueConstraint()->setValue(value
);
4008 const QXmlName objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("attribute"));
4009 if ((objectName
.namespaceURI() == StandardNamespaces::xsi
) &&
4010 (m_namePool
->stringForLocalName(objectName
.localName()) != QString::fromLatin1("type")) &&
4011 (m_namePool
->stringForLocalName(objectName
.localName()) != QString::fromLatin1("nil")) &&
4012 (m_namePool
->stringForLocalName(objectName
.localName()) != QString::fromLatin1("schemaLocation")) &&
4013 (m_namePool
->stringForLocalName(objectName
.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) {
4015 error(QtXmlPatterns::tr("Content of %1 attribute of %2 element must not be from namespace %3.")
4016 .arg(formatAttribute("name"))
4017 .arg(formatElement("attribute"))
4018 .arg(formatURI(CommonNamespaces::XSI
)));
4021 if (m_namePool
->stringForLocalName(objectName
.localName()) == QString::fromLatin1("xmlns")) {
4022 error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3.")
4023 .arg(formatAttribute("name"))
4024 .arg(formatElement("attribute"))
4025 .arg(formatData("xmlns")));
4028 attribute
->setName(objectName
);
4030 bool hasTypeAttribute
= false;
4031 bool hasTypeSpecified
= false;
4033 if (hasAttribute(QString::fromLatin1("type"))) {
4034 hasTypeAttribute
= true;
4036 const QString type
= readQNameAttribute(QString::fromLatin1("type"), "attribute");
4038 convertName(type
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
4039 m_schemaResolver
->addAttributeType(attribute
, typeName
, currentSourceLocation()); // add to resolver
4040 hasTypeSpecified
= true;
4043 validateIdAttribute("attribute");
4045 TagValidationHandler
tagValidator(XsdTagScope::GlobalAttribute
, this, m_namePool
);
4053 if (isStartElement()) {
4054 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
4055 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
4057 tagValidator
.validate(token
);
4059 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
4060 const XsdAnnotation::Ptr annotation
= parseAnnotation();
4061 attribute
->addAnnotation(annotation
);
4062 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
4063 if (hasTypeAttribute
) {
4064 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4065 .arg(formatElement("attribute"))
4066 .arg(formatElement("simpleType"))
4067 .arg(formatAttribute("type")));
4071 const XsdSimpleType::Ptr type
= parseLocalSimpleType();
4072 type
->setContext(attribute
);
4073 attribute
->setType(type
);
4074 hasTypeSpecified
= true;
4076 // add it to list of anonymous types as well
4077 addAnonymousType(type
);
4084 if (!hasTypeSpecified
) {
4085 attribute
->setType(BuiltinTypes::xsAnySimpleType
); // default value
4089 tagValidator
.finalize();
4094 XsdAttributeUse::Ptr
XsdSchemaParser::parseLocalAttribute(const NamedSchemaComponent::Ptr
&parent
)
4096 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Attribute
, this);
4098 validateElement(XsdTagScope::LocalAttribute
);
4100 bool hasRefAttribute
= false;
4101 bool hasTypeAttribute
= false;
4102 bool hasTypeSpecified
= false;
4104 XsdAttributeUse::Ptr attributeUse
;
4105 if (hasAttribute(QString::fromLatin1("ref"))) {
4106 const XsdAttributeReference::Ptr reference
= XsdAttributeReference::Ptr(new XsdAttributeReference());
4107 reference
->setType(XsdAttributeReference::AttributeUse
);
4108 reference
->setSourceLocation(currentSourceLocation());
4110 attributeUse
= reference
;
4111 hasRefAttribute
= true;
4113 attributeUse
= XsdAttributeUse::Ptr(new XsdAttributeUse());
4116 if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
4117 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4118 .arg(formatElement("attribute"))
4119 .arg(formatAttribute("default"))
4120 .arg(formatAttribute("fixed")));
4121 return attributeUse
;
4124 if (hasRefAttribute
) {
4125 if (hasAttribute(QString::fromLatin1("form"))) {
4126 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4127 .arg(formatElement("attribute"))
4128 .arg(formatAttribute("ref"))
4129 .arg(formatAttribute("form")));
4130 return attributeUse
;
4132 if (hasAttribute(QString::fromLatin1("name"))) {
4133 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4134 .arg(formatElement("attribute"))
4135 .arg(formatAttribute("ref"))
4136 .arg(formatAttribute("name")));
4137 return attributeUse
;
4139 if (hasAttribute(QString::fromLatin1("type"))) {
4140 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4141 .arg(formatElement("attribute"))
4142 .arg(formatAttribute("ref"))
4143 .arg(formatAttribute("type")));
4144 return attributeUse
;
4150 // default, fixed and use are handled by both, attribute use and attribute reference
4151 if (hasAttribute(QString::fromLatin1("default"))) {
4152 const QString value
= readAttribute(QString::fromLatin1("default"));
4153 attributeUse
->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint()));
4154 attributeUse
->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Default
);
4155 attributeUse
->valueConstraint()->setValue(value
);
4156 } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4157 const QString value
= readAttribute(QString::fromLatin1("fixed"));
4158 attributeUse
->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint()));
4159 attributeUse
->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Fixed
);
4160 attributeUse
->valueConstraint()->setValue(value
);
4163 if (hasAttribute(QString::fromLatin1("use"))) {
4164 const QString value
= readAttribute(QString::fromLatin1("use"));
4165 if (value
!= QString::fromLatin1("optional") &&
4166 value
!= QString::fromLatin1("prohibited") &&
4167 value
!= QString::fromLatin1("required")) {
4168 attributeContentError("use", "attribute", value
);
4169 return attributeUse
;
4172 if (value
== QString::fromLatin1("optional"))
4173 attributeUse
->setUseType(XsdAttributeUse::OptionalUse
);
4174 else if (value
== QString::fromLatin1("prohibited"))
4175 attributeUse
->setUseType(XsdAttributeUse::ProhibitedUse
);
4176 else if (value
== QString::fromLatin1("required"))
4177 attributeUse
->setUseType(XsdAttributeUse::RequiredUse
);
4179 if (attributeUse
->valueConstraint() && attributeUse
->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Default
&& value
!= QString::fromLatin1("optional")) {
4180 error(QtXmlPatterns::tr("%1 attribute of %2 element must have the value %3 because the %4 attribute is set.")
4181 .arg(formatAttribute("use"))
4182 .arg(formatElement("attribute"))
4183 .arg(formatData("optional"))
4184 .arg(formatElement("default")));
4185 return attributeUse
;
4189 const XsdAttribute::Ptr
attribute(new XsdAttribute());
4191 attributeUse
->setAttribute(attribute
);
4192 m_componentLocationHash
.insert(attribute
, currentSourceLocation());
4194 attribute
->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
4195 attribute
->scope()->setVariety(XsdAttribute::Scope::Local
);
4196 attribute
->scope()->setParent(parent
);
4198 // now make a difference between attribute reference and attribute use
4199 if (hasRefAttribute
) {
4200 const QString reference
= readQNameAttribute(QString::fromLatin1("ref"), "attribute");
4201 QXmlName referenceName
;
4202 convertName(reference
, NamespaceSupport::ElementName
, referenceName
); // translate qualified name into QXmlName
4204 const XsdAttributeReference::Ptr attributeReference
= attributeUse
;
4205 attributeReference
->setReferenceName(referenceName
);
4207 if (hasAttribute(QString::fromLatin1("name"))) {
4208 const QString attributeName
= readNameAttribute("attribute");
4210 QXmlName objectName
;
4211 if (hasAttribute(QString::fromLatin1("form"))) {
4212 const QString value
= readAttribute(QString::fromLatin1("form"));
4213 if (value
!= QString::fromLatin1("qualified") && value
!= QString::fromLatin1("unqualified")) {
4214 attributeContentError("form", "attribute", value
);
4215 return attributeUse
;
4218 if (value
== QString::fromLatin1("qualified")) {
4219 objectName
= m_namePool
->allocateQName(m_targetNamespace
, attributeName
);
4221 objectName
= m_namePool
->allocateQName(QString(), attributeName
);
4224 if (m_attributeFormDefault
== QString::fromLatin1("qualified")) {
4225 objectName
= m_namePool
->allocateQName(m_targetNamespace
, attributeName
);
4227 objectName
= m_namePool
->allocateQName(QString(), attributeName
);
4231 if ((objectName
.namespaceURI() == StandardNamespaces::xsi
) &&
4232 (m_namePool
->stringForLocalName(objectName
.localName()) != QString::fromLatin1("type")) &&
4233 (m_namePool
->stringForLocalName(objectName
.localName()) != QString::fromLatin1("nil")) &&
4234 (m_namePool
->stringForLocalName(objectName
.localName()) != QString::fromLatin1("schemaLocation")) &&
4235 (m_namePool
->stringForLocalName(objectName
.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) {
4237 error(QtXmlPatterns::tr("Content of %1 attribute of %2 element must not be from namespace %3.")
4238 .arg(formatAttribute("name"))
4239 .arg(formatElement("attribute"))
4240 .arg(formatURI(CommonNamespaces::XSI
)));
4241 return attributeUse
;
4243 if (m_namePool
->stringForLocalName(objectName
.localName()) == QString::fromLatin1("xmlns")) {
4244 error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3.")
4245 .arg(formatAttribute("name"))
4246 .arg(formatElement("attribute"))
4247 .arg(formatData("xmlns")));
4248 return attributeUse
;
4251 attribute
->setName(objectName
);
4254 if (hasAttribute(QString::fromLatin1("type"))) {
4255 hasTypeAttribute
= true;
4257 const QString type
= readQNameAttribute(QString::fromLatin1("type"), "attribute");
4259 convertName(type
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
4260 m_schemaResolver
->addAttributeType(attribute
, typeName
, currentSourceLocation()); // add to resolver
4261 hasTypeSpecified
= true;
4264 if (attributeUse
->valueConstraint()) {
4265 //TODO: check whether assigning the value constraint of the attribute use to the attribute is correct
4266 if (!attribute
->valueConstraint())
4267 attribute
->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
4269 attribute
->valueConstraint()->setVariety((XsdAttribute::ValueConstraint::Variety
)attributeUse
->valueConstraint()->variety());
4270 attribute
->valueConstraint()->setValue(attributeUse
->valueConstraint()->value());
4271 attribute
->valueConstraint()->setLexicalForm(attributeUse
->valueConstraint()->lexicalForm());
4275 validateIdAttribute("attribute");
4277 TagValidationHandler
tagValidator(XsdTagScope::LocalAttribute
, this, m_namePool
);
4285 if (isStartElement()) {
4286 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
4287 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
4289 tagValidator
.validate(token
);
4291 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
4292 const XsdAnnotation::Ptr annotation
= parseAnnotation();
4293 attribute
->addAnnotation(annotation
);
4294 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
4295 if (hasTypeAttribute
) {
4296 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4297 .arg(formatElement("attribute"))
4298 .arg(formatElement("simpleType"))
4299 .arg(formatAttribute("type")));
4302 if (hasRefAttribute
) {
4303 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4304 .arg(formatElement("attribute"))
4305 .arg(formatElement("simpleType"))
4306 .arg(formatAttribute("ref")));
4310 const XsdSimpleType::Ptr type
= parseLocalSimpleType();
4311 type
->setContext(attribute
);
4312 attribute
->setType(type
);
4313 hasTypeSpecified
= true;
4315 // add it to list of anonymous types as well
4316 addAnonymousType(type
);
4323 if (!hasTypeSpecified
) {
4324 attribute
->setType(BuiltinTypes::xsAnySimpleType
); // default value
4327 tagValidator
.finalize();
4329 return attributeUse
;
4332 XsdAttributeGroup::Ptr
XsdSchemaParser::parseNamedAttributeGroup()
4334 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::AttributeGroup
, this);
4336 validateElement(XsdTagScope::NamedAttributeGroup
);
4338 const XsdAttributeGroup::Ptr
attributeGroup(new XsdAttributeGroup());
4341 const QXmlName objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("attributeGroup"));
4342 attributeGroup
->setName(objectName
);
4344 validateIdAttribute("attributeGroup");
4346 TagValidationHandler
tagValidator(XsdTagScope::NamedAttributeGroup
, this, m_namePool
);
4354 if (isStartElement()) {
4355 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
4356 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
4358 tagValidator
.validate(token
);
4360 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
4361 const XsdAnnotation::Ptr annotation
= parseAnnotation();
4362 attributeGroup
->addAnnotation(annotation
);
4363 } else if (isSchemaTag(XsdSchemaToken::Attribute
, token
, namespaceToken
)) {
4364 const XsdAttributeUse::Ptr attributeUse
= parseLocalAttribute(attributeGroup
);
4366 if (attributeUse
->useType() == XsdAttributeUse::ProhibitedUse
) {
4367 warning(QtXmlPatterns::tr("Specifying use='prohibited' inside an attribute group has no effect."));
4369 attributeGroup
->addAttributeUse(attributeUse
);
4371 } else if (isSchemaTag(XsdSchemaToken::AttributeGroup
, token
, namespaceToken
)) {
4372 const XsdAttributeUse::Ptr attributeUse
= parseReferredAttributeGroup();
4373 attributeGroup
->addAttributeUse(attributeUse
);
4374 } else if (isSchemaTag(XsdSchemaToken::AnyAttribute
, token
, namespaceToken
)) {
4375 const XsdWildcard::Ptr wildcard
= parseAnyAttribute();
4376 attributeGroup
->setWildcard(wildcard
);
4383 tagValidator
.finalize();
4385 return attributeGroup
;
4388 XsdAttributeUse::Ptr
XsdSchemaParser::parseReferredAttributeGroup()
4390 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::AttributeGroup
, this);
4392 validateElement(XsdTagScope::ReferredAttributeGroup
);
4394 const XsdAttributeReference::Ptr
attributeReference(new XsdAttributeReference());
4395 attributeReference
->setType(XsdAttributeReference::AttributeGroup
);
4396 attributeReference
->setSourceLocation(currentSourceLocation());
4399 const QString reference
= readQNameAttribute(QString::fromLatin1("ref"), "attributeGroup");
4400 QXmlName referenceName
;
4401 convertName(reference
, NamespaceSupport::ElementName
, referenceName
); // translate qualified name into QXmlName
4402 attributeReference
->setReferenceName(referenceName
);
4404 validateIdAttribute("attributeGroup");
4406 TagValidationHandler
tagValidator(XsdTagScope::ReferredAttributeGroup
, this, m_namePool
);
4414 if (isStartElement()) {
4415 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
4416 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
4418 tagValidator
.validate(token
);
4420 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
4421 const XsdAnnotation::Ptr annotation
= parseAnnotation();
4422 attributeReference
->addAnnotation(annotation
);
4429 tagValidator
.finalize();
4431 return attributeReference
;
4434 XsdElement::Ptr
XsdSchemaParser::parseGlobalElement()
4436 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Element
, this);
4438 validateElement(XsdTagScope::GlobalElement
);
4440 const XsdElement::Ptr
element(new XsdElement());
4441 element
->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope()));
4442 element
->scope()->setVariety(XsdElement::Scope::Global
);
4444 bool hasTypeAttribute
= false;
4445 bool hasTypeSpecified
= false;
4446 bool hasSubstitutionGroup
= false;
4449 const QXmlName objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("element"));
4450 element
->setName(objectName
);
4452 if (hasAttribute(QString::fromLatin1("abstract"))) {
4453 const QString abstract
= readAttribute(QString::fromLatin1("abstract"));
4455 const Boolean::Ptr value
= Boolean::fromLexical(abstract
);
4456 if (value
->hasError()) {
4457 attributeContentError("abstract", "element", abstract
, BuiltinTypes::xsBoolean
);
4461 element
->setIsAbstract(value
->as
<Boolean
>()->value());
4463 element
->setIsAbstract(false); // the default value
4466 if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
4467 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4468 .arg(formatElement("element"))
4469 .arg(formatAttribute("default"))
4470 .arg(formatAttribute("fixed")));
4474 if (hasAttribute(QString::fromLatin1("default"))) {
4475 const QString value
= readAttribute(QString::fromLatin1("default"));
4476 element
->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
4477 element
->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default
);
4478 element
->valueConstraint()->setValue(value
);
4479 } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4480 const QString value
= readAttribute(QString::fromLatin1("fixed"));
4481 element
->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
4482 element
->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed
);
4483 element
->valueConstraint()->setValue(value
);
4486 element
->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint
| NamedSchemaComponent::RestrictionConstraint
| NamedSchemaComponent::SubstitutionConstraint
, "element"));
4487 element
->setSubstitutionGroupExclusions(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint
| SchemaType::RestrictionConstraint
, "element"));
4489 if (hasAttribute(QString::fromLatin1("nillable"))) {
4490 const QString nillable
= readAttribute(QString::fromLatin1("nillable"));
4492 const Boolean::Ptr value
= Boolean::fromLexical(nillable
);
4493 if (value
->hasError()) {
4494 attributeContentError("nillable", "element", nillable
, BuiltinTypes::xsBoolean
);
4498 element
->setIsNillable(value
->as
<Boolean
>()->value());
4500 element
->setIsNillable(false); // the default value
4503 if (hasAttribute(QString::fromLatin1("type"))) {
4504 const QString type
= readQNameAttribute(QString::fromLatin1("type"), "element");
4506 convertName(type
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
4507 m_schemaResolver
->addElementType(element
, typeName
, currentSourceLocation()); // add to resolver
4509 hasTypeAttribute
= true;
4510 hasTypeSpecified
= true;
4513 if (hasAttribute(QString::fromLatin1("substitutionGroup"))) {
4514 QList
<QXmlName
> elementNames
;
4516 const QString value
= readAttribute(QString::fromLatin1("substitutionGroup"));
4517 const QStringList substitutionGroups
= value
.split(QLatin1Char(' '), QString::SkipEmptyParts
);
4518 if (substitutionGroups
.isEmpty()) {
4519 attributeContentError("substitutionGroup", "element", value
, BuiltinTypes::xsQName
);
4523 for (int i
= 0; i
< substitutionGroups
.count(); ++i
) {
4524 const QString value
= substitutionGroups
.at(i
).simplified();
4525 if (!XPathHelper::isQName(value
)) {
4526 attributeContentError("substitutionGroup", "element", value
, BuiltinTypes::xsQName
);
4530 QXmlName elementName
;
4531 convertName(value
, NamespaceSupport::ElementName
, elementName
); // translate qualified name into QXmlName
4532 elementNames
.append(elementName
);
4535 m_schemaResolver
->addSubstitutionGroupAffiliation(element
, elementNames
, currentSourceLocation()); // add to resolver
4537 hasSubstitutionGroup
= true;
4540 validateIdAttribute("element");
4542 XsdAlternative::List alternatives
;
4544 TagValidationHandler
tagValidator(XsdTagScope::GlobalElement
, this, m_namePool
);
4552 if (isStartElement()) {
4553 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
4554 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
4556 tagValidator
.validate(token
);
4558 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
4559 const XsdAnnotation::Ptr annotation
= parseAnnotation();
4560 element
->addAnnotation(annotation
);
4561 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
4562 if (hasTypeAttribute
) {
4563 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4564 .arg(formatElement("element"))
4565 .arg(formatElement("simpleType"))
4566 .arg(formatAttribute("type")));
4570 const XsdSimpleType::Ptr type
= parseLocalSimpleType();
4571 type
->setContext(element
);
4572 element
->setType(type
);
4574 // add it to list of anonymous types as well
4575 addAnonymousType(type
);
4577 hasTypeSpecified
= true;
4578 } else if (isSchemaTag(XsdSchemaToken::ComplexType
, token
, namespaceToken
)) {
4579 if (hasTypeAttribute
) {
4580 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4581 .arg(formatElement("element"))
4582 .arg(formatElement("complexType"))
4583 .arg(formatAttribute("type")));
4587 const XsdComplexType::Ptr type
= parseLocalComplexType();
4588 type
->setContext(element
);
4589 element
->setType(type
);
4591 // add it to list of anonymous types as well
4592 addAnonymousType(type
);
4594 hasTypeSpecified
= true;
4595 } else if (isSchemaTag(XsdSchemaToken::Alternative
, token
, namespaceToken
)) {
4596 const XsdAlternative::Ptr alternative
= parseAlternative();
4597 alternatives
.append(alternative
);
4598 } else if (isSchemaTag(XsdSchemaToken::Unique
, token
, namespaceToken
)) {
4599 const XsdIdentityConstraint::Ptr constraint
= parseUnique();
4600 element
->addIdentityConstraint(constraint
);
4601 } else if (isSchemaTag(XsdSchemaToken::Key
, token
, namespaceToken
)) {
4602 const XsdIdentityConstraint::Ptr constraint
= parseKey();
4603 element
->addIdentityConstraint(constraint
);
4604 } else if (isSchemaTag(XsdSchemaToken::Keyref
, token
, namespaceToken
)) {
4605 const XsdIdentityConstraint::Ptr constraint
= parseKeyRef(element
);
4606 element
->addIdentityConstraint(constraint
);
4613 tagValidator
.finalize();
4615 if (!hasTypeSpecified
) {
4616 if (hasSubstitutionGroup
)
4617 m_schemaResolver
->addSubstitutionGroupType(element
);
4619 element
->setType(BuiltinTypes::xsAnyType
);
4622 if (!alternatives
.isEmpty()) {
4623 element
->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
4625 for (int i
= 0; i
< alternatives
.count(); ++i
) {
4626 if (alternatives
.at(i
)->test())
4627 element
->typeTable()->addAlternative(alternatives
.at(i
));
4629 if (i
== (alternatives
.count() - 1)) { // the final one
4630 if (!alternatives
.at(i
)->test()) {
4631 element
->typeTable()->setDefaultTypeDefinition(alternatives
.at(i
));
4633 const XsdAlternative::Ptr
alternative(new XsdAlternative());
4634 if (element
->type())
4635 alternative
->setType(element
->type());
4637 m_schemaResolver
->addAlternativeType(alternative
, element
); // add to resolver
4639 element
->typeTable()->setDefaultTypeDefinition(alternative
);
4648 XsdTerm::Ptr
XsdSchemaParser::parseLocalElement(const XsdParticle::Ptr
&particle
, const NamedSchemaComponent::Ptr
&parent
)
4650 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Element
, this);
4652 validateElement(XsdTagScope::LocalElement
);
4654 bool hasRefAttribute
= false;
4655 bool hasTypeAttribute
= false;
4656 bool hasTypeSpecified
= false;
4659 XsdElement::Ptr element
;
4660 if (hasAttribute(QString::fromLatin1("ref"))) {
4661 term
= XsdReference::Ptr(new XsdReference());
4662 hasRefAttribute
= true;
4664 term
= XsdElement::Ptr(new XsdElement());
4668 if (hasRefAttribute
) {
4669 if (hasAttribute(QString::fromLatin1("name"))) {
4670 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4671 .arg(formatElement("element"))
4672 .arg(formatAttribute("ref"))
4673 .arg(formatAttribute("name")));
4675 } else if (hasAttribute(QString::fromLatin1("block"))) {
4676 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4677 .arg(formatElement("element"))
4678 .arg(formatAttribute("ref"))
4679 .arg(formatAttribute("block")));
4681 } else if (hasAttribute(QString::fromLatin1("nillable"))) {
4682 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4683 .arg(formatElement("element"))
4684 .arg(formatAttribute("ref"))
4685 .arg(formatAttribute("nillable")));
4687 } else if (hasAttribute(QString::fromLatin1("default"))) {
4688 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4689 .arg(formatElement("element"))
4690 .arg(formatAttribute("ref"))
4691 .arg(formatAttribute("default")));
4693 } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4694 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4695 .arg(formatElement("element"))
4696 .arg(formatAttribute("ref"))
4697 .arg(formatAttribute("fixed")));
4699 } else if (hasAttribute(QString::fromLatin1("form"))) {
4700 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4701 .arg(formatElement("element"))
4702 .arg(formatAttribute("ref"))
4703 .arg(formatAttribute("form")));
4705 } else if (hasAttribute(QString::fromLatin1("type"))) {
4706 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4707 .arg(formatElement("element"))
4708 .arg(formatAttribute("ref"))
4709 .arg(formatAttribute("type")));
4715 if (!parseMinMaxConstraint(particle
, "element")) {
4719 if (!hasAttribute(QString::fromLatin1("name")) && !hasAttribute(QString::fromLatin1("ref"))) {
4720 error(QtXmlPatterns::tr("%1 element must have either %2 or %3 attribute.")
4721 .arg(formatElement("element"))
4722 .arg(formatAttribute("name"))
4723 .arg(formatAttribute("ref")));
4727 if (hasRefAttribute
) {
4728 const QString ref
= readQNameAttribute(QString::fromLatin1("ref"), "element");
4729 QXmlName referenceName
;
4730 convertName(ref
, NamespaceSupport::ElementName
, referenceName
); // translate qualified name into QXmlName
4732 const XsdReference::Ptr reference
= term
;
4733 reference
->setReferenceName(referenceName
);
4734 reference
->setType(XsdReference::Element
);
4735 reference
->setSourceLocation(currentSourceLocation());
4737 element
->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope()));
4738 element
->scope()->setVariety(XsdElement::Scope::Local
);
4739 element
->scope()->setParent(parent
);
4741 if (hasAttribute(QString::fromLatin1("name"))) {
4742 const QString elementName
= readNameAttribute("element");
4744 QXmlName objectName
;
4745 if (hasAttribute(QString::fromLatin1("form"))) {
4746 const QString value
= readAttribute(QString::fromLatin1("form"));
4747 if (value
!= QString::fromLatin1("qualified") && value
!= QString::fromLatin1("unqualified")) {
4748 attributeContentError("form", "element", value
);
4752 if (value
== QString::fromLatin1("qualified")) {
4753 objectName
= m_namePool
->allocateQName(m_targetNamespace
, elementName
);
4755 objectName
= m_namePool
->allocateQName(QString(), elementName
);
4758 if (m_elementFormDefault
== QString::fromLatin1("qualified")) {
4759 objectName
= m_namePool
->allocateQName(m_targetNamespace
, elementName
);
4761 objectName
= m_namePool
->allocateQName(QString(), elementName
);
4765 element
->setName(objectName
);
4768 if (hasAttribute(QString::fromLatin1("nillable"))) {
4769 const QString nillable
= readAttribute(QString::fromLatin1("nillable"));
4771 const Boolean::Ptr value
= Boolean::fromLexical(nillable
);
4772 if (value
->hasError()) {
4773 attributeContentError("nillable", "element", nillable
, BuiltinTypes::xsBoolean
);
4777 element
->setIsNillable(value
->as
<Boolean
>()->value());
4779 element
->setIsNillable(false); // the default value
4782 if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
4783 error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together.")
4784 .arg(formatElement("element"))
4785 .arg(formatAttribute("default"))
4786 .arg(formatAttribute("fixed")));
4790 if (hasAttribute(QString::fromLatin1("default"))) {
4791 const QString value
= readAttribute(QString::fromLatin1("default"));
4792 element
->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
4793 element
->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default
);
4794 element
->valueConstraint()->setValue(value
);
4795 } else if (hasAttribute(QString::fromLatin1("fixed"))) {
4796 const QString value
= readAttribute(QString::fromLatin1("fixed"));
4797 element
->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
4798 element
->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed
);
4799 element
->valueConstraint()->setValue(value
);
4802 if (hasAttribute(QString::fromLatin1("type"))) {
4803 const QString type
= readQNameAttribute(QString::fromLatin1("type"), "element");
4805 convertName(type
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
4806 m_schemaResolver
->addElementType(element
, typeName
, currentSourceLocation()); // add to resolver
4808 hasTypeAttribute
= true;
4809 hasTypeSpecified
= true;
4812 element
->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint
| NamedSchemaComponent::RestrictionConstraint
| NamedSchemaComponent::SubstitutionConstraint
, "element"));
4815 validateIdAttribute("element");
4817 XsdAlternative::List alternatives
;
4819 TagValidationHandler
tagValidator(XsdTagScope::LocalElement
, this, m_namePool
);
4827 if (isStartElement()) {
4828 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
4829 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
4831 tagValidator
.validate(token
);
4833 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
4834 const XsdAnnotation::Ptr annotation
= parseAnnotation();
4835 element
->addAnnotation(annotation
);
4836 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
4837 if (hasRefAttribute
) {
4838 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4839 .arg(formatElement("element"))
4840 .arg(formatElement("simpleType"))
4841 .arg(formatAttribute("ref")));
4843 } else if (hasTypeAttribute
) {
4844 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4845 .arg(formatElement("element"))
4846 .arg(formatElement("simpleType"))
4847 .arg(formatAttribute("type")));
4851 const XsdSimpleType::Ptr type
= parseLocalSimpleType();
4852 type
->setContext(element
);
4853 element
->setType(type
);
4855 // add it to list of anonymous types as well
4856 addAnonymousType(type
);
4858 hasTypeSpecified
= true;
4859 } else if (isSchemaTag(XsdSchemaToken::ComplexType
, token
, namespaceToken
)) {
4860 if (hasRefAttribute
) {
4861 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4862 .arg(formatElement("element"))
4863 .arg(formatElement("complexType"))
4864 .arg(formatAttribute("ref")));
4866 } else if (hasTypeAttribute
) {
4867 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4868 .arg(formatElement("element"))
4869 .arg(formatElement("complexType"))
4870 .arg(formatAttribute("type")));
4874 const XsdComplexType::Ptr type
= parseLocalComplexType();
4875 type
->setContext(element
);
4876 element
->setType(type
);
4878 // add it to list of anonymous types as well
4879 addAnonymousType(type
);
4881 hasTypeSpecified
= true;
4882 } else if (isSchemaTag(XsdSchemaToken::Alternative
, token
, namespaceToken
)) {
4883 if (hasRefAttribute
) {
4884 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4885 .arg(formatElement("element"))
4886 .arg(formatElement("alternative"))
4887 .arg(formatAttribute("ref")));
4891 const XsdAlternative::Ptr alternative
= parseAlternative();
4892 alternatives
.append(alternative
);
4893 } else if (isSchemaTag(XsdSchemaToken::Unique
, token
, namespaceToken
)) {
4894 if (hasRefAttribute
) {
4895 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4896 .arg(formatElement("element"))
4897 .arg(formatElement("unique"))
4898 .arg(formatAttribute("ref")));
4902 const XsdIdentityConstraint::Ptr constraint
= parseUnique();
4903 element
->addIdentityConstraint(constraint
);
4904 } else if (isSchemaTag(XsdSchemaToken::Key
, token
, namespaceToken
)) {
4905 if (hasRefAttribute
) {
4906 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4907 .arg(formatElement("element"))
4908 .arg(formatElement("key"))
4909 .arg(formatAttribute("ref")));
4913 const XsdIdentityConstraint::Ptr constraint
= parseKey();
4914 element
->addIdentityConstraint(constraint
);
4915 } else if (isSchemaTag(XsdSchemaToken::Keyref
, token
, namespaceToken
)) {
4916 if (hasRefAttribute
) {
4917 error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute.")
4918 .arg(formatElement("element"))
4919 .arg(formatElement("keyref"))
4920 .arg(formatAttribute("ref")));
4924 const XsdIdentityConstraint::Ptr constraint
= parseKeyRef(element
);
4925 element
->addIdentityConstraint(constraint
);
4932 tagValidator
.finalize();
4934 if (!hasTypeSpecified
&& !hasRefAttribute
)
4935 element
->setType(BuiltinTypes::xsAnyType
);
4937 if (!hasRefAttribute
&& !alternatives
.isEmpty()) {
4938 element
->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
4940 for (int i
= 0; i
< alternatives
.count(); ++i
) {
4941 if (alternatives
.at(i
)->test())
4942 element
->typeTable()->addAlternative(alternatives
.at(i
));
4944 if (i
== (alternatives
.count() - 1)) { // the final one
4945 if (!alternatives
.at(i
)->test()) {
4946 element
->typeTable()->setDefaultTypeDefinition(alternatives
.at(i
));
4948 const XsdAlternative::Ptr
alternative(new XsdAlternative());
4949 if (element
->type())
4950 alternative
->setType(element
->type());
4952 m_schemaResolver
->addAlternativeType(alternative
, element
); // add to resolver
4954 element
->typeTable()->setDefaultTypeDefinition(alternative
);
4963 XsdIdentityConstraint::Ptr
XsdSchemaParser::parseUnique()
4965 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Unique
, this);
4967 validateElement(XsdTagScope::Unique
);
4969 const XsdIdentityConstraint::Ptr
constraint(new XsdIdentityConstraint());
4970 constraint
->setCategory(XsdIdentityConstraint::Unique
);
4973 const QXmlName objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("unique"));
4974 constraint
->setName(objectName
);
4976 validateIdAttribute("unique");
4978 TagValidationHandler
tagValidator(XsdTagScope::Unique
, this, m_namePool
);
4986 if (isStartElement()) {
4987 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
4988 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
4990 tagValidator
.validate(token
);
4992 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
4993 const XsdAnnotation::Ptr annotation
= parseAnnotation();
4994 constraint
->addAnnotation(annotation
);
4995 } else if (isSchemaTag(XsdSchemaToken::Selector
, token
, namespaceToken
)) {
4996 parseSelector(constraint
);
4997 } else if (isSchemaTag(XsdSchemaToken::Field
, token
, namespaceToken
)) {
4998 parseField(constraint
);
5005 // add constraint to schema for further checking
5006 addIdentityConstraint(constraint
);
5008 tagValidator
.finalize();
5013 XsdIdentityConstraint::Ptr
XsdSchemaParser::parseKey()
5015 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Key
, this);
5017 validateElement(XsdTagScope::Key
);
5019 const XsdIdentityConstraint::Ptr
constraint(new XsdIdentityConstraint());
5020 constraint
->setCategory(XsdIdentityConstraint::Key
);
5023 const QXmlName objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("key"));
5024 constraint
->setName(objectName
);
5026 validateIdAttribute("key");
5028 TagValidationHandler
tagValidator(XsdTagScope::Key
, this, m_namePool
);
5036 if (isStartElement()) {
5037 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
5038 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
5040 tagValidator
.validate(token
);
5042 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
5043 const XsdAnnotation::Ptr annotation
= parseAnnotation();
5044 constraint
->addAnnotation(annotation
);
5045 } else if (isSchemaTag(XsdSchemaToken::Selector
, token
, namespaceToken
)) {
5046 parseSelector(constraint
);
5047 } else if (isSchemaTag(XsdSchemaToken::Field
, token
, namespaceToken
)) {
5048 parseField(constraint
);
5055 // add constraint to schema for further checking
5056 addIdentityConstraint(constraint
);
5058 tagValidator
.finalize();
5063 XsdIdentityConstraint::Ptr
XsdSchemaParser::parseKeyRef(const XsdElement::Ptr
&element
)
5065 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Keyref
, this);
5067 validateElement(XsdTagScope::KeyRef
);
5069 const XsdIdentityConstraint::Ptr
constraint(new XsdIdentityConstraint());
5070 constraint
->setCategory(XsdIdentityConstraint::KeyReference
);
5073 const QXmlName objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("keyref"));
5074 constraint
->setName(objectName
);
5076 const QString refer
= readQNameAttribute(QString::fromLatin1("refer"), "keyref");
5077 QXmlName referenceName
;
5078 convertName(refer
, NamespaceSupport::ElementName
, referenceName
); // translate qualified name into QXmlName
5079 m_schemaResolver
->addKeyReference(element
, constraint
, referenceName
, currentSourceLocation()); // add to resolver
5081 validateIdAttribute("keyref");
5083 TagValidationHandler
tagValidator(XsdTagScope::KeyRef
, this, m_namePool
);
5091 if (isStartElement()) {
5092 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
5093 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
5095 tagValidator
.validate(token
);
5097 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
5098 const XsdAnnotation::Ptr annotation
= parseAnnotation();
5099 constraint
->addAnnotation(annotation
);
5100 } else if (isSchemaTag(XsdSchemaToken::Selector
, token
, namespaceToken
)) {
5101 parseSelector(constraint
);
5102 } else if (isSchemaTag(XsdSchemaToken::Field
, token
, namespaceToken
)) {
5103 parseField(constraint
);
5110 // add constraint to schema for further checking
5111 addIdentityConstraint(constraint
);
5113 tagValidator
.finalize();
5118 void XsdSchemaParser::parseSelector(const XsdIdentityConstraint::Ptr
&ptr
)
5120 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Selector
, this);
5122 validateElement(XsdTagScope::Selector
);
5125 const XsdXPathExpression::Ptr expression
= readXPathExpression("selector");
5127 const QString xpath
= readXPathAttribute(QString::fromLatin1("xpath"), XPathSelector
, "selector");
5128 expression
->setExpression(xpath
);
5130 ptr
->setSelector(expression
);
5132 validateIdAttribute("selector");
5134 TagValidationHandler
tagValidator(XsdTagScope::Selector
, this, m_namePool
);
5142 if (isStartElement()) {
5143 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
5144 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
5146 tagValidator
.validate(token
);
5148 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
5149 const XsdAnnotation::Ptr annotation
= parseAnnotation();
5150 expression
->addAnnotation(annotation
);
5157 tagValidator
.finalize();
5160 void XsdSchemaParser::parseField(const XsdIdentityConstraint::Ptr
&ptr
)
5162 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Field
, this);
5164 validateElement(XsdTagScope::Field
);
5167 const XsdXPathExpression::Ptr expression
= readXPathExpression("field");
5169 const QString xpath
= readXPathAttribute(QString::fromLatin1("xpath"), XPathField
, "field");
5170 expression
->setExpression(xpath
);
5172 ptr
->addField(expression
);
5174 validateIdAttribute("field");
5176 TagValidationHandler
tagValidator(XsdTagScope::Field
, this, m_namePool
);
5184 if (isStartElement()) {
5185 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
5186 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
5188 tagValidator
.validate(token
);
5190 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
5191 const XsdAnnotation::Ptr annotation
= parseAnnotation();
5192 expression
->addAnnotation(annotation
);
5199 tagValidator
.finalize();
5202 XsdAlternative::Ptr
XsdSchemaParser::parseAlternative()
5204 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Alternative
, this);
5206 validateElement(XsdTagScope::Alternative
);
5208 const XsdAlternative::Ptr
alternative(new XsdAlternative());
5210 bool hasTypeSpecified
= false;
5212 if (hasAttribute(QString::fromLatin1("test"))) {
5213 const XsdXPathExpression::Ptr expression
= readXPathExpression("alternative");
5215 const QString test
= readXPathAttribute(QString::fromLatin1("test"), XPath20
, "alternative");
5216 expression
->setExpression(test
);
5218 alternative
->setTest(expression
);
5221 if (hasAttribute(QString::fromLatin1("type"))) {
5222 const QString type
= readQNameAttribute(QString::fromLatin1("type"), "alternative");
5224 convertName(type
, NamespaceSupport::ElementName
, typeName
); // translate qualified name into QXmlName
5225 m_schemaResolver
->addAlternativeType(alternative
, typeName
, currentSourceLocation()); // add to resolver
5227 hasTypeSpecified
= true;
5230 validateIdAttribute("alternative");
5232 TagValidationHandler
tagValidator(XsdTagScope::Alternative
, this, m_namePool
);
5240 if (isStartElement()) {
5241 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
5242 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
5244 tagValidator
.validate(token
);
5246 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
5247 const XsdAnnotation::Ptr annotation
= parseAnnotation();
5248 alternative
->addAnnotation(annotation
);
5249 } else if (isSchemaTag(XsdSchemaToken::SimpleType
, token
, namespaceToken
)) {
5250 const XsdSimpleType::Ptr type
= parseLocalSimpleType();
5251 alternative
->setType(type
);
5253 // add it to list of anonymous types as well
5254 addAnonymousType(type
);
5256 hasTypeSpecified
= true;
5257 } else if (isSchemaTag(XsdSchemaToken::ComplexType
, token
, namespaceToken
)) {
5258 const XsdComplexType::Ptr type
= parseLocalComplexType();
5259 alternative
->setType(type
);
5261 // add it to list of anonymous types as well
5262 addAnonymousType(type
);
5264 hasTypeSpecified
= true;
5271 tagValidator
.finalize();
5273 if (!hasTypeSpecified
) {
5274 error(QtXmlPatterns::tr("%1 element must have either %2 attribute or %3 or %4 as child element.")
5275 .arg(formatElement("alternative"))
5276 .arg(formatAttribute("type"))
5277 .arg(formatElement("simpleType"))
5278 .arg(formatElement("complexType")));
5285 XsdNotation::Ptr
XsdSchemaParser::parseNotation()
5287 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Notation
, this);
5289 validateElement(XsdTagScope::Notation
);
5291 const XsdNotation::Ptr
notation(new XsdNotation());
5294 const QXmlName objectName
= m_namePool
->allocateQName(m_targetNamespace
, readNameAttribute("notation"));
5295 notation
->setName(objectName
);
5297 bool hasOptionalAttribute
= false;
5299 if (hasAttribute(QString::fromLatin1("public"))) {
5300 const QString value
= readAttribute(QString::fromLatin1("public"));
5301 if (!value
.isEmpty()) {
5302 const DerivedString
<TypeToken
>::Ptr publicId
= DerivedString
<TypeToken
>::fromLexical(m_namePool
, value
);
5303 if (publicId
->hasError()) {
5304 attributeContentError("public", "notation", value
, BuiltinTypes::xsToken
);
5307 notation
->setPublicId(publicId
);
5310 hasOptionalAttribute
= true;
5313 if (hasAttribute(QString::fromLatin1("system"))) {
5314 const QString value
= readAttribute(QString::fromLatin1("system"));
5315 if (!isValidUri(value
)) {
5316 attributeContentError("system", "notation", value
, BuiltinTypes::xsAnyURI
);
5320 if (!value
.isEmpty()) {
5321 const AnyURI::Ptr systemId
= AnyURI::fromLexical(value
);
5322 notation
->setSystemId(systemId
);
5325 hasOptionalAttribute
= true;
5328 if (!hasOptionalAttribute
) {
5329 error(QtXmlPatterns::tr("%1 element requires either %2 or %3 attribute.")
5330 .arg(formatElement("notation"))
5331 .arg(formatAttribute("public"))
5332 .arg(formatAttribute("system")));
5336 validateIdAttribute("notation");
5338 TagValidationHandler
tagValidator(XsdTagScope::Notation
, this, m_namePool
);
5346 if (isCharacters() || isEntityReference()) {
5347 if (!text().toString().trimmed().isEmpty()) {
5348 error(QtXmlPatterns::tr("Text or entity references not allowed inside %1 element").arg(formatElement("notation.")));
5353 if (isStartElement()) {
5354 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
5355 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
5357 tagValidator
.validate(token
);
5359 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
5360 const XsdAnnotation::Ptr annotation
= parseAnnotation();
5361 notation
->addAnnotation(annotation
);
5368 tagValidator
.finalize();
5373 XsdWildcard::Ptr
XsdSchemaParser::parseAny(const XsdParticle::Ptr
&particle
)
5375 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::Any
, this);
5377 validateElement(XsdTagScope::Any
);
5379 const XsdWildcard::Ptr
wildcard(new XsdWildcard());
5382 if (!parseMinMaxConstraint(particle
, "any")) {
5386 if (hasAttribute(QString::fromLatin1("namespace"))) {
5387 const QSet
<QString
> values
= readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), QString::SkipEmptyParts
).toSet();
5388 if ((values
.contains(QString::fromLatin1("##any")) || values
.contains(QString::fromLatin1("##other"))) && values
.count() != 1) {
5389 error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs.")
5390 .arg(formatAttribute("namespace"))
5391 .arg(formatElement("any"))
5392 .arg(formatData("##any"))
5393 .arg(formatData("##other")));
5397 if (values
.contains(QString::fromLatin1("##any"))) {
5398 wildcard
->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any
);
5399 } else if (values
.contains(QString::fromLatin1("##other"))) {
5400 wildcard
->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not
);
5401 if (!m_targetNamespace
.isEmpty())
5402 wildcard
->namespaceConstraint()->setNamespaces(QSet
<QString
>() << m_targetNamespace
);
5404 wildcard
->namespaceConstraint()->setNamespaces(QSet
<QString
>() << XsdWildcard::absentNamespace());
5406 wildcard
->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration
);
5407 QStringList newValues
= values
.toList();
5409 // replace the ##targetNamespace entry
5410 for (int i
= 0; i
< newValues
.count(); ++i
) {
5411 if (newValues
.at(i
) == QString::fromLatin1("##targetNamespace")) {
5412 if (!m_targetNamespace
.isEmpty())
5413 newValues
[i
] = m_targetNamespace
;
5415 newValues
[i
] = XsdWildcard::absentNamespace();
5416 } else if (newValues
.at(i
) == QString::fromLatin1("##local")) {
5417 newValues
[i
] = XsdWildcard::absentNamespace();
5421 // check for invalid URIs
5422 for (int i
= 0; i
< newValues
.count(); ++i
) {
5423 const QString stringValue
= newValues
.at(i
);
5424 if (stringValue
== XsdWildcard::absentNamespace())
5427 if (!isValidUri(stringValue
)) {
5428 attributeContentError("namespace", "any", stringValue
, BuiltinTypes::xsAnyURI
);
5433 wildcard
->namespaceConstraint()->setNamespaces(newValues
.toSet());
5436 wildcard
->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any
);
5439 if (hasAttribute(QString::fromLatin1("processContents"))) {
5440 const QString value
= readAttribute(QString::fromLatin1("processContents"));
5441 if (value
!= QString::fromLatin1("lax") &&
5442 value
!= QString::fromLatin1("skip") &&
5443 value
!= QString::fromLatin1("strict")) {
5444 attributeContentError("processContents", "any", value
);
5448 if (value
== QString::fromLatin1("lax")) {
5449 wildcard
->setProcessContents(XsdWildcard::Lax
);
5450 } else if (value
== QString::fromLatin1("skip")) {
5451 wildcard
->setProcessContents(XsdWildcard::Skip
);
5452 } else if (value
== QString::fromLatin1("strict")) {
5453 wildcard
->setProcessContents(XsdWildcard::Strict
);
5456 wildcard
->setProcessContents(XsdWildcard::Strict
);
5459 validateIdAttribute("any");
5461 TagValidationHandler
tagValidator(XsdTagScope::Any
, this, m_namePool
);
5469 if (isStartElement()) {
5470 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
5471 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
5473 tagValidator
.validate(token
);
5475 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
5476 const XsdAnnotation::Ptr annotation
= parseAnnotation();
5477 wildcard
->addAnnotation(annotation
);
5484 tagValidator
.finalize();
5489 XsdWildcard::Ptr
XsdSchemaParser::parseAnyAttribute()
5491 const ElementNamespaceHandler
namespaceHandler(XsdSchemaToken::AnyAttribute
, this);
5493 validateElement(XsdTagScope::AnyAttribute
);
5495 const XsdWildcard::Ptr
wildcard(new XsdWildcard());
5498 if (hasAttribute(QString::fromLatin1("namespace"))) {
5499 const QSet
<QString
> values
= readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), QString::SkipEmptyParts
).toSet();
5500 if ((values
.contains(QString::fromLatin1("##any")) || values
.contains(QString::fromLatin1("##other"))) && values
.count() != 1) {
5501 error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs.")
5502 .arg(formatAttribute("namespace"))
5503 .arg(formatElement("anyAttribute"))
5504 .arg(formatData("##any"))
5505 .arg(formatData("##other")));
5509 if (values
.contains(QString::fromLatin1("##any"))) {
5510 wildcard
->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any
);
5511 } else if (values
.contains(QString::fromLatin1("##other"))) {
5512 wildcard
->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not
);
5513 if (!m_targetNamespace
.isEmpty())
5514 wildcard
->namespaceConstraint()->setNamespaces(QSet
<QString
>() << m_targetNamespace
);
5516 wildcard
->namespaceConstraint()->setNamespaces(QSet
<QString
>() << XsdWildcard::absentNamespace());
5518 wildcard
->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration
);
5519 QStringList newValues
= values
.toList();
5521 // replace the ##targetNamespace entry
5522 for (int i
= 0; i
< newValues
.count(); ++i
) {
5523 if (newValues
.at(i
) == QString::fromLatin1("##targetNamespace")) {
5524 if (!m_targetNamespace
.isEmpty())
5525 newValues
[i
] = m_targetNamespace
;
5527 newValues
[i
] = XsdWildcard::absentNamespace();
5528 } else if (newValues
.at(i
) == QString::fromLatin1("##local")) {
5529 newValues
[i
] = XsdWildcard::absentNamespace();
5533 // check for invalid URIs
5534 for (int i
= 0; i
< newValues
.count(); ++i
) {
5535 const QString stringValue
= newValues
.at(i
);
5536 if (stringValue
== XsdWildcard::absentNamespace())
5539 if (!isValidUri(stringValue
)) {
5540 attributeContentError("namespace", "anyAttribute", stringValue
, BuiltinTypes::xsAnyURI
);
5545 wildcard
->namespaceConstraint()->setNamespaces(newValues
.toSet());
5548 wildcard
->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any
);
5551 if (hasAttribute(QString::fromLatin1("processContents"))) {
5552 const QString value
= readAttribute(QString::fromLatin1("processContents"));
5553 if (value
!= QString::fromLatin1("lax") &&
5554 value
!= QString::fromLatin1("skip") &&
5555 value
!= QString::fromLatin1("strict")) {
5556 attributeContentError("processContents", "anyAttribute", value
);
5560 if (value
== QString::fromLatin1("lax")) {
5561 wildcard
->setProcessContents(XsdWildcard::Lax
);
5562 } else if (value
== QString::fromLatin1("skip")) {
5563 wildcard
->setProcessContents(XsdWildcard::Skip
);
5564 } else if (value
== QString::fromLatin1("strict")) {
5565 wildcard
->setProcessContents(XsdWildcard::Strict
);
5568 wildcard
->setProcessContents(XsdWildcard::Strict
);
5571 validateIdAttribute("anyAttribute");
5573 TagValidationHandler
tagValidator(XsdTagScope::AnyAttribute
, this, m_namePool
);
5581 if (isStartElement()) {
5582 const XsdSchemaToken::NodeName token
= XsdSchemaToken::toToken(name());
5583 const XsdSchemaToken::NodeName namespaceToken
= XsdSchemaToken::toToken(namespaceUri());
5585 tagValidator
.validate(token
);
5587 if (isSchemaTag(XsdSchemaToken::Annotation
, token
, namespaceToken
)) {
5588 const XsdAnnotation::Ptr annotation
= parseAnnotation();
5589 wildcard
->addAnnotation(annotation
);
5596 tagValidator
.finalize();
5602 void XsdSchemaParser::parseUnknownDocumentation()
5604 Q_ASSERT(isStartElement());
5605 m_namespaceSupport
.pushContext();
5606 m_namespaceSupport
.setPrefixes(namespaceDeclarations());
5614 if (isStartElement())
5615 parseUnknownDocumentation();
5618 m_namespaceSupport
.popContext();
5621 void XsdSchemaParser::parseUnknown()
5623 Q_ASSERT(isStartElement());
5624 m_namespaceSupport
.pushContext();
5625 m_namespaceSupport
.setPrefixes(namespaceDeclarations());
5627 error(QtXmlPatterns::tr("%1 element is not allowed in this context.").arg(formatElement(name().toString())));
5635 if (isStartElement())
5639 m_namespaceSupport
.popContext();
5642 bool XsdSchemaParser::parseMinMaxConstraint(const XsdParticle::Ptr
&particle
, const char *elementName
)
5644 if (hasAttribute(QString::fromLatin1("minOccurs"))) {
5645 const QString value
= readAttribute(QString::fromLatin1("minOccurs"));
5647 DerivedInteger
<TypeNonNegativeInteger
>::Ptr integer
= DerivedInteger
<TypeNonNegativeInteger
>::fromLexical(m_namePool
, value
);
5648 if (integer
->hasError()) {
5649 attributeContentError("minOccurs", elementName
, value
, BuiltinTypes::xsNonNegativeInteger
);
5652 particle
->setMinimumOccurs(integer
->as
< DerivedInteger
<TypeNonNegativeInteger
> >()->storedValue());
5655 particle
->setMinimumOccurs(1);
5658 if (hasAttribute(QString::fromLatin1("maxOccurs"))) {
5659 const QString value
= readAttribute(QString::fromLatin1("maxOccurs"));
5661 if (value
== QString::fromLatin1("unbounded")) {
5662 particle
->setMaximumOccursUnbounded(true);
5664 particle
->setMaximumOccursUnbounded(false);
5665 DerivedInteger
<TypeNonNegativeInteger
>::Ptr integer
= DerivedInteger
<TypeNonNegativeInteger
>::fromLexical(m_namePool
, value
);
5666 if (integer
->hasError()) {
5667 attributeContentError("maxOccurs", elementName
, value
, BuiltinTypes::xsNonNegativeInteger
);
5670 particle
->setMaximumOccurs(integer
->as
< DerivedInteger
<TypeNonNegativeInteger
> >()->storedValue());
5674 particle
->setMaximumOccursUnbounded(false);
5675 particle
->setMaximumOccurs(1);
5678 if (!particle
->maximumOccursUnbounded()) {
5679 if (particle
->maximumOccurs() < particle
->minimumOccurs()) {
5680 error(QtXmlPatterns::tr("%1 attribute of %2 element has larger value than %3 attribute.")
5681 .arg(formatAttribute("minOccurs"))
5682 .arg(formatElement(elementName
))
5683 .arg(formatAttribute("maxOccurs")));
5691 QSourceLocation
XsdSchemaParser::currentSourceLocation() const
5693 QSourceLocation location
;
5694 location
.setLine(lineNumber());
5695 location
.setColumn(columnNumber());
5696 location
.setUri(m_documentURI
);
5701 void XsdSchemaParser::convertName(const QString
&qualifiedName
, NamespaceSupport::NameType type
, QXmlName
&name
)
5703 bool result
= m_namespaceSupport
.processName(qualifiedName
, type
, name
);
5705 error(QtXmlPatterns::tr("Prefix of qualified name %1 is not defined.").arg(formatKeyword(qualifiedName
)));
5709 QString
XsdSchemaParser::readNameAttribute(const char *elementName
)
5711 const QString value
= readAttribute(QString::fromLatin1("name")).simplified();
5712 if (!QXmlUtils::isNCName(value
)) {
5713 attributeContentError("name", elementName
, value
, BuiltinTypes::xsNCName
);
5720 QString
XsdSchemaParser::readQNameAttribute(const QString
&typeAttribute
, const char *elementName
)
5722 const QString value
= readAttribute(typeAttribute
).simplified();
5723 if (!XPathHelper::isQName(value
)) {
5724 attributeContentError(typeAttribute
.toLatin1(), elementName
, value
, BuiltinTypes::xsQName
);
5731 QString
XsdSchemaParser::readNamespaceAttribute(const QString
&attributeName
, const char *elementName
)
5733 const QString value
= readAttribute(attributeName
);
5734 if (value
.isEmpty()) {
5735 attributeContentError(attributeName
.toLatin1(), elementName
, value
, BuiltinTypes::xsAnyURI
);
5742 SchemaType::DerivationConstraints
XsdSchemaParser::readDerivationConstraintAttribute(const SchemaType::DerivationConstraints
&allowedConstraints
, const char *elementName
)
5744 // first convert the flags into strings for easier comparision
5745 QSet
<QString
> allowedContent
;
5746 if (allowedConstraints
& SchemaType::RestrictionConstraint
)
5747 allowedContent
.insert(QString::fromLatin1("restriction"));
5748 if (allowedConstraints
& SchemaType::ExtensionConstraint
)
5749 allowedContent
.insert(QString::fromLatin1("extension"));
5750 if (allowedConstraints
& SchemaType::ListConstraint
)
5751 allowedContent
.insert(QString::fromLatin1("list"));
5752 if (allowedConstraints
& SchemaType::UnionConstraint
)
5753 allowedContent
.insert(QString::fromLatin1("union"));
5755 // read content from the attribute if available, otherwise use the default definitions from the schema tag
5757 if (hasAttribute(QString::fromLatin1("final"))) {
5758 content
= readAttribute(QString::fromLatin1("final"));
5760 // split string into list to validate the content of the attribute
5761 const QStringList values
= content
.split(QLatin1Char(' '), QString::SkipEmptyParts
);
5762 for (int i
= 0; i
< values
.count(); i
++) {
5763 const QString value
= values
.at(i
);
5764 if (!allowedContent
.contains(value
) && (value
!= QString::fromLatin1("#all"))) {
5765 attributeContentError("final", elementName
, value
);
5766 return SchemaType::DerivationConstraints();
5769 if ((value
== QString::fromLatin1("#all")) && values
.count() != 1) {
5770 error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values.")
5771 .arg(formatAttribute("final"))
5772 .arg(formatElement(elementName
))
5773 .arg(formatData("#all")));
5774 return SchemaType::DerivationConstraints();
5778 // content of the default value has been validated in parseSchema already
5779 content
= m_finalDefault
;
5782 QSet
<QString
> contentSet
= content
.split(QLatin1Char(' '), QString::SkipEmptyParts
).toSet();
5784 // if the '#all' tag is defined, we return all allowed values
5785 if (contentSet
.contains(QString::fromLatin1("#all"))) {
5786 return allowedConstraints
;
5787 } else { // return the values from content set that intersects with the allowed values
5788 contentSet
.intersect(allowedContent
);
5790 SchemaType::DerivationConstraints constraints
;
5792 if (contentSet
.contains(QString::fromLatin1("restriction")))
5793 constraints
|= SchemaType::RestrictionConstraint
;
5794 if (contentSet
.contains(QString::fromLatin1("extension")))
5795 constraints
|= SchemaType::ExtensionConstraint
;
5796 if (contentSet
.contains(QString::fromLatin1("list")))
5797 constraints
|= SchemaType::ListConstraint
;
5798 if (contentSet
.contains(QString::fromLatin1("union")))
5799 constraints
|= SchemaType::UnionConstraint
;
5805 NamedSchemaComponent::BlockingConstraints
XsdSchemaParser::readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints
&allowedConstraints
, const char *elementName
)
5807 // first convert the flags into strings for easier comparision
5808 QSet
<QString
> allowedContent
;
5809 if (allowedConstraints
& NamedSchemaComponent::RestrictionConstraint
)
5810 allowedContent
.insert(QString::fromLatin1("restriction"));
5811 if (allowedConstraints
& NamedSchemaComponent::ExtensionConstraint
)
5812 allowedContent
.insert(QString::fromLatin1("extension"));
5813 if (allowedConstraints
& NamedSchemaComponent::SubstitutionConstraint
)
5814 allowedContent
.insert(QString::fromLatin1("substitution"));
5816 // read content from the attribute if available, otherwise use the default definitions from the schema tag
5818 if (hasAttribute(QString::fromLatin1("block"))) {
5819 content
= readAttribute(QString::fromLatin1("block"));
5821 // split string into list to validate the content of the attribute
5822 const QStringList values
= content
.split(QLatin1Char(' '), QString::SkipEmptyParts
);
5823 for (int i
= 0; i
< values
.count(); i
++) {
5824 const QString value
= values
.at(i
);
5825 if (!allowedContent
.contains(value
) && (value
!= QString::fromLatin1("#all"))) {
5826 attributeContentError("block", elementName
, value
);
5827 return NamedSchemaComponent::BlockingConstraints();
5830 if ((value
== QString::fromLatin1("#all")) && values
.count() != 1) {
5831 error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values.")
5832 .arg(formatAttribute("block"))
5833 .arg(formatElement(elementName
))
5834 .arg(formatData("#all")));
5835 return NamedSchemaComponent::BlockingConstraints();
5839 // content of the default value has been validated in parseSchema already
5840 content
= m_blockDefault
;
5843 QSet
<QString
> contentSet
= content
.split(QLatin1Char(' '), QString::SkipEmptyParts
).toSet();
5845 // if the '#all' tag is defined, we return all allowed values
5846 if (contentSet
.contains(QString::fromLatin1("#all"))) {
5847 return allowedConstraints
;
5848 } else { // return the values from content set that intersects with the allowed values
5849 contentSet
.intersect(allowedContent
);
5851 NamedSchemaComponent::BlockingConstraints constraints
;
5853 if (contentSet
.contains(QString::fromLatin1("restriction")))
5854 constraints
|= NamedSchemaComponent::RestrictionConstraint
;
5855 if (contentSet
.contains(QString::fromLatin1("extension")))
5856 constraints
|= NamedSchemaComponent::ExtensionConstraint
;
5857 if (contentSet
.contains(QString::fromLatin1("substitution")))
5858 constraints
|= NamedSchemaComponent::SubstitutionConstraint
;
5864 XsdXPathExpression::Ptr
XsdSchemaParser::readXPathExpression(const char *elementName
)
5866 const XsdXPathExpression::Ptr
expression(new XsdXPathExpression());
5868 const QList
<QXmlName
> namespaceBindings
= m_namespaceSupport
.namespaceBindings();
5870 for (int i
= 0; i
< namespaceBindings
.count(); ++i
) {
5871 if (namespaceBindings
.at(i
).prefix() == StandardPrefixes::empty
)
5872 emptyName
= namespaceBindings
.at(i
);
5875 expression
->setNamespaceBindings(namespaceBindings
);
5877 QString xpathDefaultNamespace
;
5878 if (hasAttribute(QString::fromLatin1("xpathDefaultNamespace"))) {
5879 xpathDefaultNamespace
= readAttribute(QString::fromLatin1("xpathDefaultNamespace"));
5880 if (xpathDefaultNamespace
!= QString::fromLatin1("##defaultNamespace") &&
5881 xpathDefaultNamespace
!= QString::fromLatin1("##targetNamespace") &&
5882 xpathDefaultNamespace
!= QString::fromLatin1("##local")) {
5883 if (!isValidUri(xpathDefaultNamespace
)) {
5884 attributeContentError("xpathDefaultNamespace", elementName
, xpathDefaultNamespace
, BuiltinTypes::xsAnyURI
);
5889 xpathDefaultNamespace
= m_xpathDefaultNamespace
;
5892 AnyURI::Ptr namespaceURI
;
5893 if (xpathDefaultNamespace
== QString::fromLatin1("##defaultNamespace")) {
5894 if (!emptyName
.isNull())
5895 namespaceURI
= AnyURI::fromLexical(m_namePool
->stringForNamespace(emptyName
.namespaceURI()));
5896 } else if (xpathDefaultNamespace
== QString::fromLatin1("##targetNamespace")) {
5897 if (!m_targetNamespace
.isEmpty())
5898 namespaceURI
= AnyURI::fromLexical(m_targetNamespace
);
5899 } else if (xpathDefaultNamespace
== QString::fromLatin1("##local")) {
5902 namespaceURI
= AnyURI::fromLexical(xpathDefaultNamespace
);
5905 if (namespaceURI
->hasError()) {
5906 attributeContentError("xpathDefaultNamespace", elementName
, xpathDefaultNamespace
, BuiltinTypes::xsAnyURI
);
5910 expression
->setDefaultNamespace(namespaceURI
);
5913 //TODO: read the base uri if qmaintaining reader support it
5918 QString
XsdSchemaParser::readXPathAttribute(const QString
&attributeName
, XPathType type
, const char *elementName
)
5920 const QString value
= readAttribute(attributeName
);
5921 if (value
.isEmpty() || value
.startsWith(QLatin1Char('/'))) {
5922 attributeContentError(attributeName
.toLatin1(), elementName
, value
);
5926 QXmlNamePool
namePool(m_namePool
.data());
5928 QXmlQuery::QueryLanguage language
= QXmlQuery::XPath20
;
5930 case XPath20
: language
= QXmlQuery::XPath20
; break;
5931 case XPathSelector
: language
= QXmlQuery::XmlSchema11IdentityConstraintSelector
; break;
5932 case XPathField
: language
= QXmlQuery::XmlSchema11IdentityConstraintField
; break;
5935 QXmlQuery
query(language
, namePool
);
5936 QXmlQueryPrivate
*queryPrivate
= query
.d
;
5938 const QList
<QXmlName
> namespaceBindings
= m_namespaceSupport
.namespaceBindings();
5939 for (int i
= 0; i
< namespaceBindings
.count(); ++i
) {
5940 if (!namespaceBindings
.at(i
).prefix() == StandardPrefixes::empty
)
5941 queryPrivate
->addAdditionalNamespaceBinding(namespaceBindings
.at(i
));
5944 query
.setQuery(value
, m_documentURI
);
5945 if (!query
.isValid()) {
5946 attributeContentError(attributeName
.toLatin1(), elementName
, value
);
5953 void XsdSchemaParser::validateIdAttribute(const char *elementName
)
5955 if (hasAttribute(QString::fromLatin1("id"))) {
5956 const QString value
= readAttribute(QString::fromLatin1("id"));
5957 DerivedString
<TypeID
>::Ptr id
= DerivedString
<TypeID
>::fromLexical(m_namePool
, value
);
5958 if (id
->hasError()) {
5959 attributeContentError("id", elementName
, value
, BuiltinTypes::xsID
);
5961 if (m_idCache
->hasId(value
)) {
5962 error(QtXmlPatterns::tr("Component with ID %1 has been defined previously.").arg(formatData(value
)));
5964 m_idCache
->addId(value
);
5970 bool XsdSchemaParser::isSchemaTag(XsdSchemaToken::NodeName tag
, XsdSchemaToken::NodeName token
, XsdSchemaToken::NodeName namespaceToken
) const
5972 return ((tag
== token
) && (namespaceToken
== XsdSchemaToken::XML_NS_SCHEMA_URI
));
5975 void XsdSchemaParser::addElement(const XsdElement::Ptr
&element
)
5977 const QXmlName objectName
= element
->name(m_namePool
);
5978 if (m_schema
->element(objectName
)) {
5979 error(QtXmlPatterns::tr("Element %1 already defined.").arg(formatElement(m_namePool
->displayName(objectName
))));
5981 m_schema
->addElement(element
);
5982 m_componentLocationHash
.insert(element
, currentSourceLocation());
5986 void XsdSchemaParser::addAttribute(const XsdAttribute::Ptr
&attribute
)
5988 const QXmlName objectName
= attribute
->name(m_namePool
);
5989 if (m_schema
->attribute(objectName
)) {
5990 error(QtXmlPatterns::tr("Attribute %1 already defined.").arg(formatAttribute(m_namePool
->displayName(objectName
))));
5992 m_schema
->addAttribute(attribute
);
5993 m_componentLocationHash
.insert(attribute
, currentSourceLocation());
5997 void XsdSchemaParser::addType(const SchemaType::Ptr
&type
)
5999 // we don't import redefinitions of builtin types, that just causes problems
6000 if (m_builtinTypeNames
.contains(type
->name(m_namePool
)))
6003 const QXmlName objectName
= type
->name(m_namePool
);
6004 if (m_schema
->type(objectName
)) {
6005 error(QtXmlPatterns::tr("Type %1 already defined.").arg(formatType(m_namePool
, objectName
)));
6007 m_schema
->addType(type
);
6008 if (type
->isSimpleType())
6009 m_componentLocationHash
.insert(XsdSimpleType::Ptr(type
), currentSourceLocation());
6011 m_componentLocationHash
.insert(XsdComplexType::Ptr(type
), currentSourceLocation());
6015 void XsdSchemaParser::addAnonymousType(const SchemaType::Ptr
&type
)
6017 m_schema
->addAnonymousType(type
);
6018 if (type
->isSimpleType())
6019 m_componentLocationHash
.insert(XsdSimpleType::Ptr(type
), currentSourceLocation());
6021 m_componentLocationHash
.insert(XsdComplexType::Ptr(type
), currentSourceLocation());
6024 void XsdSchemaParser::addAttributeGroup(const XsdAttributeGroup::Ptr
&group
)
6026 const QXmlName objectName
= group
->name(m_namePool
);
6027 if (m_schema
->attributeGroup(objectName
)) {
6028 error(QtXmlPatterns::tr("Attribute group %1 already defined.").arg(formatKeyword(m_namePool
, objectName
)));
6030 m_schema
->addAttributeGroup(group
);
6031 m_componentLocationHash
.insert(group
, currentSourceLocation());
6035 void XsdSchemaParser::addElementGroup(const XsdModelGroup::Ptr
&group
)
6037 const QXmlName objectName
= group
->name(m_namePool
);
6038 if (m_schema
->elementGroup(objectName
)) {
6039 error(QtXmlPatterns::tr("Element group %1 already defined.").arg(formatKeyword(m_namePool
, objectName
)));
6041 m_schema
->addElementGroup(group
);
6042 m_componentLocationHash
.insert(group
, currentSourceLocation());
6046 void XsdSchemaParser::addNotation(const XsdNotation::Ptr
¬ation
)
6048 const QXmlName objectName
= notation
->name(m_namePool
);
6049 if (m_schema
->notation(objectName
)) {
6050 error(QtXmlPatterns::tr("Notation %1 already defined.").arg(formatKeyword(m_namePool
, objectName
)));
6052 m_schema
->addNotation(notation
);
6053 m_componentLocationHash
.insert(notation
, currentSourceLocation());
6057 void XsdSchemaParser::addIdentityConstraint(const XsdIdentityConstraint::Ptr
&constraint
)
6059 const QXmlName objectName
= constraint
->name(m_namePool
);
6060 if (m_schema
->identityConstraint(objectName
)) {
6061 error(QtXmlPatterns::tr("Identity constraint %1 already defined.").arg(formatKeyword(m_namePool
, objectName
)));
6063 m_schema
->addIdentityConstraint(constraint
);
6064 m_componentLocationHash
.insert(constraint
, currentSourceLocation());
6068 void XsdSchemaParser::addFacet(const XsdFacet::Ptr
&facet
, XsdFacet::Hash
&facets
, const SchemaType::Ptr
&type
)
6070 // @see http://www.w3.org/TR/xmlschema-2/#src-single-facet-value
6071 if (facets
.contains(facet
->type())) {
6072 error(QtXmlPatterns::tr("Duplicated facets in simple type %1.").arg(formatType(m_namePool
, type
)));
6076 facets
.insert(facet
->type(), facet
);