summaryrefslogtreecommitdiff
path: root/src/xmlpatterns/schema
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmlpatterns/schema')
-rw-r--r--src/xmlpatterns/schema/.gitignore1
-rw-r--r--src/xmlpatterns/schema/builtinschemas.qrc5
-rw-r--r--src/xmlpatterns/schema/doc/All_diagram.dot13
-rw-r--r--src/xmlpatterns/schema/doc/Alternative_diagram.dot11
-rw-r--r--src/xmlpatterns/schema/doc/Annotation_diagram.dot9
-rw-r--r--src/xmlpatterns/schema/doc/AnyAttribute_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/Any_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/Assert_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/Choice_diagram.dot22
-rw-r--r--src/xmlpatterns/schema/doc/ComplexContentExtension_diagram.dot47
-rw-r--r--src/xmlpatterns/schema/doc/ComplexContentRestriction_diagram.dot47
-rw-r--r--src/xmlpatterns/schema/doc/ComplexContent_diagram.dot11
-rw-r--r--src/xmlpatterns/schema/doc/DefaultOpenContent_diagram.dot9
-rw-r--r--src/xmlpatterns/schema/doc/EnumerationFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/Field_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/FractionDigitsFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/GlobalAttribute_diagram.dot9
-rw-r--r--src/xmlpatterns/schema/doc/GlobalComplexType_diagram.dot52
-rw-r--r--src/xmlpatterns/schema/doc/GlobalElement_diagram.dot32
-rw-r--r--src/xmlpatterns/schema/doc/GlobalSimpleType_diagram.dot13
-rw-r--r--src/xmlpatterns/schema/doc/Import_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/Include_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/KeyRef_diagram.dot12
-rw-r--r--src/xmlpatterns/schema/doc/Key_diagram.dot12
-rw-r--r--src/xmlpatterns/schema/doc/LengthFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/List_diagram.dot9
-rw-r--r--src/xmlpatterns/schema/doc/LocalAll_diagram.dot13
-rw-r--r--src/xmlpatterns/schema/doc/LocalAttribute_diagram.dot9
-rw-r--r--src/xmlpatterns/schema/doc/LocalChoice_diagram.dot22
-rw-r--r--src/xmlpatterns/schema/doc/LocalComplexType_diagram.dot52
-rw-r--r--src/xmlpatterns/schema/doc/LocalElement_diagram.dot32
-rw-r--r--src/xmlpatterns/schema/doc/LocalSequence_diagram.dot22
-rw-r--r--src/xmlpatterns/schema/doc/LocalSimpleType_diagram.dot13
-rw-r--r--src/xmlpatterns/schema/doc/MaxExclusiveFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/MaxInclusiveFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/MaxLengthFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/MinExclusiveFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/MinInclusiveFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/MinLengthFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/NamedAttributeGroup_diagram.dot17
-rw-r--r--src/xmlpatterns/schema/doc/NamedGroup_diagram.dot13
-rw-r--r--src/xmlpatterns/schema/doc/Notation_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/Override_diagram.dot21
-rw-r--r--src/xmlpatterns/schema/doc/PatternFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/Redefine_diagram.dot15
-rw-r--r--src/xmlpatterns/schema/doc/ReferredAttributeGroup_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/ReferredGroup_diagram.dot13
-rw-r--r--src/xmlpatterns/schema/doc/Schema_diagram.dot66
-rw-r--r--src/xmlpatterns/schema/doc/Selector_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/Sequence_diagram.dot22
-rw-r--r--src/xmlpatterns/schema/doc/SimpleContentExtension_diagram.dot23
-rw-r--r--src/xmlpatterns/schema/doc/SimpleContentRestriction_diagram.dot87
-rw-r--r--src/xmlpatterns/schema/doc/SimpleContent_diagram.dot11
-rw-r--r--src/xmlpatterns/schema/doc/SimpleRestriction_diagram.dot62
-rw-r--r--src/xmlpatterns/schema/doc/TotalDigitsFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/Union_diagram.dot10
-rw-r--r--src/xmlpatterns/schema/doc/Unique_diagram.dot12
-rw-r--r--src/xmlpatterns/schema/doc/WhiteSpaceFacet_diagram.dot6
-rw-r--r--src/xmlpatterns/schema/doc/legend.dot7
-rw-r--r--src/xmlpatterns/schema/qnamespacesupport.cpp132
-rw-r--r--src/xmlpatterns/schema/qnamespacesupport_p.h143
-rw-r--r--src/xmlpatterns/schema/qxsdalternative.cpp38
-rw-r--r--src/xmlpatterns/schema/qxsdalternative_p.h84
-rw-r--r--src/xmlpatterns/schema/qxsdannotated.cpp33
-rw-r--r--src/xmlpatterns/schema/qxsdannotated_p.h66
-rw-r--r--src/xmlpatterns/schema/qxsdannotation.cpp48
-rw-r--r--src/xmlpatterns/schema/qxsdannotation_p.h97
-rw-r--r--src/xmlpatterns/schema/qxsdapplicationinformation.cpp38
-rw-r--r--src/xmlpatterns/schema/qxsdapplicationinformation_p.h85
-rw-r--r--src/xmlpatterns/schema/qxsdassertion.cpp28
-rw-r--r--src/xmlpatterns/schema/qxsdassertion_p.h71
-rw-r--r--src/xmlpatterns/schema/qxsdattribute.cpp100
-rw-r--r--src/xmlpatterns/schema/qxsdattribute_p.h216
-rw-r--r--src/xmlpatterns/schema/qxsdattributegroup.cpp43
-rw-r--r--src/xmlpatterns/schema/qxsdattributegroup_p.h92
-rw-r--r--src/xmlpatterns/schema/qxsdattributereference.cpp58
-rw-r--r--src/xmlpatterns/schema/qxsdattributereference_p.h117
-rw-r--r--src/xmlpatterns/schema/qxsdattributeterm.cpp28
-rw-r--r--src/xmlpatterns/schema/qxsdattributeterm_p.h66
-rw-r--r--src/xmlpatterns/schema/qxsdattributeuse.cpp106
-rw-r--r--src/xmlpatterns/schema/qxsdattributeuse_p.h194
-rw-r--r--src/xmlpatterns/schema/qxsdcomplextype.cpp201
-rw-r--r--src/xmlpatterns/schema/qxsdcomplextype_p.h374
-rw-r--r--src/xmlpatterns/schema/qxsddocumentation.cpp56
-rw-r--r--src/xmlpatterns/schema/qxsddocumentation_p.h107
-rw-r--r--src/xmlpatterns/schema/qxsdelement.cpp214
-rw-r--r--src/xmlpatterns/schema/qxsdelement_p.h373
-rw-r--r--src/xmlpatterns/schema/qxsdfacet.cpp94
-rw-r--r--src/xmlpatterns/schema/qxsdfacet_p.h183
-rw-r--r--src/xmlpatterns/schema/qxsdidcache.cpp36
-rw-r--r--src/xmlpatterns/schema/qxsdidcache_p.h69
-rw-r--r--src/xmlpatterns/schema/qxsdidchelper.cpp107
-rw-r--r--src/xmlpatterns/schema/qxsdidchelper_p.h156
-rw-r--r--src/xmlpatterns/schema/qxsdidentityconstraint.cpp63
-rw-r--r--src/xmlpatterns/schema/qxsdidentityconstraint_p.h143
-rw-r--r--src/xmlpatterns/schema/qxsdinstancereader.cpp166
-rw-r--r--src/xmlpatterns/schema/qxsdinstancereader_p.h159
-rw-r--r--src/xmlpatterns/schema/qxsdmodelgroup.cpp48
-rw-r--r--src/xmlpatterns/schema/qxsdmodelgroup_p.h109
-rw-r--r--src/xmlpatterns/schema/qxsdnotation.cpp38
-rw-r--r--src/xmlpatterns/schema/qxsdnotation_p.h89
-rw-r--r--src/xmlpatterns/schema/qxsdparticle.cpp65
-rw-r--r--src/xmlpatterns/schema/qxsdparticle_p.h124
-rw-r--r--src/xmlpatterns/schema/qxsdparticlechecker.cpp510
-rw-r--r--src/xmlpatterns/schema/qxsdparticlechecker_p.h69
-rw-r--r--src/xmlpatterns/schema/qxsdreference.cpp53
-rw-r--r--src/xmlpatterns/schema/qxsdreference_p.h115
-rw-r--r--src/xmlpatterns/schema/qxsdschema.cpp242
-rw-r--r--src/xmlpatterns/schema/qxsdschema_p.h271
-rw-r--r--src/xmlpatterns/schema/qxsdschemachecker.cpp2031
-rw-r--r--src/xmlpatterns/schema/qxsdschemachecker_helper.cpp276
-rw-r--r--src/xmlpatterns/schema/qxsdschemachecker_p.h254
-rw-r--r--src/xmlpatterns/schema/qxsdschemachecker_setup.cpp287
-rw-r--r--src/xmlpatterns/schema/qxsdschemacontext.cpp498
-rw-r--r--src/xmlpatterns/schema/qxsdschemacontext_p.h157
-rw-r--r--src/xmlpatterns/schema/qxsdschemadebugger.cpp196
-rw-r--r--src/xmlpatterns/schema/qxsdschemadebugger_p.h97
-rw-r--r--src/xmlpatterns/schema/qxsdschemahelper.cpp791
-rw-r--r--src/xmlpatterns/schema/qxsdschemahelper_p.h156
-rw-r--r--src/xmlpatterns/schema/qxsdschemamerger.cpp127
-rw-r--r--src/xmlpatterns/schema/qxsdschemamerger_p.h69
-rw-r--r--src/xmlpatterns/schema/qxsdschemaparser.cpp6012
-rw-r--r--src/xmlpatterns/schema/qxsdschemaparser_p.h691
-rw-r--r--src/xmlpatterns/schema/qxsdschemaparser_setup.cpp1070
-rw-r--r--src/xmlpatterns/schema/qxsdschemaparsercontext.cpp573
-rw-r--r--src/xmlpatterns/schema/qxsdschemaparsercontext_p.h201
-rw-r--r--src/xmlpatterns/schema/qxsdschemaresolver.cpp1706
-rw-r--r--src/xmlpatterns/schema/qxsdschemaresolver_p.h548
-rw-r--r--src/xmlpatterns/schema/qxsdschematoken.cpp2951
-rw-r--r--src/xmlpatterns/schema/qxsdschematoken_p.h168
-rw-r--r--src/xmlpatterns/schema/qxsdschematypesfactory.cpp96
-rw-r--r--src/xmlpatterns/schema/qxsdschematypesfactory_p.h79
-rw-r--r--src/xmlpatterns/schema/qxsdsimpletype.cpp118
-rw-r--r--src/xmlpatterns/schema/qxsdsimpletype_p.h189
-rw-r--r--src/xmlpatterns/schema/qxsdstatemachine.cpp433
-rw-r--r--src/xmlpatterns/schema/qxsdstatemachine_p.h209
-rw-r--r--src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp230
-rw-r--r--src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h111
-rw-r--r--src/xmlpatterns/schema/qxsdterm.cpp38
-rw-r--r--src/xmlpatterns/schema/qxsdterm_p.h84
-rw-r--r--src/xmlpatterns/schema/qxsdtypechecker.cpp1308
-rw-r--r--src/xmlpatterns/schema/qxsdtypechecker_p.h159
-rw-r--r--src/xmlpatterns/schema/qxsduserschematype.cpp45
-rw-r--r--src/xmlpatterns/schema/qxsduserschematype_p.h94
-rw-r--r--src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp185
-rw-r--r--src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h149
-rw-r--r--src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp1245
-rw-r--r--src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h266
-rw-r--r--src/xmlpatterns/schema/qxsdwildcard.cpp85
-rw-r--r--src/xmlpatterns/schema/qxsdwildcard_p.h169
-rw-r--r--src/xmlpatterns/schema/qxsdxpathexpression.cpp58
-rw-r--r--src/xmlpatterns/schema/qxsdxpathexpression_p.h113
-rw-r--r--src/xmlpatterns/schema/schema.pri93
-rw-r--r--src/xmlpatterns/schema/schemas/xml.xsd145
-rw-r--r--src/xmlpatterns/schema/tokens.xml125
155 files changed, 31784 insertions, 0 deletions
diff --git a/src/xmlpatterns/schema/.gitignore b/src/xmlpatterns/schema/.gitignore
new file mode 100644
index 0000000000..2b29f27645
--- /dev/null
+++ b/src/xmlpatterns/schema/.gitignore
@@ -0,0 +1 @@
+tests
diff --git a/src/xmlpatterns/schema/builtinschemas.qrc b/src/xmlpatterns/schema/builtinschemas.qrc
new file mode 100644
index 0000000000..fb43d78b7b
--- /dev/null
+++ b/src/xmlpatterns/schema/builtinschemas.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="http://www.w3.org/XML/1998/namespace">schemas/xml.xsd</file>
+</qresource>
+</RCC>
diff --git a/src/xmlpatterns/schema/doc/All_diagram.dot b/src/xmlpatterns/schema/doc/All_diagram.dot
new file mode 100644
index 0000000000..3352b723f5
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/All_diagram.dot
@@ -0,0 +1,13 @@
+digraph All {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="any"]
+ 1 -> 3 [label="element"]
+ 2 -> 3 [label="any"]
+ 2 -> 3 [label="element"]
+ 3 -> 3 [label="any"]
+ 3 -> 3 [label="element"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Alternative_diagram.dot b/src/xmlpatterns/schema/doc/Alternative_diagram.dot
new file mode 100644
index 0000000000..2119c4947d
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Alternative_diagram.dot
@@ -0,0 +1,11 @@
+digraph Alternative {
+ mindist = 2.0
+ 1 -> 3 [label="complexType"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="simpleType"]
+ 2 -> 3 [label="complexType"]
+ 2 -> 3 [label="simpleType"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Annotation_diagram.dot b/src/xmlpatterns/schema/doc/Annotation_diagram.dot
new file mode 100644
index 0000000000..260b6f70d0
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Annotation_diagram.dot
@@ -0,0 +1,9 @@
+digraph Annotation {
+ mindist = 2.0
+ 1 -> 2 [label="appinfo"]
+ 1 -> 2 [label="documentation"]
+ 2 -> 2 [label="appinfo"]
+ 2 -> 2 [label="documentation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/AnyAttribute_diagram.dot b/src/xmlpatterns/schema/doc/AnyAttribute_diagram.dot
new file mode 100644
index 0000000000..d252ebdaa3
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/AnyAttribute_diagram.dot
@@ -0,0 +1,6 @@
+digraph AnyAttribute {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Any_diagram.dot b/src/xmlpatterns/schema/doc/Any_diagram.dot
new file mode 100644
index 0000000000..f54063f94e
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Any_diagram.dot
@@ -0,0 +1,6 @@
+digraph Any {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Assert_diagram.dot b/src/xmlpatterns/schema/doc/Assert_diagram.dot
new file mode 100644
index 0000000000..7093bef689
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Assert_diagram.dot
@@ -0,0 +1,6 @@
+digraph Assert {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Choice_diagram.dot b/src/xmlpatterns/schema/doc/Choice_diagram.dot
new file mode 100644
index 0000000000..7b320169ca
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Choice_diagram.dot
@@ -0,0 +1,22 @@
+digraph Choice {
+ mindist = 2.0
+ 1 -> 3 [label="choice"]
+ 1 -> 3 [label="group"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="sequence"]
+ 1 -> 3 [label="any"]
+ 1 -> 3 [label="element"]
+ 2 -> 3 [label="choice"]
+ 2 -> 3 [label="group"]
+ 2 -> 3 [label="sequence"]
+ 2 -> 3 [label="any"]
+ 2 -> 3 [label="element"]
+ 3 -> 3 [label="choice"]
+ 3 -> 3 [label="group"]
+ 3 -> 3 [label="sequence"]
+ 3 -> 3 [label="any"]
+ 3 -> 3 [label="element"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/ComplexContentExtension_diagram.dot b/src/xmlpatterns/schema/doc/ComplexContentExtension_diagram.dot
new file mode 100644
index 0000000000..613161241e
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/ComplexContentExtension_diagram.dot
@@ -0,0 +1,47 @@
+digraph ComplexContentExtension {
+ mindist = 2.0
+ 1 -> 4 [label="choice"]
+ 1 -> 4 [label="group"]
+ 1 -> 4 [label="all"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 4 [label="sequence"]
+ 1 -> 6 [label="anyAttribute"]
+ 1 -> 7 [label="assert"]
+ 1 -> 3 [label="openContent"]
+ 1 -> 5 [label="attribute"]
+ 1 -> 5 [label="attributeGroup"]
+ 2 -> 4 [label="choice"]
+ 2 -> 4 [label="group"]
+ 2 -> 4 [label="all"]
+ 2 -> 4 [label="sequence"]
+ 2 -> 6 [label="anyAttribute"]
+ 2 -> 7 [label="assert"]
+ 2 -> 3 [label="openContent"]
+ 2 -> 5 [label="attribute"]
+ 2 -> 5 [label="attributeGroup"]
+ 3 -> 4 [label="choice"]
+ 3 -> 4 [label="group"]
+ 3 -> 4 [label="all"]
+ 3 -> 4 [label="sequence"]
+ 3 -> 6 [label="anyAttribute"]
+ 3 -> 7 [label="assert"]
+ 3 -> 5 [label="attribute"]
+ 3 -> 5 [label="attributeGroup"]
+ 4 -> 6 [label="anyAttribute"]
+ 4 -> 7 [label="assert"]
+ 4 -> 5 [label="attribute"]
+ 4 -> 5 [label="attributeGroup"]
+ 5 -> 6 [label="anyAttribute"]
+ 5 -> 7 [label="assert"]
+ 5 -> 5 [label="attribute"]
+ 5 -> 5 [label="attributeGroup"]
+ 6 -> 7 [label="assert"]
+ 7 -> 7 [label="assert"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+ 5 [shape=doublecircle, style=filled, color=green]
+ 6 [shape=doublecircle, style=filled, color=green]
+ 7 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/ComplexContentRestriction_diagram.dot b/src/xmlpatterns/schema/doc/ComplexContentRestriction_diagram.dot
new file mode 100644
index 0000000000..bfda892dc3
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/ComplexContentRestriction_diagram.dot
@@ -0,0 +1,47 @@
+digraph ComplexContentRestriction {
+ mindist = 2.0
+ 1 -> 4 [label="choice"]
+ 1 -> 4 [label="group"]
+ 1 -> 4 [label="all"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 4 [label="sequence"]
+ 1 -> 6 [label="anyAttribute"]
+ 1 -> 7 [label="assert"]
+ 1 -> 3 [label="openContent"]
+ 1 -> 5 [label="attribute"]
+ 1 -> 5 [label="attributeGroup"]
+ 2 -> 4 [label="choice"]
+ 2 -> 4 [label="group"]
+ 2 -> 4 [label="all"]
+ 2 -> 4 [label="sequence"]
+ 2 -> 6 [label="anyAttribute"]
+ 2 -> 7 [label="assert"]
+ 2 -> 3 [label="openContent"]
+ 2 -> 5 [label="attribute"]
+ 2 -> 5 [label="attributeGroup"]
+ 3 -> 4 [label="choice"]
+ 3 -> 4 [label="group"]
+ 3 -> 4 [label="all"]
+ 3 -> 4 [label="sequence"]
+ 3 -> 6 [label="anyAttribute"]
+ 3 -> 7 [label="assert"]
+ 3 -> 5 [label="attribute"]
+ 3 -> 5 [label="attributeGroup"]
+ 4 -> 6 [label="anyAttribute"]
+ 4 -> 7 [label="assert"]
+ 4 -> 5 [label="attribute"]
+ 4 -> 5 [label="attributeGroup"]
+ 5 -> 6 [label="anyAttribute"]
+ 5 -> 7 [label="assert"]
+ 5 -> 5 [label="attribute"]
+ 5 -> 5 [label="attributeGroup"]
+ 6 -> 7 [label="assert"]
+ 7 -> 7 [label="assert"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+ 5 [shape=doublecircle, style=filled, color=green]
+ 6 [shape=doublecircle, style=filled, color=green]
+ 7 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/ComplexContent_diagram.dot b/src/xmlpatterns/schema/doc/ComplexContent_diagram.dot
new file mode 100644
index 0000000000..949c27e22f
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/ComplexContent_diagram.dot
@@ -0,0 +1,11 @@
+digraph ComplexContent {
+ mindist = 2.0
+ 1 -> 3 [label="restriction"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="extension"]
+ 2 -> 3 [label="restriction"]
+ 2 -> 3 [label="extension"]
+ 1 [shape=circle, style=filled, color=blue]
+ 2 [shape=circle, style=filled, color=red]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/DefaultOpenContent_diagram.dot b/src/xmlpatterns/schema/doc/DefaultOpenContent_diagram.dot
new file mode 100644
index 0000000000..61e7d14800
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/DefaultOpenContent_diagram.dot
@@ -0,0 +1,9 @@
+digraph DefaultOpenContent {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="any"]
+ 2 -> 3 [label="any"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=circle, style=filled, color=red]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/EnumerationFacet_diagram.dot b/src/xmlpatterns/schema/doc/EnumerationFacet_diagram.dot
new file mode 100644
index 0000000000..91be76bf03
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/EnumerationFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph EnumerationFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Field_diagram.dot b/src/xmlpatterns/schema/doc/Field_diagram.dot
new file mode 100644
index 0000000000..1c597b32ce
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Field_diagram.dot
@@ -0,0 +1,6 @@
+digraph Field {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/FractionDigitsFacet_diagram.dot b/src/xmlpatterns/schema/doc/FractionDigitsFacet_diagram.dot
new file mode 100644
index 0000000000..5e098b32f6
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/FractionDigitsFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph FractionDigitsFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/GlobalAttribute_diagram.dot b/src/xmlpatterns/schema/doc/GlobalAttribute_diagram.dot
new file mode 100644
index 0000000000..25a1a43ca8
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/GlobalAttribute_diagram.dot
@@ -0,0 +1,9 @@
+digraph GlobalAttribute {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="simpleType"]
+ 2 -> 3 [label="simpleType"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/GlobalComplexType_diagram.dot b/src/xmlpatterns/schema/doc/GlobalComplexType_diagram.dot
new file mode 100644
index 0000000000..05e40b7767
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/GlobalComplexType_diagram.dot
@@ -0,0 +1,52 @@
+digraph GlobalComplexType {
+ mindist = 2.0
+ 1 -> 5 [label="choice"]
+ 1 -> 3 [label="complexContent"]
+ 1 -> 5 [label="group"]
+ 1 -> 5 [label="all"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 5 [label="sequence"]
+ 1 -> 3 [label="simpleContent"]
+ 1 -> 7 [label="anyAttribute"]
+ 1 -> 8 [label="assert"]
+ 1 -> 4 [label="openContent"]
+ 1 -> 6 [label="attribute"]
+ 1 -> 6 [label="attributeGroup"]
+ 2 -> 5 [label="choice"]
+ 2 -> 3 [label="complexContent"]
+ 2 -> 5 [label="group"]
+ 2 -> 5 [label="all"]
+ 2 -> 5 [label="sequence"]
+ 2 -> 3 [label="simpleContent"]
+ 2 -> 7 [label="anyAttribute"]
+ 2 -> 8 [label="assert"]
+ 2 -> 4 [label="openContent"]
+ 2 -> 6 [label="attribute"]
+ 2 -> 6 [label="attributeGroup"]
+ 4 -> 5 [label="choice"]
+ 4 -> 5 [label="group"]
+ 4 -> 5 [label="all"]
+ 4 -> 5 [label="sequence"]
+ 4 -> 7 [label="anyAttribute"]
+ 4 -> 8 [label="assert"]
+ 4 -> 6 [label="attribute"]
+ 4 -> 6 [label="attributeGroup"]
+ 5 -> 7 [label="anyAttribute"]
+ 5 -> 8 [label="assert"]
+ 5 -> 6 [label="attribute"]
+ 5 -> 6 [label="attributeGroup"]
+ 6 -> 7 [label="anyAttribute"]
+ 6 -> 8 [label="assert"]
+ 6 -> 6 [label="attribute"]
+ 6 -> 6 [label="attributeGroup"]
+ 7 -> 8 [label="assert"]
+ 8 -> 8 [label="assert"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+ 5 [shape=doublecircle, style=filled, color=green]
+ 6 [shape=doublecircle, style=filled, color=green]
+ 7 [shape=doublecircle, style=filled, color=green]
+ 8 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/GlobalElement_diagram.dot b/src/xmlpatterns/schema/doc/GlobalElement_diagram.dot
new file mode 100644
index 0000000000..20447a7129
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/GlobalElement_diagram.dot
@@ -0,0 +1,32 @@
+digraph GlobalElement {
+ mindist = 2.0
+ 1 -> 3 [label="complexType"]
+ 1 -> 4 [label="alternative"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 5 [label="key"]
+ 1 -> 3 [label="simpleType"]
+ 1 -> 5 [label="keyref"]
+ 1 -> 5 [label="unique"]
+ 2 -> 3 [label="complexType"]
+ 2 -> 4 [label="alternative"]
+ 2 -> 5 [label="key"]
+ 2 -> 3 [label="simpleType"]
+ 2 -> 5 [label="keyref"]
+ 2 -> 5 [label="unique"]
+ 3 -> 4 [label="alternative"]
+ 3 -> 5 [label="key"]
+ 3 -> 5 [label="keyref"]
+ 3 -> 5 [label="unique"]
+ 4 -> 4 [label="alternative"]
+ 4 -> 5 [label="key"]
+ 4 -> 5 [label="keyref"]
+ 4 -> 5 [label="unique"]
+ 5 -> 5 [label="key"]
+ 5 -> 5 [label="keyref"]
+ 5 -> 5 [label="unique"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+ 5 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/GlobalSimpleType_diagram.dot b/src/xmlpatterns/schema/doc/GlobalSimpleType_diagram.dot
new file mode 100644
index 0000000000..ccb7f54ea4
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/GlobalSimpleType_diagram.dot
@@ -0,0 +1,13 @@
+digraph GlobalSimpleType {
+ mindist = 2.0
+ 1 -> 3 [label="restriction"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="list"]
+ 1 -> 3 [label="union"]
+ 2 -> 3 [label="restriction"]
+ 2 -> 3 [label="list"]
+ 2 -> 3 [label="union"]
+ 1 [shape=circle, style=filled, color=blue]
+ 2 [shape=circle, style=filled, color=red]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Import_diagram.dot b/src/xmlpatterns/schema/doc/Import_diagram.dot
new file mode 100644
index 0000000000..3484bc3221
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Import_diagram.dot
@@ -0,0 +1,6 @@
+digraph Import {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Include_diagram.dot b/src/xmlpatterns/schema/doc/Include_diagram.dot
new file mode 100644
index 0000000000..357e4c922c
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Include_diagram.dot
@@ -0,0 +1,6 @@
+digraph Include {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/KeyRef_diagram.dot b/src/xmlpatterns/schema/doc/KeyRef_diagram.dot
new file mode 100644
index 0000000000..ff425b98f1
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/KeyRef_diagram.dot
@@ -0,0 +1,12 @@
+digraph KeyRef {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="selector"]
+ 2 -> 3 [label="selector"]
+ 3 -> 4 [label="field"]
+ 4 -> 4 [label="field"]
+ 1 [shape=circle, style=filled, color=blue]
+ 2 [shape=circle, style=filled, color=red]
+ 3 [shape=circle, style=filled, color=red]
+ 4 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Key_diagram.dot b/src/xmlpatterns/schema/doc/Key_diagram.dot
new file mode 100644
index 0000000000..bbc09cd8e9
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Key_diagram.dot
@@ -0,0 +1,12 @@
+digraph Key {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="selector"]
+ 2 -> 3 [label="selector"]
+ 3 -> 4 [label="field"]
+ 4 -> 4 [label="field"]
+ 1 [shape=circle, style=filled, color=blue]
+ 2 [shape=circle, style=filled, color=red]
+ 3 [shape=circle, style=filled, color=red]
+ 4 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/LengthFacet_diagram.dot b/src/xmlpatterns/schema/doc/LengthFacet_diagram.dot
new file mode 100644
index 0000000000..1f9205b10c
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/LengthFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph LengthFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/List_diagram.dot b/src/xmlpatterns/schema/doc/List_diagram.dot
new file mode 100644
index 0000000000..44cc698f0d
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/List_diagram.dot
@@ -0,0 +1,9 @@
+digraph List {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="simpleType"]
+ 2 -> 3 [label="simpleType"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/LocalAll_diagram.dot b/src/xmlpatterns/schema/doc/LocalAll_diagram.dot
new file mode 100644
index 0000000000..88f1b6126b
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/LocalAll_diagram.dot
@@ -0,0 +1,13 @@
+digraph LocalAll {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="any"]
+ 1 -> 3 [label="element"]
+ 2 -> 3 [label="any"]
+ 2 -> 3 [label="element"]
+ 3 -> 3 [label="any"]
+ 3 -> 3 [label="element"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/LocalAttribute_diagram.dot b/src/xmlpatterns/schema/doc/LocalAttribute_diagram.dot
new file mode 100644
index 0000000000..b01f0cfff6
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/LocalAttribute_diagram.dot
@@ -0,0 +1,9 @@
+digraph LocalAttribute {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="simpleType"]
+ 2 -> 3 [label="simpleType"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/LocalChoice_diagram.dot b/src/xmlpatterns/schema/doc/LocalChoice_diagram.dot
new file mode 100644
index 0000000000..b16c47f668
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/LocalChoice_diagram.dot
@@ -0,0 +1,22 @@
+digraph LocalChoice {
+ mindist = 2.0
+ 1 -> 3 [label="choice"]
+ 1 -> 3 [label="group"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="sequence"]
+ 1 -> 3 [label="any"]
+ 1 -> 3 [label="element"]
+ 2 -> 3 [label="choice"]
+ 2 -> 3 [label="group"]
+ 2 -> 3 [label="sequence"]
+ 2 -> 3 [label="any"]
+ 2 -> 3 [label="element"]
+ 3 -> 3 [label="choice"]
+ 3 -> 3 [label="group"]
+ 3 -> 3 [label="sequence"]
+ 3 -> 3 [label="any"]
+ 3 -> 3 [label="element"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/LocalComplexType_diagram.dot b/src/xmlpatterns/schema/doc/LocalComplexType_diagram.dot
new file mode 100644
index 0000000000..92c54b7873
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/LocalComplexType_diagram.dot
@@ -0,0 +1,52 @@
+digraph LocalComplexType {
+ mindist = 2.0
+ 1 -> 5 [label="choice"]
+ 1 -> 3 [label="complexContent"]
+ 1 -> 5 [label="group"]
+ 1 -> 5 [label="all"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 5 [label="sequence"]
+ 1 -> 3 [label="simpleContent"]
+ 1 -> 7 [label="anyAttribute"]
+ 1 -> 8 [label="assert"]
+ 1 -> 4 [label="openContent"]
+ 1 -> 6 [label="attribute"]
+ 1 -> 6 [label="attributeGroup"]
+ 2 -> 5 [label="choice"]
+ 2 -> 3 [label="complexContent"]
+ 2 -> 5 [label="group"]
+ 2 -> 5 [label="all"]
+ 2 -> 5 [label="sequence"]
+ 2 -> 3 [label="simpleContent"]
+ 2 -> 7 [label="anyAttribute"]
+ 2 -> 8 [label="assert"]
+ 2 -> 4 [label="openContent"]
+ 2 -> 6 [label="attribute"]
+ 2 -> 6 [label="attributeGroup"]
+ 4 -> 5 [label="choice"]
+ 4 -> 5 [label="group"]
+ 4 -> 5 [label="all"]
+ 4 -> 5 [label="sequence"]
+ 4 -> 7 [label="anyAttribute"]
+ 4 -> 8 [label="assert"]
+ 4 -> 6 [label="attribute"]
+ 4 -> 6 [label="attributeGroup"]
+ 5 -> 7 [label="anyAttribute"]
+ 5 -> 8 [label="assert"]
+ 5 -> 6 [label="attribute"]
+ 5 -> 6 [label="attributeGroup"]
+ 6 -> 7 [label="anyAttribute"]
+ 6 -> 8 [label="assert"]
+ 6 -> 6 [label="attribute"]
+ 6 -> 6 [label="attributeGroup"]
+ 7 -> 8 [label="assert"]
+ 8 -> 8 [label="assert"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+ 5 [shape=doublecircle, style=filled, color=green]
+ 6 [shape=doublecircle, style=filled, color=green]
+ 7 [shape=doublecircle, style=filled, color=green]
+ 8 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/LocalElement_diagram.dot b/src/xmlpatterns/schema/doc/LocalElement_diagram.dot
new file mode 100644
index 0000000000..397397a59a
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/LocalElement_diagram.dot
@@ -0,0 +1,32 @@
+digraph LocalElement {
+ mindist = 2.0
+ 1 -> 3 [label="complexType"]
+ 1 -> 4 [label="alternative"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 5 [label="key"]
+ 1 -> 3 [label="simpleType"]
+ 1 -> 5 [label="keyref"]
+ 1 -> 5 [label="unique"]
+ 2 -> 3 [label="complexType"]
+ 2 -> 4 [label="alternative"]
+ 2 -> 5 [label="key"]
+ 2 -> 3 [label="simpleType"]
+ 2 -> 5 [label="keyref"]
+ 2 -> 5 [label="unique"]
+ 3 -> 4 [label="alternative"]
+ 3 -> 5 [label="key"]
+ 3 -> 5 [label="keyref"]
+ 3 -> 5 [label="unique"]
+ 4 -> 4 [label="alternative"]
+ 4 -> 5 [label="key"]
+ 4 -> 5 [label="keyref"]
+ 4 -> 5 [label="unique"]
+ 5 -> 5 [label="key"]
+ 5 -> 5 [label="keyref"]
+ 5 -> 5 [label="unique"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+ 5 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/LocalSequence_diagram.dot b/src/xmlpatterns/schema/doc/LocalSequence_diagram.dot
new file mode 100644
index 0000000000..0dc7f39d4b
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/LocalSequence_diagram.dot
@@ -0,0 +1,22 @@
+digraph LocalSequence {
+ mindist = 2.0
+ 1 -> 3 [label="choice"]
+ 1 -> 3 [label="group"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="sequence"]
+ 1 -> 3 [label="any"]
+ 1 -> 3 [label="element"]
+ 2 -> 3 [label="choice"]
+ 2 -> 3 [label="group"]
+ 2 -> 3 [label="sequence"]
+ 2 -> 3 [label="any"]
+ 2 -> 3 [label="element"]
+ 3 -> 3 [label="choice"]
+ 3 -> 3 [label="group"]
+ 3 -> 3 [label="sequence"]
+ 3 -> 3 [label="any"]
+ 3 -> 3 [label="element"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/LocalSimpleType_diagram.dot b/src/xmlpatterns/schema/doc/LocalSimpleType_diagram.dot
new file mode 100644
index 0000000000..ac13305aa7
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/LocalSimpleType_diagram.dot
@@ -0,0 +1,13 @@
+digraph LocalSimpleType {
+ mindist = 2.0
+ 1 -> 3 [label="restriction"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="list"]
+ 1 -> 3 [label="union"]
+ 2 -> 3 [label="restriction"]
+ 2 -> 3 [label="list"]
+ 2 -> 3 [label="union"]
+ 1 [shape=circle, style=filled, color=blue]
+ 2 [shape=circle, style=filled, color=red]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/MaxExclusiveFacet_diagram.dot b/src/xmlpatterns/schema/doc/MaxExclusiveFacet_diagram.dot
new file mode 100644
index 0000000000..28364f7241
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/MaxExclusiveFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph MaxExclusiveFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/MaxInclusiveFacet_diagram.dot b/src/xmlpatterns/schema/doc/MaxInclusiveFacet_diagram.dot
new file mode 100644
index 0000000000..9e2c265e41
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/MaxInclusiveFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph MaxInclusiveFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/MaxLengthFacet_diagram.dot b/src/xmlpatterns/schema/doc/MaxLengthFacet_diagram.dot
new file mode 100644
index 0000000000..d565217329
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/MaxLengthFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph MaxLengthFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/MinExclusiveFacet_diagram.dot b/src/xmlpatterns/schema/doc/MinExclusiveFacet_diagram.dot
new file mode 100644
index 0000000000..d3b3f1f9b4
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/MinExclusiveFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph MinExclusiveFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/MinInclusiveFacet_diagram.dot b/src/xmlpatterns/schema/doc/MinInclusiveFacet_diagram.dot
new file mode 100644
index 0000000000..e5ca65d8f0
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/MinInclusiveFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph MinInclusiveFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/MinLengthFacet_diagram.dot b/src/xmlpatterns/schema/doc/MinLengthFacet_diagram.dot
new file mode 100644
index 0000000000..1dcced49ac
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/MinLengthFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph MinLengthFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/NamedAttributeGroup_diagram.dot b/src/xmlpatterns/schema/doc/NamedAttributeGroup_diagram.dot
new file mode 100644
index 0000000000..1754f6753d
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/NamedAttributeGroup_diagram.dot
@@ -0,0 +1,17 @@
+digraph NamedAttributeGroup {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 4 [label="anyAttribute"]
+ 1 -> 3 [label="attribute"]
+ 1 -> 3 [label="attributeGroup"]
+ 2 -> 4 [label="anyAttribute"]
+ 2 -> 3 [label="attribute"]
+ 2 -> 3 [label="attributeGroup"]
+ 3 -> 4 [label="anyAttribute"]
+ 3 -> 3 [label="attribute"]
+ 3 -> 3 [label="attributeGroup"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/NamedGroup_diagram.dot b/src/xmlpatterns/schema/doc/NamedGroup_diagram.dot
new file mode 100644
index 0000000000..6d9a289c0d
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/NamedGroup_diagram.dot
@@ -0,0 +1,13 @@
+digraph NamedGroup {
+ mindist = 2.0
+ 1 -> 3 [label="choice"]
+ 1 -> 3 [label="all"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="sequence"]
+ 2 -> 3 [label="choice"]
+ 2 -> 3 [label="all"]
+ 2 -> 3 [label="sequence"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Notation_diagram.dot b/src/xmlpatterns/schema/doc/Notation_diagram.dot
new file mode 100644
index 0000000000..951f26a041
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Notation_diagram.dot
@@ -0,0 +1,6 @@
+digraph Notation {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Override_diagram.dot b/src/xmlpatterns/schema/doc/Override_diagram.dot
new file mode 100644
index 0000000000..448451a32c
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Override_diagram.dot
@@ -0,0 +1,21 @@
+digraph Override {
+ mindist = 2.0
+ 1 -> 2 [label="group"]
+ 1 -> 2 [label="complexType"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 2 [label="simpleType"]
+ 1 -> 2 [label="element"]
+ 1 -> 2 [label="notation"]
+ 1 -> 2 [label="attribute"]
+ 1 -> 2 [label="attributeGroup"]
+ 2 -> 2 [label="group"]
+ 2 -> 2 [label="complexType"]
+ 2 -> 2 [label="annotation"]
+ 2 -> 2 [label="simpleType"]
+ 2 -> 2 [label="element"]
+ 2 -> 2 [label="notation"]
+ 2 -> 2 [label="attribute"]
+ 2 -> 2 [label="attributeGroup"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/PatternFacet_diagram.dot b/src/xmlpatterns/schema/doc/PatternFacet_diagram.dot
new file mode 100644
index 0000000000..794d74c6f5
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/PatternFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph PatternFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Redefine_diagram.dot b/src/xmlpatterns/schema/doc/Redefine_diagram.dot
new file mode 100644
index 0000000000..ba4871deb9
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Redefine_diagram.dot
@@ -0,0 +1,15 @@
+digraph Redefine {
+ mindist = 2.0
+ 1 -> 2 [label="group"]
+ 1 -> 2 [label="complexType"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 2 [label="simpleType"]
+ 1 -> 2 [label="attributeGroup"]
+ 2 -> 2 [label="group"]
+ 2 -> 2 [label="complexType"]
+ 2 -> 2 [label="annotation"]
+ 2 -> 2 [label="simpleType"]
+ 2 -> 2 [label="attributeGroup"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/ReferredAttributeGroup_diagram.dot b/src/xmlpatterns/schema/doc/ReferredAttributeGroup_diagram.dot
new file mode 100644
index 0000000000..fd0887256b
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/ReferredAttributeGroup_diagram.dot
@@ -0,0 +1,6 @@
+digraph ReferredAttributeGroup {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/ReferredGroup_diagram.dot b/src/xmlpatterns/schema/doc/ReferredGroup_diagram.dot
new file mode 100644
index 0000000000..c32f69f83c
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/ReferredGroup_diagram.dot
@@ -0,0 +1,13 @@
+digraph ReferredGroup {
+ mindist = 2.0
+ 1 -> 3 [label="choice"]
+ 1 -> 3 [label="all"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="sequence"]
+ 2 -> 3 [label="choice"]
+ 2 -> 3 [label="all"]
+ 2 -> 3 [label="sequence"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Schema_diagram.dot b/src/xmlpatterns/schema/doc/Schema_diagram.dot
new file mode 100644
index 0000000000..7d39337ce6
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Schema_diagram.dot
@@ -0,0 +1,66 @@
+digraph Schema {
+ mindist = 2.0
+ 1 -> 5 [label="group"]
+ 1 -> 5 [label="complexType"]
+ 1 -> 2 [label="import"]
+ 1 -> 2 [label="include"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="defaultOpenContent"]
+ 1 -> 5 [label="simpleType"]
+ 1 -> 5 [label="element"]
+ 1 -> 5 [label="notation"]
+ 1 -> 2 [label="override"]
+ 1 -> 5 [label="attribute"]
+ 1 -> 5 [label="attributeGroup"]
+ 1 -> 2 [label="redefine"]
+ 2 -> 5 [label="group"]
+ 2 -> 5 [label="complexType"]
+ 2 -> 2 [label="import"]
+ 2 -> 2 [label="include"]
+ 2 -> 2 [label="annotation"]
+ 2 -> 3 [label="defaultOpenContent"]
+ 2 -> 5 [label="simpleType"]
+ 2 -> 5 [label="element"]
+ 2 -> 5 [label="notation"]
+ 2 -> 2 [label="override"]
+ 2 -> 5 [label="attribute"]
+ 2 -> 5 [label="attributeGroup"]
+ 2 -> 2 [label="redefine"]
+ 3 -> 5 [label="group"]
+ 3 -> 5 [label="complexType"]
+ 3 -> 4 [label="annotation"]
+ 3 -> 5 [label="simpleType"]
+ 3 -> 5 [label="element"]
+ 3 -> 5 [label="notation"]
+ 3 -> 5 [label="attribute"]
+ 3 -> 5 [label="attributeGroup"]
+ 4 -> 5 [label="group"]
+ 4 -> 5 [label="complexType"]
+ 4 -> 5 [label="simpleType"]
+ 4 -> 5 [label="element"]
+ 4 -> 5 [label="notation"]
+ 4 -> 5 [label="attribute"]
+ 4 -> 5 [label="attributeGroup"]
+ 5 -> 5 [label="group"]
+ 5 -> 5 [label="complexType"]
+ 5 -> 6 [label="annotation"]
+ 5 -> 5 [label="simpleType"]
+ 5 -> 5 [label="element"]
+ 5 -> 5 [label="notation"]
+ 5 -> 5 [label="attribute"]
+ 5 -> 5 [label="attributeGroup"]
+ 6 -> 5 [label="group"]
+ 6 -> 5 [label="complexType"]
+ 6 -> 6 [label="annotation"]
+ 6 -> 5 [label="simpleType"]
+ 6 -> 5 [label="element"]
+ 6 -> 5 [label="notation"]
+ 6 -> 5 [label="attribute"]
+ 6 -> 5 [label="attributeGroup"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+ 5 [shape=doublecircle, style=filled, color=green]
+ 6 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Selector_diagram.dot b/src/xmlpatterns/schema/doc/Selector_diagram.dot
new file mode 100644
index 0000000000..f3e93dce69
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Selector_diagram.dot
@@ -0,0 +1,6 @@
+digraph Selector {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Sequence_diagram.dot b/src/xmlpatterns/schema/doc/Sequence_diagram.dot
new file mode 100644
index 0000000000..917274408d
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Sequence_diagram.dot
@@ -0,0 +1,22 @@
+digraph Sequence {
+ mindist = 2.0
+ 1 -> 3 [label="choice"]
+ 1 -> 3 [label="group"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="sequence"]
+ 1 -> 3 [label="any"]
+ 1 -> 3 [label="element"]
+ 2 -> 3 [label="choice"]
+ 2 -> 3 [label="group"]
+ 2 -> 3 [label="sequence"]
+ 2 -> 3 [label="any"]
+ 2 -> 3 [label="element"]
+ 3 -> 3 [label="choice"]
+ 3 -> 3 [label="group"]
+ 3 -> 3 [label="sequence"]
+ 3 -> 3 [label="any"]
+ 3 -> 3 [label="element"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/SimpleContentExtension_diagram.dot b/src/xmlpatterns/schema/doc/SimpleContentExtension_diagram.dot
new file mode 100644
index 0000000000..3ceebfd30b
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/SimpleContentExtension_diagram.dot
@@ -0,0 +1,23 @@
+digraph SimpleContentExtension {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 4 [label="anyAttribute"]
+ 1 -> 5 [label="assert"]
+ 1 -> 3 [label="attribute"]
+ 1 -> 3 [label="attributeGroup"]
+ 2 -> 4 [label="anyAttribute"]
+ 2 -> 5 [label="assert"]
+ 2 -> 3 [label="attribute"]
+ 2 -> 3 [label="attributeGroup"]
+ 3 -> 4 [label="anyAttribute"]
+ 3 -> 5 [label="assert"]
+ 3 -> 3 [label="attribute"]
+ 3 -> 3 [label="attributeGroup"]
+ 4 -> 5 [label="assert"]
+ 5 -> 5 [label="assert"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+ 5 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/SimpleContentRestriction_diagram.dot b/src/xmlpatterns/schema/doc/SimpleContentRestriction_diagram.dot
new file mode 100644
index 0000000000..75b0b71e24
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/SimpleContentRestriction_diagram.dot
@@ -0,0 +1,87 @@
+digraph SimpleContentRestriction {
+ mindist = 2.0
+ 1 -> 3 [label="simpleType"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 4 [label="length"]
+ 1 -> 6 [label="anyAttribute"]
+ 1 -> 4 [label="maxExclusive"]
+ 1 -> 4 [label="totalDigits"]
+ 1 -> 4 [label="maxInclusive"]
+ 1 -> 4 [label="maxLength"]
+ 1 -> 7 [label="assert"]
+ 1 -> 4 [label="assertion"]
+ 1 -> 5 [label="attribute"]
+ 1 -> 4 [label="minExclusive"]
+ 1 -> 5 [label="attributeGroup"]
+ 1 -> 4 [label="minInclusive"]
+ 1 -> 4 [label="minLength"]
+ 1 -> 4 [label="whiteSpace"]
+ 1 -> 4 [label="pattern"]
+ 1 -> 4 [label="enumeration"]
+ 1 -> 4 [label="fractionDigits"]
+ 2 -> 3 [label="simpleType"]
+ 2 -> 4 [label="length"]
+ 2 -> 6 [label="anyAttribute"]
+ 2 -> 4 [label="maxExclusive"]
+ 2 -> 4 [label="totalDigits"]
+ 2 -> 4 [label="maxInclusive"]
+ 2 -> 4 [label="maxLength"]
+ 2 -> 7 [label="assert"]
+ 2 -> 4 [label="assertion"]
+ 2 -> 5 [label="attribute"]
+ 2 -> 4 [label="minExclusive"]
+ 2 -> 5 [label="attributeGroup"]
+ 2 -> 4 [label="minInclusive"]
+ 2 -> 4 [label="minLength"]
+ 2 -> 4 [label="whiteSpace"]
+ 2 -> 4 [label="pattern"]
+ 2 -> 4 [label="enumeration"]
+ 2 -> 4 [label="fractionDigits"]
+ 3 -> 4 [label="fractionDigits"]
+ 3 -> 4 [label="minLength"]
+ 3 -> 4 [label="whiteSpace"]
+ 3 -> 6 [label="anyAttribute"]
+ 3 -> 4 [label="length"]
+ 3 -> 7 [label="assert"]
+ 3 -> 4 [label="maxExclusive"]
+ 3 -> 4 [label="enumeration"]
+ 3 -> 4 [label="assertion"]
+ 3 -> 4 [label="maxInclusive"]
+ 3 -> 5 [label="attribute"]
+ 3 -> 4 [label="maxLength"]
+ 3 -> 4 [label="pattern"]
+ 3 -> 4 [label="totalDigits"]
+ 3 -> 5 [label="attributeGroup"]
+ 3 -> 4 [label="minExclusive"]
+ 3 -> 4 [label="minInclusive"]
+ 4 -> 4 [label="fractionDigits"]
+ 4 -> 4 [label="minLength"]
+ 4 -> 4 [label="whiteSpace"]
+ 4 -> 6 [label="anyAttribute"]
+ 4 -> 4 [label="length"]
+ 4 -> 7 [label="assert"]
+ 4 -> 4 [label="maxExclusive"]
+ 4 -> 4 [label="enumeration"]
+ 4 -> 4 [label="assertion"]
+ 4 -> 4 [label="maxInclusive"]
+ 4 -> 5 [label="attribute"]
+ 4 -> 4 [label="maxLength"]
+ 4 -> 4 [label="pattern"]
+ 4 -> 4 [label="totalDigits"]
+ 4 -> 5 [label="attributeGroup"]
+ 4 -> 4 [label="minExclusive"]
+ 4 -> 4 [label="minInclusive"]
+ 5 -> 6 [label="anyAttribute"]
+ 5 -> 7 [label="assert"]
+ 5 -> 5 [label="attribute"]
+ 5 -> 5 [label="attributeGroup"]
+ 6 -> 7 [label="assert"]
+ 7 -> 7 [label="assert"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+ 5 [shape=doublecircle, style=filled, color=green]
+ 6 [shape=doublecircle, style=filled, color=green]
+ 7 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/SimpleContent_diagram.dot b/src/xmlpatterns/schema/doc/SimpleContent_diagram.dot
new file mode 100644
index 0000000000..c996329ed6
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/SimpleContent_diagram.dot
@@ -0,0 +1,11 @@
+digraph SimpleContent {
+ mindist = 2.0
+ 1 -> 3 [label="restriction"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="extension"]
+ 2 -> 3 [label="restriction"]
+ 2 -> 3 [label="extension"]
+ 1 [shape=circle, style=filled, color=blue]
+ 2 [shape=circle, style=filled, color=red]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/SimpleRestriction_diagram.dot b/src/xmlpatterns/schema/doc/SimpleRestriction_diagram.dot
new file mode 100644
index 0000000000..09cb0419ea
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/SimpleRestriction_diagram.dot
@@ -0,0 +1,62 @@
+digraph SimpleRestriction {
+ mindist = 2.0
+ 1 -> 4 [label="fractionDigits"]
+ 1 -> 4 [label="minLength"]
+ 1 -> 4 [label="whiteSpace"]
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="simpleType"]
+ 1 -> 4 [label="length"]
+ 1 -> 4 [label="maxExclusive"]
+ 1 -> 4 [label="enumeration"]
+ 1 -> 4 [label="assertion"]
+ 1 -> 4 [label="maxInclusive"]
+ 1 -> 4 [label="maxLength"]
+ 1 -> 4 [label="pattern"]
+ 1 -> 4 [label="totalDigits"]
+ 1 -> 4 [label="minExclusive"]
+ 1 -> 4 [label="minInclusive"]
+ 2 -> 4 [label="fractionDigits"]
+ 2 -> 4 [label="minLength"]
+ 2 -> 4 [label="whiteSpace"]
+ 2 -> 3 [label="simpleType"]
+ 2 -> 4 [label="length"]
+ 2 -> 4 [label="maxExclusive"]
+ 2 -> 4 [label="enumeration"]
+ 2 -> 4 [label="assertion"]
+ 2 -> 4 [label="maxInclusive"]
+ 2 -> 4 [label="maxLength"]
+ 2 -> 4 [label="pattern"]
+ 2 -> 4 [label="totalDigits"]
+ 2 -> 4 [label="minExclusive"]
+ 2 -> 4 [label="minInclusive"]
+ 3 -> 4 [label="fractionDigits"]
+ 3 -> 4 [label="minLength"]
+ 3 -> 4 [label="whiteSpace"]
+ 3 -> 4 [label="length"]
+ 3 -> 4 [label="maxExclusive"]
+ 3 -> 4 [label="enumeration"]
+ 3 -> 4 [label="assertion"]
+ 3 -> 4 [label="maxInclusive"]
+ 3 -> 4 [label="maxLength"]
+ 3 -> 4 [label="pattern"]
+ 3 -> 4 [label="totalDigits"]
+ 3 -> 4 [label="minExclusive"]
+ 3 -> 4 [label="minInclusive"]
+ 4 -> 4 [label="fractionDigits"]
+ 4 -> 4 [label="minLength"]
+ 4 -> 4 [label="whiteSpace"]
+ 4 -> 4 [label="length"]
+ 4 -> 4 [label="maxExclusive"]
+ 4 -> 4 [label="enumeration"]
+ 4 -> 4 [label="assertion"]
+ 4 -> 4 [label="maxInclusive"]
+ 4 -> 4 [label="maxLength"]
+ 4 -> 4 [label="pattern"]
+ 4 -> 4 [label="totalDigits"]
+ 4 -> 4 [label="minExclusive"]
+ 4 -> 4 [label="minInclusive"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+ 4 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/TotalDigitsFacet_diagram.dot b/src/xmlpatterns/schema/doc/TotalDigitsFacet_diagram.dot
new file mode 100644
index 0000000000..0ef4cd6e68
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/TotalDigitsFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph TotalDigitsFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Union_diagram.dot b/src/xmlpatterns/schema/doc/Union_diagram.dot
new file mode 100644
index 0000000000..d6c1865efd
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Union_diagram.dot
@@ -0,0 +1,10 @@
+digraph Union {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="simpleType"]
+ 2 -> 3 [label="simpleType"]
+ 3 -> 3 [label="simpleType"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+ 3 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/Unique_diagram.dot b/src/xmlpatterns/schema/doc/Unique_diagram.dot
new file mode 100644
index 0000000000..5b1d098c35
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/Unique_diagram.dot
@@ -0,0 +1,12 @@
+digraph Unique {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 -> 3 [label="selector"]
+ 2 -> 3 [label="selector"]
+ 3 -> 4 [label="field"]
+ 4 -> 4 [label="field"]
+ 1 [shape=circle, style=filled, color=blue]
+ 2 [shape=circle, style=filled, color=red]
+ 3 [shape=circle, style=filled, color=red]
+ 4 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/WhiteSpaceFacet_diagram.dot b/src/xmlpatterns/schema/doc/WhiteSpaceFacet_diagram.dot
new file mode 100644
index 0000000000..596403c5c7
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/WhiteSpaceFacet_diagram.dot
@@ -0,0 +1,6 @@
+digraph WhiteSpaceFacet {
+ mindist = 2.0
+ 1 -> 2 [label="annotation"]
+ 1 [shape=doublecircle, style=filled, color=blue]
+ 2 [shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/doc/legend.dot b/src/xmlpatterns/schema/doc/legend.dot
new file mode 100644
index 0000000000..4f5792ecf1
--- /dev/null
+++ b/src/xmlpatterns/schema/doc/legend.dot
@@ -0,0 +1,7 @@
+digraph {
+ size="5,4"
+ 1 [label=" start state ", shape=circle, style=filled, color=blue]
+ 2 [label="start/end state", shape=doublecircle, style=filled, color=blue]
+ 3 [label=" internal state", shape=circle, style=filled, color=red]
+ 4 [label=" end state ", shape=doublecircle, style=filled, color=green]
+}
diff --git a/src/xmlpatterns/schema/qnamespacesupport.cpp b/src/xmlpatterns/schema/qnamespacesupport.cpp
new file mode 100644
index 0000000000..00698d6638
--- /dev/null
+++ b/src/xmlpatterns/schema/qnamespacesupport.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#include "qnamespacesupport_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+NamespaceSupport::NamespaceSupport()
+{
+}
+
+NamespaceSupport::NamespaceSupport(const NamePool::Ptr &namePool)
+ : m_namePool(namePool)
+{
+ // the XML namespace
+ const QXmlName binding = namePool->allocateBinding(QLatin1String("xml"),
+ QLatin1String("http://www.w3.org/XML/1998/namespace"));
+ m_ns.insert(binding.prefix(), binding.namespaceURI());
+}
+
+void NamespaceSupport::setPrefix(const QXmlName::PrefixCode prefixCode, const QXmlName::NamespaceCode namespaceCode)
+{
+ m_ns.insert(prefixCode, namespaceCode);
+}
+
+void NamespaceSupport::setPrefixes(const QXmlStreamNamespaceDeclarations &declarations)
+{
+ for (int i = 0; i < declarations.count(); i++) {
+ const QXmlStreamNamespaceDeclaration declaration = declarations.at(i);
+
+ const QXmlName::PrefixCode prefixCode = m_namePool->allocatePrefix(declaration.prefix().toString());
+ const QXmlName::NamespaceCode namespaceCode = m_namePool->allocateNamespace(declaration.namespaceUri().toString());
+ m_ns.insert(prefixCode, namespaceCode);
+ }
+}
+
+void NamespaceSupport::setTargetNamespace(const QXmlName::NamespaceCode namespaceCode)
+{
+ m_ns.insert(0, namespaceCode);
+}
+
+QXmlName::PrefixCode NamespaceSupport::prefix(const QXmlName::NamespaceCode namespaceCode) const
+{
+ NamespaceHash::const_iterator itc, it = m_ns.constBegin();
+ while ((itc=it) != m_ns.constEnd()) {
+ ++it;
+ if (*itc == namespaceCode)
+ return itc.key();
+ }
+ return 0;
+}
+
+QXmlName::NamespaceCode NamespaceSupport::uri(const QXmlName::PrefixCode prefixCode) const
+{
+ return m_ns.value(prefixCode);
+}
+
+bool NamespaceSupport::processName(const QString& qname, NameType type, QXmlName &name) const
+{
+ int len = qname.size();
+ const QChar *data = qname.constData();
+ for (int pos = 0; pos < len; ++pos) {
+ if (data[pos] == QLatin1Char(':')) {
+ const QXmlName::PrefixCode prefixCode = m_namePool->allocatePrefix(qname.left(pos));
+ if (!m_ns.contains(prefixCode))
+ return false;
+ const QXmlName::NamespaceCode namespaceCode = uri(prefixCode);
+ const QXmlName::LocalNameCode localNameCode = m_namePool->allocateLocalName(qname.mid(pos + 1));
+ name = QXmlName(namespaceCode, localNameCode, prefixCode);
+ return true;
+ }
+ }
+
+ // there was no ':'
+ QXmlName::NamespaceCode namespaceCode = 0;
+ // attributes don't take default namespace
+ if (type == ElementName && !m_ns.isEmpty()) {
+ namespaceCode = m_ns.value(0); // get default namespace
+ }
+
+ const QXmlName::LocalNameCode localNameCode = m_namePool->allocateLocalName(qname);
+ name = QXmlName(namespaceCode, localNameCode, 0);
+
+ return true;
+}
+
+void NamespaceSupport::pushContext()
+{
+ m_nsStack.push(m_ns);
+}
+
+void NamespaceSupport::popContext()
+{
+ m_ns.clear();
+ if(!m_nsStack.isEmpty())
+ m_ns = m_nsStack.pop();
+}
+
+QList<QXmlName> NamespaceSupport::namespaceBindings() const
+{
+ QList<QXmlName> bindings;
+
+ QHashIterator<QXmlName::PrefixCode, QXmlName::NamespaceCode> it(m_ns);
+ while (it.hasNext()) {
+ it.next();
+ bindings.append(QXmlName(it.value(), StandardLocalNames::empty, it.key()));
+ }
+
+ return bindings;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qnamespacesupport_p.h b/src/xmlpatterns/schema/qnamespacesupport_p.h
new file mode 100644
index 0000000000..d338eaec01
--- /dev/null
+++ b/src/xmlpatterns/schema/qnamespacesupport_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_NamespaceSupport_H
+#define Patternist_NamespaceSupport_H
+
+#include "qnamepool_p.h"
+
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QHash>
+#include <QtCore/QSet>
+#include <QtCore/QStack>
+#include <QtCore/QXmlStreamNamespaceDeclarations>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A helper class for handling nested namespace declarations.
+ *
+ * This class is mostly an adaption of QXmlNamespaceSupport to the NamePool
+ * mechanism used in XmlPatterns.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class NamespaceSupport
+ {
+ public:
+ /**
+ * Describes whether the name to process is an attribute or element.
+ */
+ enum NameType
+ {
+ AttributeName, ///< An attribute name to process.
+ ElementName ///< An element name to process.
+ };
+
+ /**
+ * Creates an empty namespace support object.
+ */
+ NamespaceSupport();
+
+ /**
+ * Creates a new namespace support object.
+ *
+ * @param namePool The name pool where all processed names are stored in.
+ */
+ NamespaceSupport(const NamePool::Ptr &namePool);
+
+ /**
+ * Adds a new prefix-to-namespace binding.
+ *
+ * @param prefixCode The name pool code for the prefix.
+ * @param namespaceCode The name pool code for the namespace.
+ */
+ void setPrefix(const QXmlName::PrefixCode prefixCode, const QXmlName::NamespaceCode namespaceCode);
+
+ /**
+ * Adds the prefix-to-namespace bindings from @p declarations to
+ * the namespace support.
+ */
+ void setPrefixes(const QXmlStreamNamespaceDeclarations &declarations);
+
+ /**
+ * Sets the name pool code of the target namespace of the schema the
+ * namespace support works on.
+ */
+ void setTargetNamespace(const QXmlName::NamespaceCode code);
+
+ /**
+ * Returns the prefix code for the given namespace @p code.
+ */
+ QXmlName::PrefixCode prefix(const QXmlName::NamespaceCode code) const;
+
+ /**
+ * Returns the namespace code for the given prefix @p code.
+ */
+ QXmlName::NamespaceCode uri(const QXmlName::PrefixCode code) const;
+
+ /**
+ * Converts the given @p qualifiedName to a resolved QXmlName @p name according
+ * to the current namespace mapping.
+ *
+ * @param qualifiedName The full qualified name.
+ * @param type The type of name processing.
+ * @param name The resolved QXmlName.
+ *
+ * @returns @c true if the name could be processed correctly or @c false if the
+ * namespace prefix is unknown.
+ */
+ bool processName(const QString &qualifiedName, NameType type, QXmlName &name) const;
+
+ /**
+ * Pushes the current namespace mapping onto the stack.
+ */
+ void pushContext();
+
+ /**
+ * Pops the current namespace mapping from the stack.
+ */
+ void popContext();
+
+ /**
+ * Returns the list of namespace bindings.
+ */
+ QList<QXmlName> namespaceBindings() const;
+
+ private:
+ typedef QHash<QXmlName::PrefixCode, QXmlName::NamespaceCode> NamespaceHash;
+
+ NamePool::Ptr m_namePool;
+ QStack<NamespaceHash> m_nsStack;
+ NamespaceHash m_ns;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdalternative.cpp b/src/xmlpatterns/schema/qxsdalternative.cpp
new file mode 100644
index 0000000000..f3f589a08b
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdalternative.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdalternative_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdAlternative::setTest(const XsdXPathExpression::Ptr &test)
+{
+ m_test = test;
+}
+
+XsdXPathExpression::Ptr XsdAlternative::test() const
+{
+ return m_test;
+}
+
+void XsdAlternative::setType(const SchemaType::Ptr &type)
+{
+ m_type = type;
+}
+
+SchemaType::Ptr XsdAlternative::type() const
+{
+ return m_type;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdalternative_p.h b/src/xmlpatterns/schema/qxsdalternative_p.h
new file mode 100644
index 0000000000..451441e02e
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdalternative_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdAlternative_H
+#define Patternist_XsdAlternative_H
+
+#include "qnamedschemacomponent_p.h"
+#include "qschematype_p.h"
+#include "qxsdannotated_p.h"
+#include "qxsdxpathexpression_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD alternative object.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdAlternative : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdAlternative> Ptr;
+ typedef QList<XsdAlternative::Ptr> List;
+
+ /**
+ * Sets the xpath @p test of the alternative.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#tac-test">Test Definition</a>
+ */
+ void setTest(const XsdXPathExpression::Ptr &test);
+
+ /**
+ * Returns the xpath test of the alternative.
+ */
+ XsdXPathExpression::Ptr test() const;
+
+ /**
+ * Sets the @p type of the alternative.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#tac-type_definition">Type Definition</a>
+ */
+ void setType(const SchemaType::Ptr &type);
+
+ /**
+ * Returns the type of the alternative.
+ */
+ SchemaType::Ptr type() const;
+
+ private:
+ XsdXPathExpression::Ptr m_test;
+ SchemaType::Ptr m_type;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdannotated.cpp b/src/xmlpatterns/schema/qxsdannotated.cpp
new file mode 100644
index 0000000000..a29b5c45ad
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdannotated.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdannotated_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdAnnotated::addAnnotation(const XsdAnnotation::Ptr &annotation)
+{
+ m_annotations.append(annotation);
+}
+
+void XsdAnnotated::addAnnotations(const XsdAnnotation::List &annotations)
+{
+ m_annotations << annotations;
+}
+
+XsdAnnotation::List XsdAnnotated::annotations() const
+{
+ return m_annotations;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdannotated_p.h b/src/xmlpatterns/schema/qxsdannotated_p.h
new file mode 100644
index 0000000000..251b252172
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdannotated_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdAnnotated_H
+#define Patternist_XsdAnnotated_H
+
+#include "qxsdannotation_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Base class for all XSD components with annotation content.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdAnnotated
+ {
+ public:
+ /**
+ * Adds a new @p annotation to the component.
+ */
+ void addAnnotation(const XsdAnnotation::Ptr &annotation);
+
+ /**
+ * Adds a list of new @p annotations to the component.
+ */
+ void addAnnotations(const XsdAnnotation::List &annotations);
+
+ /**
+ * Returns the list of all annotations of the component.
+ */
+ XsdAnnotation::List annotations() const;
+
+ private:
+ XsdAnnotation::List m_annotations;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdannotation.cpp b/src/xmlpatterns/schema/qxsdannotation.cpp
new file mode 100644
index 0000000000..0a9dc04e99
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdannotation.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdannotation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdAnnotation::setId(const DerivedString<TypeID>::Ptr &id)
+{
+ m_id = id;
+}
+
+DerivedString<TypeID>::Ptr XsdAnnotation::id() const
+{
+ return m_id;
+}
+
+void XsdAnnotation::addApplicationInformation(const XsdApplicationInformation::Ptr &information)
+{
+ m_applicationInformation.append(information);
+}
+
+XsdApplicationInformation::List XsdAnnotation::applicationInformation() const
+{
+ return m_applicationInformation;
+}
+
+void XsdAnnotation::addDocumentation(const XsdDocumentation::Ptr &documentation)
+{
+ m_documentations.append(documentation);
+}
+
+XsdDocumentation::List XsdAnnotation::documentation() const
+{
+ return m_documentations;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdannotation_p.h b/src/xmlpatterns/schema/qxsdannotation_p.h
new file mode 100644
index 0000000000..8c23bae1ef
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdannotation_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdAnnotation_H
+#define Patternist_XsdAnnotation_H
+
+#include "qderivedstring_p.h"
+#include "qxsdapplicationinformation_p.h"
+#include "qxsddocumentation_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD annotation object.
+ *
+ * This class represents the <em>annotation</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#cAnnotations">here</a>.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdAnnotation : public NamedSchemaComponent
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdAnnotation> Ptr;
+ typedef QList<XsdAnnotation::Ptr> List;
+
+ /**
+ * Sets the @p id of the annotation.
+ */
+ void setId(const DerivedString<TypeID>::Ptr &id);
+
+ /**
+ * Returns the @p id of the annotation.
+ */
+ DerivedString<TypeID>::Ptr id() const;
+
+ /**
+ * Adds an application @p information to the annotation.
+ *
+ * The application information is meant to be interpreted by
+ * a software system, e.g. other parts of the XML processor pipeline.
+ */
+ void addApplicationInformation(const XsdApplicationInformation::Ptr &information);
+
+ /**
+ * Returns the list of all application information of the annotation.
+ */
+ XsdApplicationInformation::List applicationInformation() const;
+
+ /**
+ * Adds a @p documentation to the annotation.
+ *
+ * The documentation is meant to be read by human being, e.g. additional
+ * constraints or information about schema components.
+ */
+ void addDocumentation(const XsdDocumentation::Ptr &documentation);
+
+ /**
+ * Returns the list of all documentations of the annotation.
+ */
+ XsdDocumentation::List documentation() const;
+
+ private:
+ DerivedString<TypeID>::Ptr m_id;
+ XsdApplicationInformation::List m_applicationInformation;
+ XsdDocumentation::List m_documentations;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdapplicationinformation.cpp b/src/xmlpatterns/schema/qxsdapplicationinformation.cpp
new file mode 100644
index 0000000000..56692207a1
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdapplicationinformation.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdapplicationinformation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdApplicationInformation::setSource(const AnyURI::Ptr &source)
+{
+ m_source = source;
+}
+
+AnyURI::Ptr XsdApplicationInformation::source() const
+{
+ return m_source;
+}
+
+void XsdApplicationInformation::setContent(const QString &content)
+{
+ m_content = content;
+}
+
+QString XsdApplicationInformation::content() const
+{
+ return m_content;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdapplicationinformation_p.h b/src/xmlpatterns/schema/qxsdapplicationinformation_p.h
new file mode 100644
index 0000000000..30839d3532
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdapplicationinformation_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdApplicationInformation_H
+#define Patternist_XsdApplicationInformation_H
+
+#include "qanytype_p.h"
+#include "qanyuri_p.h"
+#include "qnamedschemacomponent_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD appinfo object.
+ *
+ * This class represents the <em>appinfo</em> component of an <em>annotation</em> object
+ * of a XML schema as described <a href="http://www.w3.org/TR/xmlschema11-1/#cAnnotations">here</a>.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdApplicationInformation : public NamedSchemaComponent
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdApplicationInformation> Ptr;
+ typedef QList<XsdApplicationInformation::Ptr> List;
+
+ /**
+ * Sets the @p source of the application information.
+ *
+ * The source points to an URL that contains more
+ * information.
+ */
+ void setSource(const AnyURI::Ptr &source);
+
+ /**
+ * Returns the source of the application information.
+ */
+ AnyURI::Ptr source() const;
+
+ /**
+ * Sets the @p content of the application information.
+ *
+ * The content can be of abritrary type.
+ */
+ void setContent(const QString &content);
+
+ /**
+ * Returns the content of the application information.
+ */
+ QString content() const;
+
+ private:
+ AnyURI::Ptr m_source;
+ QString m_content;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdassertion.cpp b/src/xmlpatterns/schema/qxsdassertion.cpp
new file mode 100644
index 0000000000..f6cbf818c1
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdassertion.cpp
@@ -0,0 +1,28 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdassertion_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdAssertion::setTest(const XsdXPathExpression::Ptr &test)
+{
+ m_test = test;
+}
+
+XsdXPathExpression::Ptr XsdAssertion::test() const
+{
+ return m_test;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdassertion_p.h b/src/xmlpatterns/schema/qxsdassertion_p.h
new file mode 100644
index 0000000000..0ae5ff6f31
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdassertion_p.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdAssertion_H
+#define Patternist_XsdAssertion_H
+
+#include "qnamedschemacomponent_p.h"
+#include "qxsdannotated_p.h"
+#include "qxsdxpathexpression_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD assertion object.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#cAssertions">Assertion Definition</a>
+ */
+ class XsdAssertion : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdAssertion> Ptr;
+ typedef QList<XsdAssertion::Ptr> List;
+
+ /**
+ * Sets the @p test of the assertion.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#as-test">Test Definition</a>
+ */
+ void setTest(const XsdXPathExpression::Ptr &test);
+
+ /**
+ * Returns the test of the assertion.
+ */
+ XsdXPathExpression::Ptr test() const;
+
+ private:
+ XsdXPathExpression::Ptr m_test;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdattribute.cpp b/src/xmlpatterns/schema/qxsdattribute.cpp
new file mode 100644
index 0000000000..6cf60ec904
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattribute.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdattribute_p.h"
+#include "qxsdcomplextype_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+
+void XsdAttribute::Scope::setVariety(Variety variety)
+{
+ m_variety = variety;
+}
+
+XsdAttribute::Scope::Variety XsdAttribute::Scope::variety() const
+{
+ return m_variety;
+}
+
+void XsdAttribute::Scope::setParent(const NamedSchemaComponent::Ptr &parent)
+{
+ m_parent = parent;
+}
+
+NamedSchemaComponent::Ptr XsdAttribute::Scope::parent() const
+{
+ return m_parent;
+}
+
+void XsdAttribute::ValueConstraint::setVariety(Variety variety)
+{
+ m_variety = variety;
+}
+
+XsdAttribute::ValueConstraint::Variety XsdAttribute::ValueConstraint::variety() const
+{
+ return m_variety;
+}
+
+void XsdAttribute::ValueConstraint::setValue(const QString &value)
+{
+ m_value = value;
+}
+
+QString XsdAttribute::ValueConstraint::value() const
+{
+ return m_value;
+}
+
+void XsdAttribute::ValueConstraint::setLexicalForm(const QString &form)
+{
+ m_lexicalForm = form;
+}
+
+QString XsdAttribute::ValueConstraint::lexicalForm() const
+{
+ return m_lexicalForm;
+}
+
+void XsdAttribute::setType(const AnySimpleType::Ptr &type)
+{
+ m_type = type;
+}
+
+AnySimpleType::Ptr XsdAttribute::type() const
+{
+ return m_type;
+}
+
+void XsdAttribute::setScope(const Scope::Ptr &scope)
+{
+ m_scope = scope;
+}
+
+XsdAttribute::Scope::Ptr XsdAttribute::scope() const
+{
+ return m_scope;
+}
+
+void XsdAttribute::setValueConstraint(const ValueConstraint::Ptr &constraint)
+{
+ m_valueConstraint = constraint;
+}
+
+XsdAttribute::ValueConstraint::Ptr XsdAttribute::valueConstraint() const
+{
+ return m_valueConstraint;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdattribute_p.h b/src/xmlpatterns/schema/qxsdattribute_p.h
new file mode 100644
index 0000000000..46d73559f2
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattribute_p.h
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdAttribute_H
+#define Patternist_XsdAttribute_H
+
+#include "qanysimpletype_p.h"
+#include "qnamedschemacomponent_p.h"
+#include "qxsdannotated_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD attribute object.
+ *
+ * This class represents the <em>attribute</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#cAttribute_Declarations">here</a>.
+ *
+ * It contains information from either a top-level attribute declaration (as child of
+ * a <em>schema</em> object) or of a local attribute declaration (as child of <em>complexType</em>
+ * or <em>attributeGroup</em> object without a 'ref' attribute).
+ *
+ * All other occurrences of the <em>attribute</em> object are represented by the XsdAttributeUse class.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSAttributeDeclaration">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdAttribute : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdAttribute> Ptr;
+ typedef QList<XsdAttribute::Ptr> List;
+
+ /**
+ * @short Describes the scope of an attribute.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#sc_a">Scope Definition</a>
+ */
+ class Scope : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<Scope> Ptr;
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#ad-scope">scope</a> of an attribute.
+ */
+ enum Variety
+ {
+ Global, ///< The attribute is defined globally as child of the <em>schema</em> object.
+ Local ///< The attribute is defined locally as child of a complex type or attribute group definition.
+ };
+
+ /**
+ * Sets the @p variety of the attribute scope.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#sc_a-variety">Variety Definition</a>
+ */
+ void setVariety(Variety variety);
+
+ /**
+ * Returns the variety of the attribute scope.
+ */
+ Variety variety() const;
+
+ /**
+ * Sets the @p parent complex type or attribute group definition of the attribute scope.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#sc_a-parent">Parent Definition</a>
+ */
+ void setParent(const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * Returns the parent complex type or attribute group definition of the attribute scope.
+ */
+ NamedSchemaComponent::Ptr parent() const;
+
+ private:
+ Variety m_variety;
+ NamedSchemaComponent::Ptr m_parent;
+ };
+
+
+ /**
+ * @short Describes the value constraint of an attribute.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#vc_a">Value Constraint Definition</a>
+ */
+ class ValueConstraint : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<ValueConstraint> Ptr;
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#ad-value_constraint">value constraint</a> of an attribute.
+ */
+ enum Variety
+ {
+ Default, ///< The attribute has a default value set.
+ Fixed ///< The attribute has a fixed value set.
+ };
+
+ /**
+ * Sets the @p variety of the attribute value constraint.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#vc_a-variety">Variety Definition</a>
+ */
+ void setVariety(Variety variety);
+
+ /**
+ * Returns the variety of the attribute value constraint.
+ */
+ Variety variety() const;
+
+ /**
+ * Sets the @p value of the constraint.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#vc_a-value">Value Definition</a>
+ */
+ void setValue(const QString &value);
+
+ /**
+ * Returns the value of the constraint.
+ */
+ QString value() const;
+
+ /**
+ * Sets the lexical @p form of the constraint.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#vc_a-lexical_form">Lexical Form Definition</a>
+ */
+ void setLexicalForm(const QString &form);
+
+ /**
+ * Returns the lexical form of the constraint.
+ */
+ QString lexicalForm() const;
+
+ private:
+ Variety m_variety;
+ QString m_value;
+ QString m_lexicalForm;
+ };
+
+ /**
+ * Sets the simple @p type definition of the attribute.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ad-type_definition">Simple Type Definition</a>
+ */
+ void setType(const AnySimpleType::Ptr &type);
+
+ /**
+ * Returns the simple type definition of the attribute.
+ */
+ AnySimpleType::Ptr type() const;
+
+ /**
+ * Sets the @p scope of the attribute.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ad-scope">Scope Definition</a>
+ */
+ void setScope(const Scope::Ptr &scope);
+
+ /**
+ * Returns the scope of the attribute.
+ */
+ Scope::Ptr scope() const;
+
+ /**
+ * Sets the value @p constraint of the attribute.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ad-value_constraint">Value Constraint Definition</a>
+ */
+ void setValueConstraint(const ValueConstraint::Ptr &constraint);
+
+ /**
+ * Returns the value constraint of the attribute.
+ */
+ ValueConstraint::Ptr valueConstraint() const;
+
+ private:
+ AnySimpleType::Ptr m_type;
+ Scope::Ptr m_scope;
+ ValueConstraint::Ptr m_valueConstraint;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdattributegroup.cpp b/src/xmlpatterns/schema/qxsdattributegroup.cpp
new file mode 100644
index 0000000000..8f2a47ed2b
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattributegroup.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdattributegroup_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdAttributeGroup::setAttributeUses(const XsdAttributeUse::List &attributeUses)
+{
+ m_attributeUses = attributeUses;
+}
+
+void XsdAttributeGroup::addAttributeUse(const XsdAttributeUse::Ptr &attributeUse)
+{
+ m_attributeUses.append(attributeUse);
+}
+
+XsdAttributeUse::List XsdAttributeGroup::attributeUses() const
+{
+ return m_attributeUses;
+}
+
+void XsdAttributeGroup::setWildcard(const XsdWildcard::Ptr &wildcard)
+{
+ m_wildcard = wildcard;
+}
+
+XsdWildcard::Ptr XsdAttributeGroup::wildcard() const
+{
+ return m_wildcard;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdattributegroup_p.h b/src/xmlpatterns/schema/qxsdattributegroup_p.h
new file mode 100644
index 0000000000..7a3bd793b2
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattributegroup_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdAttributeGroup_H
+#define Patternist_XsdAttributeGroup_H
+
+#include "qxsdannotated_p.h"
+#include "qxsdattributeuse_p.h"
+#include "qxsdwildcard_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents the XSD attributeGroup object.
+ *
+ * This class represents the <em>attributeGroup</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#cAttribute_Group_Definitions">here</a>.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSAttributeGroup">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdAttributeGroup : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdAttributeGroup> Ptr;
+ typedef QList<XsdAttributeGroup::Ptr> List;
+
+ /**
+ * Sets the list of attribute @p uses that are defined in the attribute group.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#agd-attribute_uses">Attribute Uses</a>
+ */
+ void setAttributeUses(const XsdAttributeUse::List &uses);
+
+ /**
+ * Adds a new attribute @p use to the attribute group.
+ */
+ void addAttributeUse(const XsdAttributeUse::Ptr &use);
+
+ /**
+ * Returns the list of all attribute uses of the attribute group.
+ */
+ XsdAttributeUse::List attributeUses() const;
+
+ /**
+ * Sets the attribute @p wildcard of the attribute group.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#agd-attribute_wildcard">Attribute Wildcard</a>
+ */
+ void setWildcard(const XsdWildcard::Ptr &wildcard);
+
+ /**
+ * Returns the attribute wildcard of the attribute group.
+ */
+ XsdWildcard::Ptr wildcard() const;
+
+ private:
+ XsdAttributeUse::List m_attributeUses;
+ XsdWildcard::Ptr m_wildcard;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdattributereference.cpp b/src/xmlpatterns/schema/qxsdattributereference.cpp
new file mode 100644
index 0000000000..3c36a4e40a
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattributereference.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdattributereference_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+bool XsdAttributeReference::isAttributeUse() const
+{
+ return false;
+}
+
+bool XsdAttributeReference::isReference() const
+{
+ return true;
+}
+
+void XsdAttributeReference::setType(Type type)
+{
+ m_type = type;
+}
+
+XsdAttributeReference::Type XsdAttributeReference::type() const
+{
+ return m_type;
+}
+
+void XsdAttributeReference::setReferenceName(const QXmlName &referenceName)
+{
+ m_referenceName = referenceName;
+}
+
+QXmlName XsdAttributeReference::referenceName() const
+{
+ return m_referenceName;
+}
+
+void XsdAttributeReference::setSourceLocation(const QSourceLocation &location)
+{
+ m_sourceLocation = location;
+}
+
+QSourceLocation XsdAttributeReference::sourceLocation() const
+{
+ return m_sourceLocation;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdattributereference_p.h b/src/xmlpatterns/schema/qxsdattributereference_p.h
new file mode 100644
index 0000000000..be48b3a8b1
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattributereference_p.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdAttributeReference_H
+#define Patternist_XsdAttributeReference_H
+
+#include "qxsdattributeuse_p.h"
+
+#include <QtXmlPatterns/QSourceLocation>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A helper class for attribute reference resolving.
+ *
+ * For easy resolving of attribute references, we have this class
+ * that can be used as a place holder for the real attribute use
+ * object it is referring to.
+ * So whenever the parser detects an attribute reference, it creates
+ * a XsdAttributeReference and returns it instead of the XsdAttributeUse.
+ * During a later phase, the resolver will look for all XsdAttributeReferences
+ * in the schema and will replace them with their referring XsdAttributeUse
+ * objects.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdAttributeReference : public XsdAttributeUse
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdAttributeReference> Ptr;
+
+ /**
+ * Describes the type of the attribute reference.
+ */
+ enum Type
+ {
+ AttributeUse, ///< The reference points to an attribute use.
+ AttributeGroup ///< The reference points to an attribute group.
+ };
+
+ /**
+ * Always returns false, used to avoid dynamic casts.
+ */
+ virtual bool isAttributeUse() const;
+
+ /**
+ * Always returns true, used to avoid dynamic casts.
+ */
+ virtual bool isReference() const;
+
+ /**
+ * Sets the @p type of the attribute reference.
+ */
+ void setType(Type type);
+
+ /**
+ * Returns the type of the attribute reference.
+ */
+ Type type() const;
+
+ /**
+ * Sets the @p name of the attribute or attribute group the
+ * attribute reference refers to.
+ */
+ void setReferenceName(const QXmlName &name);
+
+ /**
+ * Returns the name of the attribute or attribute group the
+ * attribute reference refers to.
+ */
+ QXmlName referenceName() const;
+
+ /**
+ * Sets the source @p location where the reference is located.
+ */
+ void setSourceLocation(const QSourceLocation &location);
+
+ /**
+ * Returns the source location where the reference is located.
+ */
+ QSourceLocation sourceLocation() const;
+
+ private:
+ Type m_type;
+ QXmlName m_referenceName;
+ QSourceLocation m_sourceLocation;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdattributeterm.cpp b/src/xmlpatterns/schema/qxsdattributeterm.cpp
new file mode 100644
index 0000000000..a9c389891a
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattributeterm.cpp
@@ -0,0 +1,28 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdattributeterm_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+bool XsdAttributeTerm::isAttributeUse() const
+{
+ return false;
+}
+
+bool XsdAttributeTerm::isReference() const
+{
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdattributeterm_p.h b/src/xmlpatterns/schema/qxsdattributeterm_p.h
new file mode 100644
index 0000000000..507df320aa
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattributeterm_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdAttributeTerm_H
+#define Patternist_XsdAttributeTerm_H
+
+#include "qnamedschemacomponent_p.h"
+#include "qxsdannotated_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A base class for all attribute types.
+ *
+ * For easy resolving of attribute references, we use this as
+ * common base class for XsdAttribute and XsdAttributeReference.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdAttributeTerm : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdAttributeTerm> Ptr;
+
+ /**
+ * Returns @c true if the term is an attribute use, @c false otherwise.
+ */
+ virtual bool isAttributeUse() const;
+
+ /**
+ * Returns @c true if the term is an attribute use reference, @c false otherwise.
+ *
+ * @note The reference term is only used internally as helper during type resolving.
+ */
+ virtual bool isReference() const;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdattributeuse.cpp b/src/xmlpatterns/schema/qxsdattributeuse.cpp
new file mode 100644
index 0000000000..96d81bcef8
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattributeuse.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdattributeuse_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdAttributeUse::ValueConstraint::setVariety(Variety variety)
+{
+ m_variety = variety;
+}
+
+XsdAttributeUse::ValueConstraint::Variety XsdAttributeUse::ValueConstraint::variety() const
+{
+ return m_variety;
+}
+
+void XsdAttributeUse::ValueConstraint::setValue(const QString &value)
+{
+ m_value = value;
+}
+
+QString XsdAttributeUse::ValueConstraint::value() const
+{
+ return m_value;
+}
+
+void XsdAttributeUse::ValueConstraint::setLexicalForm(const QString &form)
+{
+ m_lexicalForm = form;
+}
+
+QString XsdAttributeUse::ValueConstraint::lexicalForm() const
+{
+ return m_lexicalForm;
+}
+
+XsdAttributeUse::ValueConstraint::Ptr XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(const XsdAttribute::ValueConstraint::Ptr &constraint)
+{
+ XsdAttributeUse::ValueConstraint::Ptr newConstraint(new XsdAttributeUse::ValueConstraint());
+ switch (constraint->variety()) {
+ case XsdAttribute::ValueConstraint::Fixed: newConstraint->setVariety(Fixed); break;
+ case XsdAttribute::ValueConstraint::Default: newConstraint->setVariety(Default); break;
+ }
+ newConstraint->setValue(constraint->value());
+ newConstraint->setLexicalForm(constraint->lexicalForm());
+
+ return newConstraint;
+}
+
+XsdAttributeUse::XsdAttributeUse()
+ : m_useType(OptionalUse)
+{
+}
+
+bool XsdAttributeUse::isAttributeUse() const
+{
+ return true;
+}
+
+void XsdAttributeUse::setUseType(UseType type)
+{
+ m_useType = type;
+}
+
+XsdAttributeUse::UseType XsdAttributeUse::useType() const
+{
+ return m_useType;
+}
+
+bool XsdAttributeUse::isRequired() const
+{
+ return (m_useType == RequiredUse);
+}
+
+void XsdAttributeUse::setAttribute(const XsdAttribute::Ptr &attribute)
+{
+ m_attribute = attribute;
+}
+
+XsdAttribute::Ptr XsdAttributeUse::attribute() const
+{
+ return m_attribute;
+}
+
+void XsdAttributeUse::setValueConstraint(const ValueConstraint::Ptr &constraint)
+{
+ m_valueConstraint = constraint;
+}
+
+XsdAttributeUse::ValueConstraint::Ptr XsdAttributeUse::valueConstraint() const
+{
+ return m_valueConstraint;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdattributeuse_p.h b/src/xmlpatterns/schema/qxsdattributeuse_p.h
new file mode 100644
index 0000000000..86021e11ad
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdattributeuse_p.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdAttributeUse_H
+#define Patternist_XsdAttributeUse_H
+
+#include "qxsdattribute_p.h"
+#include "qxsdattributeterm_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD attribute use object.
+ *
+ * This class represents the <em>attribute use</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#cAttributeUse">here</a>.
+ *
+ * It contains information from a local attribute declaration (as child of <em>complexType</em>
+ * or <em>attributeGroup</em> object).
+ *
+ * All other occurrences of the <em>attribute</em> object are represented by the XsdAttribute class.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSAttributeUse">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdAttributeUse : public XsdAttributeTerm
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdAttributeUse> Ptr;
+ typedef QList<XsdAttributeUse::Ptr> List;
+
+ /**
+ * Describes the value constraint of an attribute use.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#vc_au">Value Constraint Definition</a>
+ */
+ class ValueConstraint : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<ValueConstraint> Ptr;
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#au-value_constraint">value constraint</a> of an attribute use.
+ */
+ enum Variety
+ {
+ Default, ///< The attribute use has a default value set.
+ Fixed ///< The attribute use has a fixed value set.
+ };
+
+ /**
+ * Sets the @p variety of the attribute use value constraint.
+ */
+ void setVariety(Variety variety);
+
+ /**
+ * Returns the variety of the attribute use value constraint.
+ */
+ Variety variety() const;
+
+ /**
+ * Sets the @p value of the constraint.
+ */
+ void setValue(const QString &value);
+
+ /**
+ * Returns the value of the constraint.
+ */
+ QString value() const;
+
+ /**
+ * Sets the lexical @p form of the constraint.
+ */
+ void setLexicalForm(const QString &form);
+
+ /**
+ * Returns the lexical form of the constraint.
+ */
+ QString lexicalForm() const;
+
+ /**
+ * Creates a new value constraint from a XsdAttribute::ValueConstraint.
+ */
+ static ValueConstraint::Ptr fromAttributeValueConstraint(const XsdAttribute::ValueConstraint::Ptr &constraint);
+
+ private:
+ Variety m_variety;
+ QString m_value;
+ QString m_lexicalForm;
+ };
+
+ /**
+ * Describes the use type of the attribute use.
+ */
+ enum UseType
+ {
+ OptionalUse, ///< The attribute can be there but doesn't need to.
+ RequiredUse, ///< The attribute must be there.
+ ProhibitedUse ///< The attribute is not allowed to be there.
+ };
+
+ /**
+ * Creates a new attribute use object.
+ */
+ XsdAttributeUse();
+
+ /**
+ * Always returns true, used to avoid dynamic casts.
+ */
+ virtual bool isAttributeUse() const;
+
+ /**
+ * Sets the use @p type of the attribute use.
+ *
+ * @see UseType
+ */
+ void setUseType(UseType type);
+
+ /**
+ * Returns the use type of the attribute use.
+ */
+ UseType useType() const;
+
+ /**
+ * Returns whether the attribute use is required.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#au-required">Required Definition</a>
+ */
+ bool isRequired() const;
+
+ /**
+ * Sets the @p attribute the attribute use is referring to.
+ * That is either a local definition as child of a complexType
+ * or attributeGroup object, or a reference defined by the
+ * 'ref' attribute.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#au-attribute_declaration">Attribute Declaration</a>
+ */
+ void setAttribute(const XsdAttribute::Ptr &attribute);
+
+ /**
+ * Returns the attribute the attribute use is referring to.
+ */
+ XsdAttribute::Ptr attribute() const;
+
+ /**
+ * Sets the value @p constraint of the attribute use.
+ *
+ * @see http://www.w3.org/TR/xmlschema11-1/#vc_au
+ */
+ void setValueConstraint(const ValueConstraint::Ptr &constraint);
+
+ /**
+ * Returns the value constraint of the attribute use.
+ */
+ ValueConstraint::Ptr valueConstraint() const;
+
+ private:
+ UseType m_useType;
+ XsdAttribute::Ptr m_attribute;
+ ValueConstraint::Ptr m_valueConstraint;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdcomplextype.cpp b/src/xmlpatterns/schema/qxsdcomplextype.cpp
new file mode 100644
index 0000000000..ddc91107fa
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdcomplextype.cpp
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdcomplextype_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdComplexType::OpenContent::setMode(Mode mode)
+{
+ m_mode = mode;
+}
+
+XsdComplexType::OpenContent::Mode XsdComplexType::OpenContent::mode() const
+{
+ return m_mode;
+}
+
+void XsdComplexType::OpenContent::setWildcard(const XsdWildcard::Ptr &wildcard)
+{
+ m_wildcard = wildcard;
+}
+
+XsdWildcard::Ptr XsdComplexType::OpenContent::wildcard() const
+{
+ return m_wildcard;
+}
+
+void XsdComplexType::ContentType::setVariety(Variety variety)
+{
+ m_variety = variety;
+}
+
+XsdComplexType::ContentType::Variety XsdComplexType::ContentType::variety() const
+{
+ return m_variety;
+}
+
+void XsdComplexType::ContentType::setParticle(const XsdParticle::Ptr &particle)
+{
+ m_particle = particle;
+}
+
+XsdParticle::Ptr XsdComplexType::ContentType::particle() const
+{
+ return m_particle;
+}
+
+void XsdComplexType::ContentType::setOpenContent(const OpenContent::Ptr &content)
+{
+ m_openContent = content;
+}
+
+XsdComplexType::OpenContent::Ptr XsdComplexType::ContentType::openContent() const
+{
+ return m_openContent;
+}
+
+void XsdComplexType::ContentType::setSimpleType(const AnySimpleType::Ptr &type)
+{
+ m_simpleType = type;
+}
+
+AnySimpleType::Ptr XsdComplexType::ContentType::simpleType() const
+{
+ return m_simpleType;
+}
+
+
+XsdComplexType::XsdComplexType()
+ : m_isAbstract(false)
+ , m_contentType(new ContentType())
+{
+ m_contentType->setVariety(ContentType::Empty);
+}
+
+void XsdComplexType::setIsAbstract(bool abstract)
+{
+ m_isAbstract = abstract;
+}
+
+bool XsdComplexType::isAbstract() const
+{
+ return m_isAbstract;
+}
+
+QString XsdComplexType::displayName(const NamePool::Ptr &np) const
+{
+ return np->displayName(name(np));
+}
+
+void XsdComplexType::setWxsSuperType(const SchemaType::Ptr &type)
+{
+ m_superType = type;
+}
+
+SchemaType::Ptr XsdComplexType::wxsSuperType() const
+{
+ return m_superType;
+}
+
+void XsdComplexType::setContext(const NamedSchemaComponent::Ptr &component)
+{
+ m_context = component;
+}
+
+NamedSchemaComponent::Ptr XsdComplexType::context() const
+{
+ return m_context;
+}
+
+void XsdComplexType::setContentType(const ContentType::Ptr &type)
+{
+ m_contentType = type;
+}
+
+XsdComplexType::ContentType::Ptr XsdComplexType::contentType() const
+{
+ return m_contentType;
+}
+
+void XsdComplexType::setAttributeUses(const XsdAttributeUse::List &attributeUses)
+{
+ m_attributeUses = attributeUses;
+}
+
+void XsdComplexType::addAttributeUse(const XsdAttributeUse::Ptr &attributeUse)
+{
+ m_attributeUses.append(attributeUse);
+}
+
+XsdAttributeUse::List XsdComplexType::attributeUses() const
+{
+ return m_attributeUses;
+}
+
+void XsdComplexType::setAttributeWildcard(const XsdWildcard::Ptr &wildcard)
+{
+ m_attributeWildcard = wildcard;
+}
+
+XsdWildcard::Ptr XsdComplexType::attributeWildcard() const
+{
+ return m_attributeWildcard;
+}
+
+XsdComplexType::TypeCategory XsdComplexType::category() const
+{
+ return ComplexType;
+}
+
+void XsdComplexType::setDerivationMethod(DerivationMethod method)
+{
+ m_derivationMethod = method;
+}
+
+XsdComplexType::DerivationMethod XsdComplexType::derivationMethod() const
+{
+ return m_derivationMethod;
+}
+
+void XsdComplexType::setProhibitedSubstitutions(const BlockingConstraints &substitutions)
+{
+ m_prohibitedSubstitutions = substitutions;
+}
+
+XsdComplexType::BlockingConstraints XsdComplexType::prohibitedSubstitutions() const
+{
+ return m_prohibitedSubstitutions;
+}
+
+void XsdComplexType::setAssertions(const XsdAssertion::List &assertions)
+{
+ m_assertions = assertions;
+}
+
+void XsdComplexType::addAssertion(const XsdAssertion::Ptr &assertion)
+{
+ m_assertions.append(assertion);
+}
+
+XsdAssertion::List XsdComplexType::assertions() const
+{
+ return m_assertions;
+}
+
+bool XsdComplexType::isDefinedBySchema() const
+{
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdcomplextype_p.h b/src/xmlpatterns/schema/qxsdcomplextype_p.h
new file mode 100644
index 0000000000..078c8f0449
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdcomplextype_p.h
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdComplexType_H
+#define Patternist_XsdComplexType_H
+
+#include "qanytype_p.h"
+#include "qxsdassertion_p.h"
+#include "qxsdattributeuse_p.h"
+#include "qxsdparticle_p.h"
+#include "qxsdsimpletype_p.h"
+#include "qxsduserschematype_p.h"
+#include "qxsdwildcard_p.h"
+
+#include <QtCore/QSet>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD complexType object.
+ *
+ * This class represents the <em>complexType</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#Complex_Type_Definitions">here</a>.
+ *
+ * It contains information from either a top-level complex type declaration (as child of a <em>schema</em> object)
+ * or a local complex type declaration (as descendant of an <em>element</em> object).
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSComplexType">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdComplexType : public XsdUserSchemaType<AnyType>
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdComplexType> Ptr;
+
+ /**
+ * @short Describes the open content object of a complex type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ct-open_content">Open Content Definition</a>
+ */
+ class OpenContent : public QSharedData, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<OpenContent> Ptr;
+
+ /**
+ * Describes the mode of the open content.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#oc-mode">Mode Definition</a>
+ */
+ enum Mode
+ {
+ None,
+ Interleave,
+ Suffix
+ };
+
+ /**
+ * Sets the @p mode of the open content.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#oc-mode">Mode Definition</a>
+ */
+ void setMode(Mode mode);
+
+ /**
+ * Returns the mode of the open content.
+ */
+ Mode mode() const;
+
+ /**
+ * Sets the @p wildcard of the open content.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#oc-wildcard">Wildcard Definition</a>
+ */
+ void setWildcard(const XsdWildcard::Ptr &wildcard);
+
+ /**
+ * Returns the wildcard of the open content.
+ */
+ XsdWildcard::Ptr wildcard() const;
+
+ private:
+ Mode m_mode;
+ XsdWildcard::Ptr m_wildcard;
+ };
+
+ /**
+ * @short Describes the content type of a complex type.
+ */
+ class ContentType : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<ContentType> Ptr;
+
+ /**
+ * Describes the variety of the content type.
+ */
+ enum Variety
+ {
+ Empty = 0, ///< The complex type has no further content.
+ Simple, ///< The complex type has only simple type content (e.g. text, number etc.)
+ ElementOnly, ///< The complex type has further elements or attributes but no text as content.
+ Mixed ///< The complex type has further elements or attributes and text as content.
+ };
+
+ /**
+ * Sets the @p variety of the content type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ct-variety">Variety Definition</a>
+ */
+ void setVariety(Variety variety);
+
+ /**
+ * Returns the variety of the content type.
+ */
+ Variety variety() const;
+
+ /**
+ * Sets the @p particle object of the content type.
+ *
+ * The content type has only a particle object if
+ * its variety is ElementOnly or Mixed.
+ *
+ * @see XsdParticle
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ct-particle">Particle Declaration</a>
+ */
+ void setParticle(const XsdParticle::Ptr &particle);
+
+ /**
+ * Returns the particle object of the content type,
+ * or an empty pointer if its variety is neither
+ * ElementOnly nor Mixed.
+ */
+ XsdParticle::Ptr particle() const;
+
+ /**
+ * Sets the open @p content object of the content type.
+ *
+ * The content type has only an open content object if
+ * its variety is ElementOnly or Mixed.
+ *
+ * @see OpenContent
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ct-open_content">Open Content Declaration</a>
+ */
+ void setOpenContent(const OpenContent::Ptr &content);
+
+ /**
+ * Returns the open content object of the content type,
+ * or an empty pointer if its variety is neither
+ * ElementOnly nor Mixed.
+ */
+ OpenContent::Ptr openContent() const;
+
+ /**
+ * Sets the simple @p type object of the content type.
+ *
+ * The content type has only a simple type object if
+ * its variety is Simple.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ct-simple_type_definition">Simple Type Definition</a>
+ */
+ void setSimpleType(const AnySimpleType::Ptr &type);
+
+ /**
+ * Returns the simple type object of the content type,
+ * or an empty pointer if its variety is not Simple.
+ */
+ AnySimpleType::Ptr simpleType() const;
+
+ private:
+ Variety m_variety;
+ XsdParticle::Ptr m_particle;
+ OpenContent::Ptr m_openContent;
+ XsdSimpleType::Ptr m_simpleType;
+ };
+
+
+ /**
+ * Creates a complex type object with empty content.
+ */
+ XsdComplexType();
+
+ /**
+ * Destroys the complex type object.
+ */
+ ~XsdComplexType() {};
+
+ /**
+ * Returns the display name of the complex type.
+ *
+ * The display name can be used to show the type name
+ * to the user.
+ *
+ * @param namePool The name pool where the type name is stored in.
+ */
+ virtual QString displayName(const NamePool::Ptr &namePool) const;
+
+ /**
+ * Sets the base type of the complex type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ctd-base_type_definition">Base Type Definition</a>
+ */
+ void setWxsSuperType(const SchemaType::Ptr &type);
+
+ /**
+ * Returns the base type of the complex type.
+ */
+ virtual SchemaType::Ptr wxsSuperType() const;
+
+ /**
+ * Sets the context @p component of the complex type.
+ *
+ * The component is either an element declaration or a complex type definition.
+ */
+ void setContext(const NamedSchemaComponent::Ptr &component);
+
+ /**
+ * Returns the context component of the complex type.
+ */
+ NamedSchemaComponent::Ptr context() const;
+
+ /**
+ * Sets the derivation @p method of the complex type.
+ *
+ * The derivation method depends on whether the complex
+ * type object has an extension or restriction object as child.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ctd-derivation_method">Derivation Method Definition</a>
+ * @see DerivationMethod
+ */
+ void setDerivationMethod(DerivationMethod method);
+
+ /**
+ * Returns the derivation method of the complex type.
+ */
+ virtual DerivationMethod derivationMethod() const;
+
+ /**
+ * Sets whether the complex type is @p abstract.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ctd-abstract">Abstract Definition</a>
+ */
+ void setIsAbstract(bool abstract);
+
+ /**
+ * Returns whether the complex type is abstract.
+ */
+ virtual bool isAbstract() const;
+
+ /**
+ * Sets the list of all attribute @p uses of the complex type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ctd-attribute_uses">Attribute Uses Declaration</a>
+ */
+ void setAttributeUses(const XsdAttributeUse::List &uses);
+
+ /**
+ * Adds a new attribute @p use to the complex type.
+ */
+ void addAttributeUse(const XsdAttributeUse::Ptr &use);
+
+ /**
+ * Returns the list of all attribute uses of the complex type.
+ */
+ XsdAttributeUse::List attributeUses() const;
+
+ /**
+ * Sets the attribute @p wildcard of the complex type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ctd-attribute_wildcard">Attribute Wildcard Declaration</a>
+ */
+ void setAttributeWildcard(const XsdWildcard::Ptr &wildcard);
+
+ /**
+ * Returns the attribute wildcard of the complex type.
+ */
+ XsdWildcard::Ptr attributeWildcard() const;
+
+ /**
+ * Always returns SchemaType::ComplexType
+ */
+ virtual TypeCategory category() const;
+
+ /**
+ * Sets the content @p type of the complex type.
+ *
+ * @see ContentType
+ */
+ void setContentType(const ContentType::Ptr &type);
+
+ /**
+ * Returns the content type of the complex type.
+ */
+ ContentType::Ptr contentType() const;
+
+ /**
+ * Sets the prohibited @p substitutions of the complex type.
+ *
+ * Only ExtensionConstraint and RestrictionConstraint are allowed.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ctd-prohibited_substitutions">Prohibited Substitutions Definition</a>
+ */
+ void setProhibitedSubstitutions(const BlockingConstraints &substitutions);
+
+ /**
+ * Returns the prohibited substitutions of the complex type.
+ */
+ BlockingConstraints prohibitedSubstitutions() const;
+
+ /**
+ * Sets the @p assertions of the complex type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ctd-assertions">Assertions Definition</a>
+ */
+ void setAssertions(const XsdAssertion::List &assertions);
+
+ /**
+ * Adds an @p assertion to the complex type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ctd-assertions">Assertions Definition</a>
+ */
+ void addAssertion(const XsdAssertion::Ptr &assertion);
+
+ /**
+ * Returns the assertions of the complex type.
+ */
+ XsdAssertion::List assertions() const;
+
+ /**
+ * Always returns @c true.
+ */
+ virtual bool isDefinedBySchema() const;
+
+ private:
+ SchemaType::Ptr m_superType;
+ NamedSchemaComponent::Ptr m_context;
+ DerivationMethod m_derivationMethod;
+ bool m_isAbstract;
+ XsdAttributeUse::List m_attributeUses;
+ XsdWildcard::Ptr m_attributeWildcard;
+ ContentType::Ptr m_contentType;
+ BlockingConstraints m_prohibitedSubstitutions;
+ XsdAssertion::List m_assertions;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsddocumentation.cpp b/src/xmlpatterns/schema/qxsddocumentation.cpp
new file mode 100644
index 0000000000..4994143798
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsddocumentation.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsddocumentation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdDocumentation::XsdDocumentation()
+{
+}
+
+XsdDocumentation::~XsdDocumentation()
+{
+}
+
+void XsdDocumentation::setSource(const AnyURI::Ptr &source)
+{
+ m_source = source;
+}
+
+AnyURI::Ptr XsdDocumentation::source() const
+{
+ return m_source;
+}
+
+void XsdDocumentation::setLanguage(const DerivedString<TypeLanguage>::Ptr &language)
+{
+ m_language = language;
+}
+
+DerivedString<TypeLanguage>::Ptr XsdDocumentation::language() const
+{
+ return m_language;
+}
+
+void XsdDocumentation::setContent(const QString &content)
+{
+ m_content = content;
+}
+
+QString XsdDocumentation::content() const
+{
+ return m_content;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsddocumentation_p.h b/src/xmlpatterns/schema/qxsddocumentation_p.h
new file mode 100644
index 0000000000..c44a2bbf10
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsddocumentation_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdDocumentation_H
+#define Patternist_XsdDocumentation_H
+
+#include "qanytype_p.h"
+#include "qanyuri_p.h"
+#include "qderivedstring_p.h"
+#include "qnamedschemacomponent_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD documentation object.
+ *
+ * This class represents the <em>documentation</em> component of an <em>annotation</em> object
+ * of a XML schema as described <a href="http://www.w3.org/TR/xmlschema11-1/#cAnnotations">here</a>.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdDocumentation : public NamedSchemaComponent
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdDocumentation> Ptr;
+ typedef QList<XsdDocumentation::Ptr> List;
+
+ /**
+ * Creates a new documentation object.
+ */
+ XsdDocumentation();
+
+ /**
+ * Destroys the documentation object.
+ */
+ ~XsdDocumentation();
+
+ /**
+ * Sets the @p source of the documentation.
+ *
+ * The source points to an URL that contains more
+ * information.
+ */
+ void setSource(const AnyURI::Ptr &source);
+
+ /**
+ * Returns the source of the documentation.
+ */
+ AnyURI::Ptr source() const;
+
+ /**
+ * Sets the @p language of the documentation.
+ */
+ void setLanguage(const DerivedString<TypeLanguage>::Ptr &language);
+
+ /**
+ * Returns the language of the documentation.
+ */
+ DerivedString<TypeLanguage>::Ptr language() const;
+
+ /**
+ * Sets the @p content of the documentation.
+ *
+ * The content can be of abritrary type.
+ */
+ void setContent(const QString &content);
+
+ /**
+ * Returns the content of the documentation.
+ */
+ QString content() const;
+
+ private:
+ AnyURI::Ptr m_source;
+ DerivedString<TypeLanguage>::Ptr m_language;
+ QString m_content;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdelement.cpp b/src/xmlpatterns/schema/qxsdelement.cpp
new file mode 100644
index 0000000000..2b8ccab6e8
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdelement.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdelement_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdElement::Scope::setVariety(Variety variety)
+{
+ m_variety = variety;
+}
+
+XsdElement::Scope::Variety XsdElement::Scope::variety() const
+{
+ return m_variety;
+}
+
+void XsdElement::Scope::setParent(const NamedSchemaComponent::Ptr &parent)
+{
+ m_parent = parent;
+}
+
+NamedSchemaComponent::Ptr XsdElement::Scope::parent() const
+{
+ return m_parent;
+}
+
+void XsdElement::ValueConstraint::setVariety(Variety variety)
+{
+ m_variety = variety;
+}
+
+XsdElement::ValueConstraint::Variety XsdElement::ValueConstraint::variety() const
+{
+ return m_variety;
+}
+
+void XsdElement::ValueConstraint::setValue(const QString &value)
+{
+ m_value = value;
+}
+
+QString XsdElement::ValueConstraint::value() const
+{
+ return m_value;
+}
+
+void XsdElement::ValueConstraint::setLexicalForm(const QString &form)
+{
+ m_lexicalForm = form;
+}
+
+QString XsdElement::ValueConstraint::lexicalForm() const
+{
+ return m_lexicalForm;
+}
+
+void XsdElement::TypeTable::addAlternative(const XsdAlternative::Ptr &alternative)
+{
+ m_alternatives.append(alternative);
+}
+
+XsdAlternative::List XsdElement::TypeTable::alternatives() const
+{
+ return m_alternatives;
+}
+
+void XsdElement::TypeTable::setDefaultTypeDefinition(const XsdAlternative::Ptr &type)
+{
+ m_defaultTypeDefinition = type;
+}
+
+XsdAlternative::Ptr XsdElement::TypeTable::defaultTypeDefinition() const
+{
+ return m_defaultTypeDefinition;
+}
+
+
+XsdElement::XsdElement()
+ : m_isAbstract(false)
+{
+}
+
+bool XsdElement::isElement() const
+{
+ return true;
+}
+
+void XsdElement::setType(const SchemaType::Ptr &type)
+{
+ m_type = type;
+}
+
+SchemaType::Ptr XsdElement::type() const
+{
+ return m_type;
+}
+
+void XsdElement::setScope(const Scope::Ptr &scope)
+{
+ m_scope = scope;
+}
+
+XsdElement::Scope::Ptr XsdElement::scope() const
+{
+ return m_scope;
+}
+
+void XsdElement::setValueConstraint(const ValueConstraint::Ptr &constraint)
+{
+ m_valueConstraint = constraint;
+}
+
+XsdElement::ValueConstraint::Ptr XsdElement::valueConstraint() const
+{
+ return m_valueConstraint;
+}
+
+void XsdElement::setTypeTable(const TypeTable::Ptr &table)
+{
+ m_typeTable = table;
+}
+
+XsdElement::TypeTable::Ptr XsdElement::typeTable() const
+{
+ return m_typeTable;
+}
+
+void XsdElement::setIsAbstract(bool abstract)
+{
+ m_isAbstract = abstract;
+}
+
+bool XsdElement::isAbstract() const
+{
+ return m_isAbstract;
+}
+
+void XsdElement::setIsNillable(bool nillable)
+{
+ m_isNillable = nillable;
+}
+
+bool XsdElement::isNillable() const
+{
+ return m_isNillable;
+}
+
+void XsdElement::setDisallowedSubstitutions(const BlockingConstraints &substitutions)
+{
+ m_disallowedSubstitutions = substitutions;
+}
+
+XsdElement::BlockingConstraints XsdElement::disallowedSubstitutions() const
+{
+ return m_disallowedSubstitutions;
+}
+
+void XsdElement::setSubstitutionGroupExclusions(const SchemaType::DerivationConstraints &exclusions)
+{
+ m_substitutionGroupExclusions = exclusions;
+}
+
+SchemaType::DerivationConstraints XsdElement::substitutionGroupExclusions() const
+{
+ return m_substitutionGroupExclusions;
+}
+
+void XsdElement::setIdentityConstraints(const XsdIdentityConstraint::List &constraints)
+{
+ m_identityConstraints = constraints;
+}
+
+void XsdElement::addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint)
+{
+ m_identityConstraints.append(constraint);
+}
+
+XsdIdentityConstraint::List XsdElement::identityConstraints() const
+{
+ return m_identityConstraints;
+}
+
+void XsdElement::setSubstitutionGroupAffiliations(const XsdElement::List &affiliations)
+{
+ m_substitutionGroupAffiliations = affiliations;
+}
+
+XsdElement::List XsdElement::substitutionGroupAffiliations() const
+{
+ return m_substitutionGroupAffiliations;
+}
+
+void XsdElement::addSubstitutionGroup(const XsdElement::Ptr &element)
+{
+ m_substitutionGroups.insert(element);
+}
+
+XsdElement::List XsdElement::substitutionGroups() const
+{
+ return m_substitutionGroups.toList();
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdelement_p.h b/src/xmlpatterns/schema/qxsdelement_p.h
new file mode 100644
index 0000000000..e57168735d
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdelement_p.h
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdElement_H
+#define Patternist_XsdElement_H
+
+#include "qschemacomponent_p.h"
+#include "qschematype_p.h"
+#include "qxsdalternative_p.h"
+#include "qxsdidentityconstraint_p.h"
+#include "qxsdcomplextype_p.h"
+
+#include <QtCore/QList>
+#include <QtCore/QSet>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD element object.
+ *
+ * This class represents the <em>element</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#cElement_Declarations">here</a>.
+ *
+ * It contains information from either a top-level element declaration (as child of a <em>schema</em> object)
+ * or a local element declaration (as descendant of an <em>complexType</em> object).
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSElementDecl">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdElement : public XsdTerm
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdElement> Ptr;
+ typedef QList<XsdElement::Ptr> List;
+
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#ed-value_constraint">constraint type</a> of the element.
+ */
+ enum ConstraintType
+ {
+ NoneConstraint, ///< The value of the element has no constraints.
+ DefaultConstraint, ///< The element has a default value set.
+ FixedConstraint ///< The element has a fixed value set.
+ };
+
+ /**
+ * Describes the scope of an element.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#sc_e">Scope Definition</a>
+ */
+ class Scope : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<Scope> Ptr;
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#ad-scope">scope</a> of an attribute.
+ */
+ enum Variety
+ {
+ Global, ///< The element is defined globally as child of the <em>schema</em> object.
+ Local ///< The element is defined locally as child of a complex type or model group definition.
+ };
+
+ /**
+ * Sets the @p variety of the element scope.
+ */
+ void setVariety(Variety variety);
+
+ /**
+ * Returns the variety of the element scope.
+ */
+ Variety variety() const;
+
+ /**
+ * Sets the @p parent complex type or model group definition of the element scope.
+ */
+ void setParent(const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * Returns the parent complex type or model group definition of the element scope.
+ */
+ NamedSchemaComponent::Ptr parent() const;
+
+ private:
+ Variety m_variety;
+ NamedSchemaComponent::Ptr m_parent;
+ };
+
+ /**
+ * Describes a type table of an element.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#tt">Type Table Definition</a>
+ */
+ class TypeTable : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<TypeTable> Ptr;
+
+ /**
+ * Adds an @p alternative to the type table.
+ */
+ void addAlternative(const XsdAlternative::Ptr &alternative);
+
+ /**
+ * Returns the alternatives of the type table.
+ */
+ XsdAlternative::List alternatives() const;
+
+ /**
+ * Sets the default @p type definition.
+ */
+ void setDefaultTypeDefinition(const XsdAlternative::Ptr &type);
+
+ /**
+ * Returns the default type definition.
+ */
+ XsdAlternative::Ptr defaultTypeDefinition() const;
+
+ private:
+ XsdAlternative::List m_alternatives;
+ XsdAlternative::Ptr m_defaultTypeDefinition;
+ };
+
+
+ /**
+ * Describes the value constraint of an element.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#vc_e">Value Constraint Definition</a>
+ */
+ class ValueConstraint : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<ValueConstraint> Ptr;
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#ed-value_constraint">value constraint</a> of an element.
+ */
+ enum Variety
+ {
+ Default, ///< The element has a default value set.
+ Fixed ///< The element has a fixed value set.
+ };
+
+ /**
+ * Sets the @p variety of the element value constraint.
+ */
+ void setVariety(Variety variety);
+
+ /**
+ * Returns the variety of the element value constraint.
+ */
+ Variety variety() const;
+
+ /**
+ * Sets the @p value of the constraint.
+ */
+ void setValue(const QString &value);
+
+ /**
+ * Returns the value of the constraint.
+ */
+ QString value() const;
+
+ /**
+ * Sets the lexical @p form of the constraint.
+ */
+ void setLexicalForm(const QString &form);
+
+ /**
+ * Returns the lexical form of the constraint.
+ */
+ QString lexicalForm() const;
+
+ private:
+ Variety m_variety;
+ QString m_value;
+ QString m_lexicalForm;
+ };
+
+ /**
+ * Creates a new element object.
+ */
+ XsdElement();
+
+ /**
+ * Always returns @c true, used to avoid dynamic casts.
+ */
+ virtual bool isElement() const;
+
+ /**
+ * Sets the @p type of the element.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-type_definition">Type Definition</a>
+ */
+ void setType(const SchemaType::Ptr &type);
+
+ /**
+ * Returns the type of the element.
+ */
+ SchemaType::Ptr type() const;
+
+ /**
+ * Sets the @p scope of the element.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-scope">Scope Definition</a>
+ */
+ void setScope(const Scope::Ptr &scope);
+
+ /**
+ * Returns the scope of the element.
+ */
+ Scope::Ptr scope() const;
+
+ /**
+ * Sets the value @p constraint of the element.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-value_constraint">Value Constraint Definition</a>
+ */
+ void setValueConstraint(const ValueConstraint::Ptr &constraint);
+
+ /**
+ * Returns the value constraint of the element.
+ */
+ ValueConstraint::Ptr valueConstraint() const;
+
+ /**
+ * Sets the type table of the element.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-type_table">Type Table Definition</a>
+ */
+ void setTypeTable(const TypeTable::Ptr &table);
+
+ /**
+ * Returns the type table of the element.
+ */
+ TypeTable::Ptr typeTable() const;
+
+ /**
+ * Sets whether the element is @p abstract.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-abstract">Abstract Definition</a>
+ */
+ void setIsAbstract(bool abstract);
+
+ /**
+ * Returns whether the element is abstract.
+ */
+ bool isAbstract() const;
+
+ /**
+ * Sets whether the element is @p nillable.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-nillable">Nillable Definition</a>
+ */
+ void setIsNillable(bool nillable);
+
+ /**
+ * Returns whether the element is nillable.
+ */
+ bool isNillable() const;
+
+ /**
+ * Sets the disallowed @p substitutions of the element.
+ *
+ * Only ExtensionConstraint, RestrictionConstraint and SubstitutionConstraint are allowed.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-disallowed_substitutions">Disallowed Substitutions Definition</a>
+ */
+ void setDisallowedSubstitutions(const BlockingConstraints &substitutions);
+
+ /**
+ * Returns the disallowed substitutions of the element.
+ */
+ BlockingConstraints disallowedSubstitutions() const;
+
+ /**
+ * Sets the substitution group @p exclusions of the element.
+ *
+ * Only SchemaType::ExtensionConstraint and SchemaType::RestrictionConstraint are allowed.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-substitution_group_exclusions">Substitution Group Exclusions Definition</a>
+ */
+ void setSubstitutionGroupExclusions(const SchemaType::DerivationConstraints &exclusions);
+
+ /**
+ * Returns the substitution group exclusions of the element.
+ */
+ SchemaType::DerivationConstraints substitutionGroupExclusions() const;
+
+ /**
+ * Sets the identity @p constraints of the element.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-identity-constraint_definitions">Identity Constraint Definition</a>
+ */
+ void setIdentityConstraints(const XsdIdentityConstraint::List &constraints);
+
+ /**
+ * Adds a new identity @p constraint to the element.
+ */
+ void addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint);
+
+ /**
+ * Returns a list of all identity constraints of the element.
+ */
+ XsdIdentityConstraint::List identityConstraints() const;
+
+ /**
+ * Sets the substitution group @p affiliations of the element.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#ed-substituion_group_affiliations">Substitution Group Affiliations</a>
+ */
+ void setSubstitutionGroupAffiliations(const XsdElement::List &affiliations);
+
+ /**
+ * Returns the substitution group affiliations of the element.
+ */
+ XsdElement::List substitutionGroupAffiliations() const;
+
+ /**
+ * Adds a substitution group to the element.
+ */
+ void addSubstitutionGroup(const XsdElement::Ptr &elements);
+
+ /**
+ * Returns the substitution groups of the element.
+ */
+ XsdElement::List substitutionGroups() const;
+
+ private:
+ SchemaType::Ptr m_type;
+ Scope::Ptr m_scope;
+ ValueConstraint::Ptr m_valueConstraint;
+ TypeTable::Ptr m_typeTable;
+ bool m_isAbstract;
+ bool m_isNillable;
+ BlockingConstraints m_disallowedSubstitutions;
+ SchemaType::DerivationConstraints m_substitutionGroupExclusions;
+ XsdIdentityConstraint::List m_identityConstraints;
+ XsdElement::List m_substitutionGroupAffiliations;
+ QSet<XsdElement::Ptr> m_substitutionGroups;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdfacet.cpp b/src/xmlpatterns/schema/qxsdfacet.cpp
new file mode 100644
index 0000000000..513eee84f2
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdfacet.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdfacet_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdFacet::XsdFacet()
+ : m_type(None)
+{
+}
+
+void XsdFacet::setType(Type type)
+{
+ m_type = type;
+}
+
+XsdFacet::Type XsdFacet::type() const
+{
+ return m_type;
+}
+
+void XsdFacet::setValue(const AtomicValue::Ptr &value)
+{
+ m_value = value;
+}
+
+AtomicValue::Ptr XsdFacet::value() const
+{
+ return m_value;
+}
+
+void XsdFacet::setMultiValue(const AtomicValue::List &value)
+{
+ m_multiValue = value;
+}
+
+AtomicValue::List XsdFacet::multiValue() const
+{
+ return m_multiValue;
+}
+
+void XsdFacet::setAssertions(const XsdAssertion::List &assertions)
+{
+ m_assertions = assertions;
+}
+
+XsdAssertion::List XsdFacet::assertions() const
+{
+ return m_assertions;
+}
+
+void XsdFacet::setFixed(bool fixed)
+{
+ m_fixed = fixed;
+}
+
+bool XsdFacet::fixed() const
+{
+ return m_fixed;
+}
+
+QString XsdFacet::typeName(Type type)
+{
+ switch (type) {
+ case Length: return QLatin1String("length"); break;
+ case MinimumLength: return QLatin1String("minLength"); break;
+ case MaximumLength: return QLatin1String("maxLength"); break;
+ case Pattern: return QLatin1String("pattern"); break;
+ case WhiteSpace: return QLatin1String("whiteSpace"); break;
+ case MaximumInclusive: return QLatin1String("maxInclusive"); break;
+ case MaximumExclusive: return QLatin1String("maxExclusive"); break;
+ case MinimumInclusive: return QLatin1String("minInclusive"); break;
+ case MinimumExclusive: return QLatin1String("minExclusive"); break;
+ case TotalDigits: return QLatin1String("totalDigits"); break;
+ case FractionDigits: return QLatin1String("fractionDigits"); break;
+ case Enumeration: return QLatin1String("enumeration"); break;
+ case Assertion: return QLatin1String("assertion"); break;
+ case None: // fall through
+ default: return QLatin1String("none"); break;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdfacet_p.h b/src/xmlpatterns/schema/qxsdfacet_p.h
new file mode 100644
index 0000000000..f1f8110809
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdfacet_p.h
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdFacet_H
+#define Patternist_XsdFacet_H
+
+#include "qitem_p.h"
+#include "qnamedschemacomponent_p.h"
+#include "qxsdannotated_p.h"
+#include "qxsdassertion_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD facet object.
+ *
+ * This class represents one of the following XML schema objects:
+ *
+ * <ul>
+ * <li><em>length</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-length">Definition</a></li>
+ * <li><em>minLength</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-minLength">Definition</a></li>
+ * <li><em>maxLength</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-maxLength">Definition</a></li>
+ * <li><em>pattern</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-pattern">Definition</a></li>
+ * <li><em>whiteSpace</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-whiteSpace">Definition</a></li>
+ * <li><em>maxInclusive</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-maxInclusive">Definition</a></li>
+ * <li><em>maxExclusive</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-maxExclusive">Definition</a></li>
+ * <li><em>minInclusive</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-minInclusive">Definition</a></li>
+ * <li><em>minExclusive</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-minExclusive">Definition</a></li>
+ * <li><em>totalDigits</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-totalDigits">Definition</a></li>
+ * <li><em>fractionDigits</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-fractionDigits">Definition</a></li>
+ * <li><em>enumeration</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-enumeration">Definition</a></li>
+ * <li><em>assertion</em> <a href="http://www.w3.org/TR/xmlschema-2/#rf-assertion">Definition</a></li>
+ * </ul>
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSFacet">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdFacet : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdFacet> Ptr;
+
+ /**
+ * Describes the type of the facet.
+ */
+ enum Type
+ {
+ None = 0, ///< An invalid facet.
+ Length = 1 << 0, ///< Match the exact length (<a href="http://www.w3.org/TR/xmlschema-2/#rf-length">Length Definition</a>)
+ MinimumLength = 1 << 1, ///< Match the minimum length (<a href="http://www.w3.org/TR/xmlschema-2/#rf-minLength">Minimum Length Definition</a>)
+ MaximumLength = 1 << 2, ///< Match the maximum length (<a href="http://www.w3.org/TR/xmlschema-2/#rf-maxLength">Maximum Length Definition</a>)
+ Pattern = 1 << 3, ///< Match a regular expression (<a href="http://www.w3.org/TR/xmlschema-2/#rf-pattern">Pattern Definition</a>)
+ WhiteSpace = 1 << 4, ///< Match a whitespace rule (<a href="http://www.w3.org/TR/xmlschema-2/#rf-whiteSpace">White Space Definition</a>)
+ MaximumInclusive = 1 << 5, ///< Match a maximum inclusive (<a href="http://www.w3.org/TR/xmlschema-2/#rf-maxInclusive">Maximum Inclusive Definition</a>)
+ MaximumExclusive = 1 << 6, ///< Match a maximum exclusive (<a href="http://www.w3.org/TR/xmlschema-2/#rf-maxExclusive">Maximum Exclusive Definition</a>)
+ MinimumInclusive = 1 << 7, ///< Match a minimum inclusive (<a href="http://www.w3.org/TR/xmlschema-2/#rf-minInclusive">Minimum Inclusive Definition</a>)
+ MinimumExclusive = 1 << 8, ///< Match a minimum exclusive (<a href="http://www.w3.org/TR/xmlschema-2/#rf-minExclusive">Minimum Exclusive Definition</a>)
+ TotalDigits = 1 << 9, ///< Match some integer digits (<a href="http://www.w3.org/TR/xmlschema-2/#rf-totalDigits">Total Digits Definition</a>)
+ FractionDigits = 1 << 10, ///< Match some double digits (<a href="http://www.w3.org/TR/xmlschema-2/#rf-fractionDigits">Fraction Digits Definition</a>)
+ Enumeration = 1 << 11, ///< Match an enumeration (<a href="http://www.w3.org/TR/xmlschema-2/#rf-enumeration">Enumeration Definition</a>)
+ Assertion = 1 << 12, ///< Match an assertion (<a href="http://www.w3.org/TR/xmlschema-2/#rf-assertion">Assertion Definition</a>)
+ };
+ typedef QHash<XsdFacet::Type, XsdFacet::Ptr> Hash;
+ typedef QHashIterator<XsdFacet::Type, XsdFacet::Ptr> HashIterator;
+
+ /**
+ * Creates a new facet object of type None.
+ */
+ XsdFacet();
+
+ /**
+ * Sets the @p type of the facet.
+ *
+ * @see Type
+ */
+ void setType(Type type);
+
+ /**
+ * Returns the type of the facet.
+ */
+ Type type() const;
+
+ /**
+ * Sets the @p value of the facet.
+ *
+ * Depending on the type of the facet the
+ * value can be a string, interger, double etc.
+ *
+ * @note This method should be used for all types of facets
+ * except Pattern, Enumeration and Assertion.
+ */
+ void setValue(const AtomicValue::Ptr &value);
+
+ /**
+ * Returns the value of the facet or an empty pointer if facet
+ * type is Pattern, Enumeration or Assertion.
+ */
+ AtomicValue::Ptr value() const;
+
+ /**
+ * Sets the @p value of the facet.
+ *
+ * @note This method should be used for if the type of the
+ * facet is Pattern or Enumeration.
+ */
+ void setMultiValue(const AtomicValue::List &value);
+
+ /**
+ * Returns the value of the facet or an empty pointer if facet
+ * type is not of type Pattern or Enumeration.
+ */
+ AtomicValue::List multiValue() const;
+
+ /**
+ * Sets the @p assertions of the facet.
+ *
+ * @note This method should be used if the type of the
+ * facet is Assertion.
+ */
+ void setAssertions(const XsdAssertion::List &assertions);
+
+ /**
+ * Returns the assertions of the facet or an empty pointer if facet
+ * type is not of type Assertion.
+ */
+ XsdAssertion::List assertions() const;
+
+ /**
+ * Sets whether the facet is @p fixed.
+ *
+ * All facets except pattern, enumeration and assertion can be fixed.
+ */
+ void setFixed(bool fixed);
+
+ /**
+ * Returns whether the facet is fixed.
+ */
+ bool fixed() const;
+
+ /**
+ * Returns the textual description of the facet @p type.
+ */
+ static QString typeName(Type type);
+
+ private:
+ Type m_type;
+ AtomicValue::Ptr m_value;
+ AtomicValue::List m_multiValue;
+ XsdAssertion::List m_assertions;
+ bool m_fixed;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdidcache.cpp b/src/xmlpatterns/schema/qxsdidcache.cpp
new file mode 100644
index 0000000000..d4a7b64544
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdidcache.cpp
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdidcache_p.h"
+
+#include <QtCore/QReadLocker>
+#include <QtCore/QWriteLocker>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdIdCache::addId(const QString &id)
+{
+ const QWriteLocker locker(&m_lock);
+ Q_ASSERT(!m_ids.contains(id));
+
+ m_ids.insert(id);
+}
+
+bool XsdIdCache::hasId(const QString &id) const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_ids.contains(id);
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdidcache_p.h b/src/xmlpatterns/schema/qxsdidcache_p.h
new file mode 100644
index 0000000000..b1d3c0f9ce
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdidcache_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdIdCache_H
+#define Patternist_XsdIdCache_H
+
+#include "qschemacomponent_p.h"
+
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QReadWriteLock>
+#include <QtCore/QSet>
+#include <QtCore/QString>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Helper class for keeping track of all existing IDs in a schema.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdIdCache : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdIdCache> Ptr;
+
+ /**
+ * Adds an @p id to the id cache.
+ */
+ void addId(const QString &id);
+
+ /**
+ * Returns whether the id cache contains the given @p id already.
+ */
+ bool hasId(const QString &id) const;
+
+ private:
+ QSet<QString> m_ids;
+ mutable QReadWriteLock m_lock;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdidchelper.cpp b/src/xmlpatterns/schema/qxsdidchelper.cpp
new file mode 100644
index 0000000000..70980cb2b7
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdidchelper.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdidchelper_p.h"
+
+#include "qderivedstring_p.h"
+#include "qxsdschemahelper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+FieldNode::FieldNode()
+{
+}
+
+FieldNode::FieldNode(const QXmlItem &item, const QString &data, const SchemaType::Ptr &type)
+ : m_item(item)
+ , m_data(data)
+ , m_type(type)
+{
+}
+
+bool FieldNode::isEmpty() const
+{
+ return m_item.isNull();
+}
+
+bool FieldNode::isEqualTo(const FieldNode &other, const NamePool::Ptr &namePool, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const
+{
+ if (m_type != other.m_type)
+ return false;
+
+ const DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(namePool, m_data);
+ const DerivedString<TypeString>::Ptr otherString = DerivedString<TypeString>::fromLexical(namePool, other.m_data);
+
+ return XsdSchemaHelper::constructAndCompare(string, AtomicComparator::OperatorEqual, otherString, m_type, context, reflection);
+}
+
+QXmlItem FieldNode::item() const
+{
+ return m_item;
+}
+
+TargetNode::TargetNode(const QXmlItem &item)
+ : m_item(item)
+{
+}
+
+QXmlItem TargetNode::item() const
+{
+ return m_item;
+}
+
+QVector<QXmlItem> TargetNode::fieldItems() const
+{
+ QVector<QXmlItem> items;
+
+ for (int i = 0; i < m_fields.count(); ++i)
+ items.append(m_fields.at(i).item());
+
+ return items;
+}
+
+int TargetNode::emptyFieldsCount() const
+{
+ int counter = 0;
+ for (int i = 0; i < m_fields.count(); ++i) {
+ if (m_fields.at(i).isEmpty())
+ ++counter;
+ }
+
+ return counter;
+}
+
+bool TargetNode::fieldsAreEqual(const TargetNode &other, const NamePool::Ptr &namePool, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const
+{
+ if (m_fields.count() != other.m_fields.count())
+ return false;
+
+ for (int i = 0; i < m_fields.count(); ++i) {
+ if (!m_fields.at(i).isEqualTo(other.m_fields.at(i), namePool, context, reflection))
+ return false;
+ }
+
+ return true;
+}
+
+void TargetNode::addField(const QXmlItem &item, const QString &data, const SchemaType::Ptr &type)
+{
+ m_fields.append(FieldNode(item, data, type));
+}
+
+bool TargetNode::operator==(const TargetNode &other) const
+{
+ return (m_item.toNodeModelIndex() == other.m_item.toNodeModelIndex());
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdidchelper_p.h b/src/xmlpatterns/schema/qxsdidchelper_p.h
new file mode 100644
index 0000000000..3034292524
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdidchelper_p.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdIdcHelper_H
+#define Patternist_XsdIdcHelper_H
+
+#include "qreportcontext_p.h"
+#include "qschematype_p.h"
+
+#include <QtXmlPatterns/QXmlItem>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+
+ /**
+ * @short A helper class for validating identity constraints.
+ *
+ * This class represents a field node from the key-sequence as defined in
+ * the validation rules at http://www.w3.org/TR/xmlschema11-1/#d0e32243.
+ */
+ class FieldNode
+ {
+ public:
+ /**
+ * Creates an empty field node.
+ */
+ FieldNode();
+
+ /**
+ * Creates a field node that is bound to a xml node.
+ *
+ * @param item The xml node the field is bound to.
+ * @param data The string content of that field.
+ * @param type The type that is bound to that field.
+ */
+ FieldNode(const QXmlItem &item, const QString &data, const SchemaType::Ptr &type);
+
+ /**
+ * Returns whether this field is empty.
+ *
+ * A field can be empty, if the xpath expression selects an absent attribute
+ * or element.
+ */
+ bool isEmpty() const;
+
+ /**
+ * Returns whether this field is equal to the @p other field.
+ *
+ * Equal means that both have the same type and there content is equal in the
+ * types value space.
+ */
+ bool isEqualTo(const FieldNode &other, const NamePool::Ptr &namePool, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const;
+
+ /**
+ * Returns the xml node item the field is bound to.
+ */
+ QXmlItem item() const;
+
+ private:
+ QXmlItem m_item;
+ QString m_data;
+ SchemaType::Ptr m_type;
+ };
+
+ /**
+ * @short A helper class for validating identity constraints.
+ *
+ * This class represents a target or qualified node from the target or qualified
+ * node set as defined in the validation rules at http://www.w3.org/TR/xmlschema11-1/#d0e32243.
+ *
+ * A target node is part of the qualified node set, if all of its fields are not empty.
+ */
+ class TargetNode
+ {
+ public:
+ /**
+ * Defines a set of target nodes.
+ */
+ typedef QSet<TargetNode> Set;
+
+ /**
+ * Creates a new target node that is bound to the xml node @p item.
+ */
+ explicit TargetNode(const QXmlItem &item);
+
+ /**
+ * Returns the xml node item the target node is bound to.
+ */
+ QXmlItem item() const;
+
+ /**
+ * Returns all xml node items, the fields of that target node are bound to.
+ */
+ QVector<QXmlItem> fieldItems() const;
+
+ /**
+ * Returns the number of fields that are empty.
+ */
+ int emptyFieldsCount() const;
+
+ /**
+ * Returns whether the target node has the same fields as the @p other target node.
+ */
+ bool fieldsAreEqual(const TargetNode &other, const NamePool::Ptr &namePool, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const;
+
+ /**
+ * Adds a new field to the target node with the given values.
+ */
+ void addField(const QXmlItem &item, const QString &data, const SchemaType::Ptr &type);
+
+ /**
+ * Returns whether the target node is equal to the @p other target node.
+ */
+ bool operator==(const TargetNode &other) const;
+
+ private:
+ QXmlItem m_item;
+ QVector<FieldNode> m_fields;
+ };
+
+ /**
+ * Creates a hash value for the given target @p node.
+ */
+ inline uint qHash(const QPatternist::TargetNode &node)
+ {
+ return qHash(node.item().toNodeModelIndex());
+ }
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdidentityconstraint.cpp b/src/xmlpatterns/schema/qxsdidentityconstraint.cpp
new file mode 100644
index 0000000000..e72a005212
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdidentityconstraint.cpp
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdidentityconstraint_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdIdentityConstraint::setCategory(Category category)
+{
+ m_category = category;
+}
+
+XsdIdentityConstraint::Category XsdIdentityConstraint::category() const
+{
+ return m_category;
+}
+
+void XsdIdentityConstraint::setSelector(const XsdXPathExpression::Ptr &selector)
+{
+ m_selector = selector;
+}
+
+XsdXPathExpression::Ptr XsdIdentityConstraint::selector() const
+{
+ return m_selector;
+}
+
+void XsdIdentityConstraint::setFields(const XsdXPathExpression::List &fields)
+{
+ m_fields = fields;
+}
+
+void XsdIdentityConstraint::addField(const XsdXPathExpression::Ptr &field)
+{
+ m_fields.append(field);
+}
+
+XsdXPathExpression::List XsdIdentityConstraint::fields() const
+{
+ return m_fields;
+}
+
+void XsdIdentityConstraint::setReferencedKey(const XsdIdentityConstraint::Ptr &referencedKey)
+{
+ m_referencedKey = referencedKey;
+}
+
+XsdIdentityConstraint::Ptr XsdIdentityConstraint::referencedKey() const
+{
+ return m_referencedKey;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdidentityconstraint_p.h b/src/xmlpatterns/schema/qxsdidentityconstraint_p.h
new file mode 100644
index 0000000000..6870b1e48f
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdidentityconstraint_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdIdentityConstraint_H
+#define Patternist_XsdIdentityConstraint_H
+
+#include "qnamedschemacomponent_p.h"
+#include "qxsdannotated_p.h"
+#include "qxsdxpathexpression_p.h"
+
+#include <QtCore/QStringList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD identity constraint object.
+ *
+ * This class represents the <em>identity constraint</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#cIdentity-constraint_Definitions">here</a>.
+ *
+ * It contains information from either a <em>key</em> object, a <em>keyref</em> object or an
+ * <em>unique</em> object.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSIdentityConstraint">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdIdentityConstraint : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdIdentityConstraint> Ptr;
+ typedef QList<XsdIdentityConstraint::Ptr> List;
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#icd-identity-constraint_category">category</a> of the identity constraint.
+ */
+ enum Category
+ {
+ Key = 1, ///< The constraint is a key constraint
+ KeyReference, ///< The constraint is a keyref constraint
+ Unique ///< The constraint is an unique constraint
+ };
+
+ /**
+ * Sets the @p category of the identity constraint.
+ *
+ * @see Category
+ */
+ void setCategory(Category category);
+
+ /**
+ * Returns the category of the identity constraint.
+ */
+ Category category() const;
+
+ /**
+ * Sets the @p selector of the identity constraint.
+ *
+ * The selector is a restricted XPath 1.0 expression,
+ * that selects a set of nodes.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#icd-selector"></a>
+ */
+ void setSelector(const XsdXPathExpression::Ptr &selector);
+
+ /**
+ * Returns the selector of the identity constraint.
+ */
+ XsdXPathExpression::Ptr selector() const;
+
+ /**
+ * Sets the @p fields of the identity constraint.
+ *
+ * Each field is a restricted XPath 1.0 expression,
+ * that selects a set of nodes.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#icd-fields"></a>
+ */
+ void setFields(const XsdXPathExpression::List &fields);
+
+ /**
+ * Adds a new @p field to the identity constraint.
+ */
+ void addField(const XsdXPathExpression::Ptr &field);
+
+ /**
+ * Returns all fields of the identity constraint.
+ */
+ XsdXPathExpression::List fields() const;
+
+ /**
+ * Sets the referenced @p key of the identity constraint.
+ *
+ * The key points to a identity constraint of type Key or Unique.
+ *
+ * The identity constraint has only a referenced key if its
+ * type is KeyReference.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#icd-referenced_key"></a>
+ */
+ void setReferencedKey(const XsdIdentityConstraint::Ptr &key);
+
+ /**
+ * Returns the referenced key of the identity constraint or an empty
+ * pointer if its type is not KeyReference.
+ */
+ XsdIdentityConstraint::Ptr referencedKey() const;
+
+ private:
+ Category m_category;
+ XsdXPathExpression::Ptr m_selector;
+ XsdXPathExpression::List m_fields;
+ XsdIdentityConstraint::Ptr m_referencedKey;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdinstancereader.cpp b/src/xmlpatterns/schema/qxsdinstancereader.cpp
new file mode 100644
index 0000000000..81c40c9c28
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdinstancereader.cpp
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdinstancereader_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdInstanceReader::XsdInstanceReader(const QAbstractXmlNodeModel *model, const XsdSchemaContext::Ptr &context)
+ : m_context(context)
+ , m_model(model->iterate(model->root(QXmlNodeModelIndex()), QXmlNodeModelIndex::AxisChild))
+{
+}
+
+bool XsdInstanceReader::atEnd() const
+{
+ return (m_model.current() == AbstractXmlPullProvider::EndOfInput);
+}
+
+void XsdInstanceReader::readNext()
+{
+ m_model.next();
+
+ if (m_model.current() == AbstractXmlPullProvider::StartElement) {
+ m_cachedAttributes = m_model.attributes();
+ m_cachedAttributeItems = m_model.attributeItems();
+ m_cachedSourceLocation = m_model.sourceLocation();
+ m_cachedItem = QXmlItem(m_model.index());
+ }
+}
+
+bool XsdInstanceReader::isStartElement() const
+{
+ return (m_model.current() == AbstractXmlPullProvider::StartElement);
+}
+
+bool XsdInstanceReader::isEndElement() const
+{
+ return (m_model.current() == AbstractXmlPullProvider::EndElement);
+}
+
+bool XsdInstanceReader::hasChildText() const
+{
+ const QXmlNodeModelIndex index = m_model.index();
+ QXmlNodeModelIndex::Iterator::Ptr it = index.model()->iterate(index, QXmlNodeModelIndex::AxisChild);
+
+ QXmlNodeModelIndex currentIndex = it->next();
+ while (!currentIndex.isNull()) {
+ if (currentIndex.kind() == QXmlNodeModelIndex::Text)
+ return true;
+
+ currentIndex = it->next();
+ }
+
+ return false;
+}
+
+bool XsdInstanceReader::hasChildElement() const
+{
+ const QXmlNodeModelIndex index = m_model.index();
+ QXmlNodeModelIndex::Iterator::Ptr it = index.model()->iterate(index, QXmlNodeModelIndex::AxisChild);
+
+ QXmlNodeModelIndex currentIndex = it->next();
+ while (!currentIndex.isNull()) {
+ if (currentIndex.kind() == QXmlNodeModelIndex::Element)
+ return true;
+
+ currentIndex = it->next();
+ }
+
+ return false;
+}
+
+QXmlName XsdInstanceReader::name() const
+{
+ return m_model.name();
+}
+
+QXmlName XsdInstanceReader::convertToQName(const QString &name) const
+{
+ const int pos = name.indexOf(QLatin1Char(':'));
+
+ QXmlName::PrefixCode prefixCode = 0;
+ QXmlName::NamespaceCode namespaceCode;
+ QXmlName::LocalNameCode localNameCode;
+ if (pos != -1) {
+ prefixCode = m_context->namePool()->allocatePrefix(name.left(pos));
+ namespaceCode = m_cachedItem.toNodeModelIndex().namespaceForPrefix(prefixCode);
+ localNameCode = m_context->namePool()->allocateLocalName(name.mid(pos + 1));
+ } else {
+ prefixCode = StandardPrefixes::empty;
+ namespaceCode = m_cachedItem.toNodeModelIndex().namespaceForPrefix(prefixCode);
+ if (namespaceCode == -1)
+ namespaceCode = StandardNamespaces::empty;
+ localNameCode = m_context->namePool()->allocateLocalName(name);
+ }
+
+ return QXmlName(namespaceCode, localNameCode, prefixCode);
+}
+
+bool XsdInstanceReader::hasAttribute(const QXmlName &name) const
+{
+ return m_cachedAttributes.contains(name);
+}
+
+QString XsdInstanceReader::attribute(const QXmlName &name) const
+{
+ Q_ASSERT(m_cachedAttributes.contains(name));
+
+ return m_cachedAttributes.value(name);
+}
+
+QSet<QXmlName> XsdInstanceReader::attributeNames() const
+{
+ return m_cachedAttributes.keys().toSet();
+}
+
+QString XsdInstanceReader::text() const
+{
+ const QXmlNodeModelIndex index = m_model.index();
+ QXmlNodeModelIndex::Iterator::Ptr it = index.model()->iterate(index, QXmlNodeModelIndex::AxisChild);
+
+ QString result;
+
+ QXmlNodeModelIndex currentIndex = it->next();
+ while (!currentIndex.isNull()) {
+ if (currentIndex.kind() == QXmlNodeModelIndex::Text) {
+ result.append(Item(currentIndex).stringValue());
+ }
+
+ currentIndex = it->next();
+ }
+
+ return result;
+}
+
+QXmlItem XsdInstanceReader::item() const
+{
+ return m_cachedItem;
+}
+
+QXmlItem XsdInstanceReader::attributeItem(const QXmlName &name) const
+{
+ return m_cachedAttributeItems.value(name);
+}
+
+QSourceLocation XsdInstanceReader::sourceLocation() const
+{
+ return m_cachedSourceLocation;
+}
+
+QVector<QXmlName> XsdInstanceReader::namespaceBindings(const QXmlNodeModelIndex &index) const
+{
+ return index.namespaceBindings();
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdinstancereader_p.h b/src/xmlpatterns/schema/qxsdinstancereader_p.h
new file mode 100644
index 0000000000..9df02d6763
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdinstancereader_p.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdInstanceReader_H
+#define Patternist_XsdInstanceReader_H
+
+#include "qabstractxmlnodemodel.h"
+#include "qpullbridge_p.h"
+#include "qxsdschemacontext_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short The schema instance reader.
+ *
+ * This class reads in a xml instance document from a QAbstractXmlNodeModel
+ * and provides a QXmlStreamReader like interface with some additional context
+ * information.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdInstanceReader
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdInstanceReader> Ptr;
+
+ /**
+ * Creates a new instance reader that will read the data from
+ * the given @p model.
+ *
+ * @param model The model the data are read from.
+ * @param context The context that is used for error reporting etc.
+ */
+ XsdInstanceReader(const QAbstractXmlNodeModel *model, const XsdSchemaContext::Ptr &context);
+
+ protected:
+ /**
+ * Returns @c true if the end of the document is reached, @c false otherwise.
+ */
+ bool atEnd() const;
+
+ /**
+ * Reads the next node from the document.
+ */
+ void readNext();
+
+ /**
+ * Returns whether the current node is a start element.
+ */
+ bool isStartElement() const;
+
+ /**
+ * Returns whether the current node is an end element.
+ */
+ bool isEndElement() const;
+
+ /**
+ * Returns whether the current node has a text node among its children.
+ */
+ bool hasChildText() const;
+
+ /**
+ * Returns whether the current node has an element node among its children.
+ */
+ bool hasChildElement() const;
+
+ /**
+ * Returns the name of the current node.
+ */
+ QXmlName name() const;
+
+ /**
+ * Returns whether the current node has an attribute with the given @p name.
+ */
+ bool hasAttribute(const QXmlName &name) const;
+
+ /**
+ * Returns the attribute with the given @p name of the current node.
+ */
+ QString attribute(const QXmlName &name) const;
+
+ /**
+ * Returns the list of attribute names of the current node.
+ */
+ QSet<QXmlName> attributeNames() const;
+
+ /**
+ * Returns the concatenated text of all direct child text nodes.
+ */
+ QString text() const;
+
+ /**
+ * Converts a qualified name into a QXmlName according to the namespace
+ * mappings of the current node.
+ */
+ QXmlName convertToQName(const QString &name) const;
+
+ /**
+ * Returns a source location object for the current position.
+ */
+ QSourceLocation sourceLocation() const;
+
+ /**
+ * Returns the QXmlItem for the current position.
+ */
+ QXmlItem item() const;
+
+ /**
+ * Returns the QXmlItem for the attribute with the given @p name at the current position.
+ */
+ QXmlItem attributeItem(const QXmlName &name) const;
+
+ /**
+ * Returns the namespace bindings for the given node model @p index.
+ */
+ QVector<QXmlName> namespaceBindings(const QXmlNodeModelIndex &index) const;
+
+ /**
+ * The shared schema context.
+ */
+ XsdSchemaContext::Ptr m_context;
+
+ private:
+ PullBridge m_model;
+ QHash<QXmlName, QString> m_cachedAttributes;
+ QHash<QXmlName, QXmlItem> m_cachedAttributeItems;
+ QSourceLocation m_cachedSourceLocation;
+ QXmlItem m_cachedItem;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdmodelgroup.cpp b/src/xmlpatterns/schema/qxsdmodelgroup.cpp
new file mode 100644
index 0000000000..1245822d24
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdmodelgroup.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdmodelgroup_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdModelGroup::XsdModelGroup()
+ : m_compositor(SequenceCompositor)
+{
+}
+
+bool XsdModelGroup::isModelGroup() const
+{
+ return true;
+}
+
+void XsdModelGroup::setCompositor(ModelCompositor compositor)
+{
+ m_compositor = compositor;
+}
+
+XsdModelGroup::ModelCompositor XsdModelGroup::compositor() const
+{
+ return m_compositor;
+}
+
+void XsdModelGroup::setParticles(const XsdParticle::List &particles)
+{
+ m_particles = particles;
+}
+
+XsdParticle::List XsdModelGroup::particles() const
+{
+ return m_particles;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdmodelgroup_p.h b/src/xmlpatterns/schema/qxsdmodelgroup_p.h
new file mode 100644
index 0000000000..b7b59acfad
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdmodelgroup_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdModelGroup_H
+#define Patternist_XsdModelGroup_H
+
+#include "qxsdparticle_p.h"
+#include "qxsdterm_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+template<typename N> class QList;
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD model group object.
+ *
+ * This class represents the <em>model group</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#cModel_Group_Definitions">here</a>.
+ *
+ * It contains information from either a <em>sequence</em> object, a <em>choice</em> object or an
+ * <em>all</em> object.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSModelGroup">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdModelGroup : public XsdTerm
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdModelGroup> Ptr;
+ typedef QList<XsdModelGroup::Ptr> List;
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#mg-compositor">compositor</a> of the model group.
+ */
+ enum ModelCompositor
+ {
+ SequenceCompositor, ///< The model group is a sequence.
+ ChoiceCompositor, ///< The model group is a choice.
+ AllCompositor ///< The model group contains elements only.
+ };
+
+ /**
+ * Creates a new model group object.
+ */
+ XsdModelGroup();
+
+ /**
+ * Returns always @c true, used to avoid dynamic casts.
+ */
+ virtual bool isModelGroup() const;
+
+ /**
+ * Sets the @p compositor of the model group.
+ *
+ * @see ModelCompositor
+ */
+ void setCompositor(ModelCompositor compositor);
+
+ /**
+ * Returns the compositor of the model group.
+ */
+ ModelCompositor compositor() const;
+
+ /**
+ * Sets the list of @p particles of the model group.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#mg-particles">Particles Definition</a>
+ */
+ void setParticles(const XsdParticle::List &particles);
+
+ /**
+ * Returns the list of particles of the model group.
+ */
+ XsdParticle::List particles() const;
+
+ private:
+ ModelCompositor m_compositor;
+ XsdParticle::List m_particles;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdnotation.cpp b/src/xmlpatterns/schema/qxsdnotation.cpp
new file mode 100644
index 0000000000..cfa0cd34cd
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdnotation.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdnotation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdNotation::setPublicId(const DerivedString<TypeToken>::Ptr &id)
+{
+ m_publicId = id;
+}
+
+DerivedString<TypeToken>::Ptr XsdNotation::publicId() const
+{
+ return m_publicId;
+}
+
+void XsdNotation::setSystemId(const AnyURI::Ptr &id)
+{
+ m_systemId = id;
+}
+
+AnyURI::Ptr XsdNotation::systemId() const
+{
+ return m_systemId;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdnotation_p.h b/src/xmlpatterns/schema/qxsdnotation_p.h
new file mode 100644
index 0000000000..dc1d597fa8
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdnotation_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdNotation_H
+#define Patternist_XsdNotation_H
+
+#include "qanyuri_p.h"
+#include "qderivedstring_p.h"
+#include "qnamedschemacomponent_p.h"
+#include "qxsdannotated_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD notation object, which should not
+ * be confused with the atomic type @c xs:NOTATION.
+ *
+ * This class represents the <em>notation</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#cNotation_Declarations">here</a>.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#XS-NotationDecl">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdNotation : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdNotation> Ptr;
+ typedef QList<XsdNotation::Ptr> List;
+
+ /**
+ * Sets the public @p identifier of the notation.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#nd-public_identifier">Public Identifier Definition</a>
+ */
+ void setPublicId(const DerivedString<TypeToken>::Ptr &identifier);
+
+ /**
+ * Returns the public identifier of the notation.
+ */
+ DerivedString<TypeToken>::Ptr publicId() const;
+
+ /**
+ * Sets the system @p identifier of the notation.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#nd-system_identifier">System Identifier Definition</a>
+ */
+ void setSystemId(const AnyURI::Ptr &identifier);
+
+ /**
+ * Returns the system identifier of the notation.
+ */
+ AnyURI::Ptr systemId() const;
+
+ private:
+ DerivedString<TypeToken>::Ptr m_publicId;
+ AnyURI::Ptr m_systemId;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdparticle.cpp b/src/xmlpatterns/schema/qxsdparticle.cpp
new file mode 100644
index 0000000000..a2671faf08
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdparticle.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdparticle_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdParticle::XsdParticle()
+ : m_minimumOccurs(1)
+ , m_maximumOccurs(1)
+ , m_maximumOccursUnbounded(false)
+{
+}
+
+void XsdParticle::setMinimumOccurs(unsigned int occurs)
+{
+ m_minimumOccurs = occurs;
+}
+
+unsigned int XsdParticle::minimumOccurs() const
+{
+ return m_minimumOccurs;
+}
+
+void XsdParticle::setMaximumOccurs(unsigned int occurs)
+{
+ m_maximumOccurs = occurs;
+}
+
+unsigned int XsdParticle::maximumOccurs() const
+{
+ return m_maximumOccurs;
+}
+
+void XsdParticle::setMaximumOccursUnbounded(bool unbounded)
+{
+ m_maximumOccursUnbounded = unbounded;
+}
+
+bool XsdParticle::maximumOccursUnbounded() const
+{
+ return m_maximumOccursUnbounded;
+}
+
+void XsdParticle::setTerm(const XsdTerm::Ptr &term)
+{
+ m_term = term;
+}
+
+XsdTerm::Ptr XsdParticle::term() const
+{
+ return m_term;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdparticle_p.h b/src/xmlpatterns/schema/qxsdparticle_p.h
new file mode 100644
index 0000000000..61e3eb3c11
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdparticle_p.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdParticle_H
+#define Patternist_XsdParticle_H
+
+#include "qnamedschemacomponent_p.h"
+#include "qxsdterm_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD particle object.
+ *
+ * This class represents the <em>particle</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#cParticles">here</a>.
+ *
+ * It contains information about the number of occurrence and a reference to
+ * either an <em>element</em> object, a <em>group</em> object or an <em>any</em> object.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSParticle">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdParticle : public NamedSchemaComponent
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdParticle> Ptr;
+ typedef QList<XsdParticle::Ptr> List;
+
+ /**
+ * Creates a new particle object.
+ */
+ XsdParticle();
+
+ /**
+ * Sets the minimum @p occurrence of the particle.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#p-min_occurs">Minimum Occurrence Definition</a>
+ */
+ void setMinimumOccurs(unsigned int occurrence);
+
+ /**
+ * Returns the minimum occurrence of the particle.
+ */
+ unsigned int minimumOccurs() const;
+
+ /**
+ * Sets the maximum @p occurrence of the particle.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#p-max_occurs">Maximum Occurrence Definition</a>
+ */
+ void setMaximumOccurs(unsigned int occurrence);
+
+ /**
+ * Returns the maximum occurrence of the particle.
+ *
+ * @note This value has only a meaning if maximumOccursUnbounded is @c false.
+ */
+ unsigned int maximumOccurs() const;
+
+ /**
+ * Sets whether the maximum occurrence of the particle is unbounded.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#p-max_occurs">Maximum Occurrence Definition</a>
+ */
+ void setMaximumOccursUnbounded(bool unbounded);
+
+ /**
+ * Returns whether the maximum occurrence of the particle is unbounded.
+ */
+ bool maximumOccursUnbounded() const;
+
+ /**
+ * Sets the @p term of the particle.
+ *
+ * The term can be an element, a model group or an element wildcard.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#p-term">Term Definition</a>
+ */
+ void setTerm(const XsdTerm::Ptr &term);
+
+ /**
+ * Returns the term of the particle.
+ */
+ XsdTerm::Ptr term() const;
+
+ private:
+ unsigned int m_minimumOccurs;
+ unsigned int m_maximumOccurs;
+ bool m_maximumOccursUnbounded;
+ XsdTerm::Ptr m_term;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdparticlechecker.cpp b/src/xmlpatterns/schema/qxsdparticlechecker.cpp
new file mode 100644
index 0000000000..1bdef0062e
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdparticlechecker.cpp
@@ -0,0 +1,510 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdparticlechecker_p.h"
+
+#include "qxsdelement_p.h"
+#include "qxsdmodelgroup_p.h"
+#include "qxsdschemahelper_p.h"
+#include "qxsdstatemachine_p.h"
+#include "qxsdstatemachinebuilder_p.h"
+#include "qxsdtypechecker_p.h"
+
+#include <QtCore/QFile>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+namespace QPatternist
+{
+ /**
+ * This template specialization is picked up by XsdStateMachine and allows us
+ * to print nice edge labels.
+ */
+ template <>
+ QString XsdStateMachine<XsdTerm::Ptr>::transitionTypeToString(XsdTerm::Ptr term) const
+ {
+ if (!term)
+ return QLatin1String("(empty)");
+
+ if (term->isElement()) {
+ return XsdElement::Ptr(term)->displayName(m_namePool);
+ } else if (term->isWildcard()) {
+ const XsdWildcard::Ptr wildcard(term);
+ return QLatin1String("(wildcard)");
+ } else {
+ return QString();
+ }
+ }
+}
+
+/**
+ * This method is used by the isUPAConform method to check whether @p term and @p otherTerm
+ * are the same resp. match each other.
+ */
+static bool termMatches(const XsdTerm::Ptr &term, const XsdTerm::Ptr &otherTerm, const NamePool::Ptr &namePool)
+{
+ if (term->isElement()) {
+ const XsdElement::Ptr element(term);
+
+ if (otherTerm->isElement()) {
+ // both, the term and the other term are elements
+
+ const XsdElement::Ptr otherElement(otherTerm);
+
+ // if they have the same name they match
+ if (element->name(namePool) == otherElement->name(namePool))
+ return true;
+
+ } else if (otherTerm->isWildcard()) {
+ // the term is an element and the other term a wildcard
+
+ const XsdWildcard::Ptr wildcard(otherTerm);
+
+ // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
+ QXmlName name = element->name(namePool);
+ if (name.namespaceURI() == StandardNamespaces::empty)
+ name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace()));
+
+ // if the wildcards namespace constraint allows the elements name, they match
+ if (XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, namePool))
+ return true;
+ }
+ } else if (term->isWildcard()) {
+ const XsdWildcard::Ptr wildcard(term);
+
+ if (otherTerm->isElement()) {
+ // the term is a wildcard and the other term an element
+
+ const XsdElement::Ptr otherElement(otherTerm);
+
+ // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
+ QXmlName name = otherElement->name(namePool);
+ if (name.namespaceURI() == StandardNamespaces::empty)
+ name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace()));
+
+ // if the wildcards namespace constraint allows the elements name, they match
+ if (XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, namePool))
+ return true;
+
+ } else if (otherTerm->isWildcard()) {
+ // both, the term and the other term are wildcards
+
+ const XsdWildcard::Ptr otherWildcard(otherTerm);
+
+ // check if the range of the wildcard overlaps.
+ const XsdWildcard::Ptr intersectionWildcard = XsdSchemaHelper::wildcardIntersection(wildcard, otherWildcard);
+ if (!intersectionWildcard ||
+ (intersectionWildcard && !(intersectionWildcard->namespaceConstraint()->variety() != XsdWildcard::NamespaceConstraint::Not && intersectionWildcard->namespaceConstraint()->namespaces().isEmpty())))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * This method is used by the subsumes algorithm to check whether the @p derivedTerm is validly derived from the @p baseTerm.
+ *
+ * @param baseTerm The term of the base component (type or group).
+ * @param derivedTerm The term of the derived component (type or group).
+ * @param particles A hash to map the passed base and derived term to the particles they belong to.
+ * @param context The schema context.
+ * @param errorMsg The error message in the case that an error occurs.
+ */
+static bool derivedTermValid(const XsdTerm::Ptr &baseTerm, const XsdTerm::Ptr &derivedTerm, const QHash<XsdTerm::Ptr, XsdParticle::Ptr> &particles, const XsdSchemaContext::Ptr &context, QString &errorMsg)
+{
+ const NamePool::Ptr namePool(context->namePool());
+
+ // find the particles where the base and derived term belongs to
+ const XsdParticle::Ptr baseParticle = particles.value(baseTerm);
+ const XsdParticle::Ptr derivedParticle = particles.value(derivedTerm);
+
+ // check that an empty particle can not be derived from a non-empty particle
+ if (derivedParticle && baseParticle) {
+ if (XsdSchemaHelper::isParticleEmptiable(derivedParticle) && !XsdSchemaHelper::isParticleEmptiable(baseParticle)) {
+ errorMsg = QtXmlPatterns::tr("empty particle cannot be derived from non-empty particle");
+ return false;
+ }
+ }
+
+ if (baseTerm->isElement()) {
+ const XsdElement::Ptr element(baseTerm);
+
+ if (derivedTerm->isElement()) {
+ // if both terms are elements
+
+ const XsdElement::Ptr derivedElement(derivedTerm);
+
+ // check names are equal
+ if (element->name(namePool) != derivedElement->name(namePool)) {
+ errorMsg = QtXmlPatterns::tr("derived particle is missing element %1").arg(formatKeyword(element->displayName(namePool)));
+ return false;
+ }
+
+ // check value constraints are equal (if available)
+ if (element->valueConstraint() && element->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
+ if (!derivedElement->valueConstraint()) {
+ errorMsg = QtXmlPatterns::tr("derived element %1 is missing value constraint as defined in base particle").arg(formatKeyword(derivedElement->displayName(namePool)));
+ return false;
+ }
+
+ if (derivedElement->valueConstraint()->variety() != XsdElement::ValueConstraint::Fixed) {
+ errorMsg = QtXmlPatterns::tr("derived element %1 has weaker value constraint than base particle").arg(formatKeyword(derivedElement->displayName(namePool)));
+ return false;
+ }
+
+ const QSourceLocation dummyLocation(QUrl(QLatin1String("http://dummy.org")), 1, 1);
+ const XsdTypeChecker checker(context, QVector<QXmlName>(), dummyLocation);
+ if (!checker.valuesAreEqual(element->valueConstraint()->value(), derivedElement->valueConstraint()->value(), derivedElement->type())) {
+ errorMsg = QtXmlPatterns::tr("fixed value constraint of element %1 differs from value constraint in base particle").arg(formatKeyword(derivedElement->displayName(namePool)));
+ return false;
+ }
+ }
+
+ // check that a derived element can not be nillable if the base element is not nillable
+ if (!element->isNillable() && derivedElement->isNillable()) {
+ errorMsg = QtXmlPatterns::tr("derived element %1 cannot be nillable as base element is not nillable").arg(formatKeyword(derivedElement->displayName(namePool)));
+ return false;
+ }
+
+ // check that the constraints of the derived element are more strict then the constraints of the base element
+ const XsdElement::BlockingConstraints baseConstraints = element->disallowedSubstitutions();
+ const XsdElement::BlockingConstraints derivedConstraints = derivedElement->disallowedSubstitutions();
+ if ((baseConstraints & XsdElement::RestrictionConstraint) && !(derivedConstraints & XsdElement::RestrictionConstraint) ||
+ (baseConstraints & XsdElement::ExtensionConstraint) && !(derivedConstraints & XsdElement::ExtensionConstraint) ||
+ (baseConstraints & XsdElement::SubstitutionConstraint) && !(derivedConstraints & XsdElement::SubstitutionConstraint)) {
+ errorMsg = QtXmlPatterns::tr("block constraints of derived element %1 must not be more weaker than in the base element").arg(formatKeyword(derivedElement->displayName(namePool)));
+ return false;
+ }
+
+ // if the type of both elements is the same we can stop testing here
+ if (element->type()->name(namePool) == derivedElement->type()->name(namePool))
+ return true;
+
+ // check that the type of the derived element can validly derived from the type of the base element
+ if (derivedElement->type()->isSimpleType()) {
+ if (!XsdSchemaHelper::isSimpleDerivationOk(derivedElement->type(), element->type(), SchemaType::DerivationConstraints())) {
+ errorMsg = QtXmlPatterns::tr("simple type of derived element %1 cannot be validly derived from base element").arg(formatKeyword(derivedElement->displayName(namePool)));
+ return false;
+ }
+ } else if (derivedElement->type()->isComplexType()) {
+ if (!XsdSchemaHelper::isComplexDerivationOk(derivedElement->type(), element->type(), SchemaType::DerivationConstraints())) {
+ errorMsg = QtXmlPatterns::tr("complex type of derived element %1 cannot be validly derived from base element").arg(formatKeyword(derivedElement->displayName(namePool)));
+ return false;
+ }
+ }
+
+ // if both, derived and base element, have a complex type that contains a particle itself, apply the subsumes algorithm
+ // recursive on their particles
+ if (element->type()->isComplexType() && derivedElement->type()->isComplexType()) {
+ if (element->type()->isDefinedBySchema() && derivedElement->type()->isDefinedBySchema()) {
+ const XsdComplexType::Ptr baseType(element->type());
+ const XsdComplexType::Ptr derivedType(derivedElement->type());
+ if ((baseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly ||
+ baseType->contentType()->variety() == XsdComplexType::ContentType::Mixed) &&
+ (derivedType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly ||
+ derivedType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) {
+
+ return XsdParticleChecker::subsumes(baseType->contentType()->particle(), derivedType->contentType()->particle(), context, errorMsg);
+ }
+ }
+ }
+
+ return true;
+ } else if (derivedTerm->isWildcard()) {
+ // derive a wildcard from an element is not allowed
+ errorMsg = QtXmlPatterns::tr("element %1 is missing in derived particle").arg(formatKeyword(element->displayName(namePool)));
+ return false;
+ }
+ } else if (baseTerm->isWildcard()) {
+ const XsdWildcard::Ptr wildcard(baseTerm);
+
+ if (derivedTerm->isElement()) {
+ // the base term is a wildcard and derived term an element
+
+ const XsdElement::Ptr derivedElement(derivedTerm);
+
+ // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
+ QXmlName name = derivedElement->name(namePool);
+ if (name.namespaceURI() == StandardNamespaces::empty)
+ name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace()));
+
+ // check that name of the element is allowed by the wildcards namespace constraint
+ if (!XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, namePool)) {
+ errorMsg = QtXmlPatterns::tr("element %1 does not match namespace constraint of wildcard in base particle").arg(formatKeyword(derivedElement->displayName(namePool)));
+ return false;
+ }
+
+ } else if (derivedTerm->isWildcard()) {
+ // both, derived and base term are wildcards
+
+ const XsdWildcard::Ptr derivedWildcard(derivedTerm);
+
+ // check that the derived wildcard is a valid subset of the base wildcard
+ if (!XsdSchemaHelper::isWildcardSubset(derivedWildcard, wildcard)) {
+ errorMsg = QtXmlPatterns::tr("wildcard in derived particle is not a valid subset of wildcard in base particle");
+ return false;
+ }
+
+ if (!XsdSchemaHelper::checkWildcardProcessContents(wildcard, derivedWildcard)) {
+ errorMsg = QtXmlPatterns::tr("processContent of wildcard in derived particle is weaker than wildcard in base particle");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+typedef QHash<QXmlName, XsdElement::Ptr> ElementHash;
+
+/**
+ * Internal helper method that checks if the given @p particle contains an element with the
+ * same name and type twice.
+ */
+static bool hasDuplicatedElementsInternal(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool, ElementHash &hash, XsdElement::Ptr &conflictingElement)
+{
+ const XsdTerm::Ptr term = particle->term();
+ if (term->isElement()) {
+ const XsdElement::Ptr mainElement(term);
+ XsdElement::List substGroups = mainElement->substitutionGroups();
+ if (substGroups.isEmpty())
+ substGroups << mainElement;
+
+ for (int i = 0; i < substGroups.count(); ++i) {
+ const XsdElement::Ptr element = substGroups.at(i);
+ if (hash.contains(element->name(namePool))) {
+ if (element->type()->name(namePool) != hash.value(element->name(namePool))->type()->name(namePool)) {
+ conflictingElement = element;
+ return true;
+ }
+ } else {
+ hash.insert(element->name(namePool), element);
+ }
+ }
+ } else if (term->isModelGroup()) {
+ const XsdModelGroup::Ptr group(term);
+ const XsdParticle::List particles = group->particles();
+ for (int i = 0; i < particles.count(); ++i) {
+ if (hasDuplicatedElementsInternal(particles.at(i), namePool, hash, conflictingElement))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool XsdParticleChecker::hasDuplicatedElements(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool, XsdElement::Ptr &conflictingElement)
+{
+ ElementHash hash;
+ return hasDuplicatedElementsInternal(particle, namePool, hash, conflictingElement);
+}
+
+bool XsdParticleChecker::isUPAConform(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool)
+{
+ /**
+ * The algorithm is implemented like described in http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html#S2.2
+ */
+
+ // create a state machine for the given particle
+ XsdStateMachine<XsdTerm::Ptr> stateMachine(namePool);
+
+ XsdStateMachineBuilder builder(&stateMachine, namePool);
+ const XsdStateMachine<XsdTerm::Ptr>::StateId endState = builder.reset();
+ const XsdStateMachine<XsdTerm::Ptr>::StateId startState = builder.buildParticle(particle, endState);
+ builder.addStartState(startState);
+
+/*
+ static int counter = 0;
+ {
+ QFile file(QString("/tmp/file_upa%1.dot").arg(counter));
+ file.open(QIODevice::WriteOnly);
+ stateMachine.outputGraph(&file, "Base");
+ file.close();
+ }
+ ::system(QString("dot -Tpng /tmp/file_upa%1.dot -o/tmp/file_upa%1.png").arg(counter).toLatin1().data());
+*/
+ const XsdStateMachine<XsdTerm::Ptr> dfa = stateMachine.toDFA();
+/*
+ {
+ QFile file(QString("/tmp/file_upa%1dfa.dot").arg(counter));
+ file.open(QIODevice::WriteOnly);
+ dfa.outputGraph(&file, "Base");
+ file.close();
+ }
+ ::system(QString("dot -Tpng /tmp/file_upa%1dfa.dot -o/tmp/file_upa%1dfa.png").arg(counter).toLatin1().data());
+*/
+ const QHash<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateType> states = dfa.states();
+ const QHash<XsdStateMachine<XsdTerm::Ptr>::StateId, QHash<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > > transitions = dfa.transitions();
+
+ // the basic idea of that algorithm is to iterate over all states of that machine and check that no two edges
+ // that match on the same term leave a state, so for a given term it should always be obvious which edge to take
+ QHashIterator<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateType> stateIt(states);
+ while (stateIt.hasNext()) { // iterate over all states
+ stateIt.next();
+
+ // fetch all transitions the current state allows
+ const QHash<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > currentTransitions = transitions.value(stateIt.key());
+ QHashIterator<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > transitionIt(currentTransitions);
+ while (transitionIt.hasNext()) { // iterate over all transitions
+ transitionIt.next();
+
+ if (transitionIt.value().size() > 1) {
+ // we have one state with two edges leaving it, that means
+ // the XsdTerm::Ptr exists twice, that is an error
+ return false;
+ }
+
+ QHashIterator<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > innerTransitionIt(currentTransitions);
+ while (innerTransitionIt.hasNext()) { // iterate over all transitions again, as we have to compare all transitions with all
+ innerTransitionIt.next();
+
+ if (transitionIt.key() == innerTransitionIt.key()) // do no compare with ourself
+ continue;
+
+ // use the helper method termMatches to check if both term matches
+ if (termMatches(transitionIt.key(), innerTransitionIt.key(), namePool))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool XsdParticleChecker::subsumes(const XsdParticle::Ptr &particle, const XsdParticle::Ptr &derivedParticle, const XsdSchemaContext::Ptr &context, QString &errorMsg)
+{
+ /**
+ * The algorithm is implemented like described in http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html#S2.3
+ */
+
+ const NamePool::Ptr namePool(context->namePool());
+
+ XsdStateMachine<XsdTerm::Ptr> baseStateMachine(namePool);
+ XsdStateMachine<XsdTerm::Ptr> derivedStateMachine(namePool);
+
+ // build up state machines for both particles
+ {
+ XsdStateMachineBuilder builder(&baseStateMachine, namePool);
+ const XsdStateMachine<XsdTerm::Ptr>::StateId endState = builder.reset();
+ const XsdStateMachine<XsdTerm::Ptr>::StateId startState = builder.buildParticle(particle, endState);
+ builder.addStartState(startState);
+
+ baseStateMachine = baseStateMachine.toDFA();
+ }
+ {
+ XsdStateMachineBuilder builder(&derivedStateMachine, namePool);
+ const XsdStateMachine<XsdTerm::Ptr>::StateId endState = builder.reset();
+ const XsdStateMachine<XsdTerm::Ptr>::StateId startState = builder.buildParticle(derivedParticle, endState);
+ builder.addStartState(startState);
+
+ derivedStateMachine = derivedStateMachine.toDFA();
+ }
+
+ QHash<XsdTerm::Ptr, XsdParticle::Ptr> particlesHash = XsdStateMachineBuilder::particleLookupMap(particle);
+ particlesHash.unite(XsdStateMachineBuilder::particleLookupMap(derivedParticle));
+
+/*
+ static int counter = 0;
+ {
+ QFile file(QString("/tmp/file_base%1.dot").arg(counter));
+ file.open(QIODevice::WriteOnly);
+ baseStateMachine.outputGraph(&file, QLatin1String("Base"));
+ file.close();
+ }
+ {
+ QFile file(QString("/tmp/file_derived%1.dot").arg(counter));
+ file.open(QIODevice::WriteOnly);
+ derivedStateMachine.outputGraph(&file, QLatin1String("Base"));
+ file.close();
+ }
+ ::system(QString("dot -Tpng /tmp/file_base%1.dot -o/tmp/file_base%1.png").arg(counter).toLatin1().data());
+ ::system(QString("dot -Tpng /tmp/file_derived%1.dot -o/tmp/file_derived%1.png").arg(counter).toLatin1().data());
+*/
+
+ const XsdStateMachine<XsdTerm::Ptr>::StateId baseStartState = baseStateMachine.startState();
+ const QHash<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateType> baseStates = baseStateMachine.states();
+ const QHash<XsdStateMachine<XsdTerm::Ptr>::StateId, QHash<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > > baseTransitions = baseStateMachine.transitions();
+
+ const XsdStateMachine<XsdTerm::Ptr>::StateId derivedStartState = derivedStateMachine.startState();
+ const QHash<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateType> derivedStates = derivedStateMachine.states();
+ const QHash<XsdStateMachine<XsdTerm::Ptr>::StateId, QHash<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > > derivedTransitions = derivedStateMachine.transitions();
+
+ // @see http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html#S2.3.1
+
+ // define working set
+ QList<QPair<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateId> > workSet;
+ QList<QPair<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateId> > processedSet;
+
+ // 1) fill working set initially with start states
+ workSet.append(qMakePair<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateId>(baseStartState, derivedStartState));
+ processedSet.append(qMakePair<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateId>(baseStartState, derivedStartState));
+
+ while (!workSet.isEmpty()) { // while there are state sets to process
+
+ // 3) dequeue on state set
+ const QPair<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateId> set = workSet.takeFirst();
+
+ const QHash<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > derivedTrans = derivedTransitions.value(set.second);
+ QHashIterator<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > derivedIt(derivedTrans);
+
+ const QHash<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > baseTrans = baseTransitions.value(set.first);
+
+ while (derivedIt.hasNext()) {
+ derivedIt.next();
+
+ bool found = false;
+ QHashIterator<XsdTerm::Ptr, QVector<XsdStateMachine<XsdTerm::Ptr>::StateId> > baseIt(baseTrans);
+ while (baseIt.hasNext()) {
+ baseIt.next();
+ if (derivedTermValid(baseIt.key(), derivedIt.key(), particlesHash, context, errorMsg)) {
+ const QPair<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateId> endSet =
+ qMakePair<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateId>(baseIt.value().first(), derivedIt.value().first());
+ if (!processedSet.contains(endSet) && !workSet.contains(endSet)) {
+ workSet.append(endSet);
+ processedSet.append(endSet);
+ }
+
+ found = true;
+ }
+ }
+
+ if (!found) {
+ return false;
+ }
+ }
+ }
+
+ // 5)
+ QHashIterator<XsdStateMachine<XsdTerm::Ptr>::StateId, XsdStateMachine<XsdTerm::Ptr>::StateType> it(derivedStates);
+ while (it.hasNext()) {
+ it.next();
+
+ if (it.value() == XsdStateMachine<XsdTerm::Ptr>::EndState || it.value() == XsdStateMachine<XsdTerm::Ptr>::StartEndState) {
+ for (int i = 0; i < processedSet.count(); ++i) {
+ if (processedSet.at(i).second == it.key() &&
+ (baseStates.value(processedSet.at(i).first) != XsdStateMachine<XsdTerm::Ptr>::EndState &&
+ baseStates.value(processedSet.at(i).first) != XsdStateMachine<XsdTerm::Ptr>::StartEndState)) {
+ errorMsg = QtXmlPatterns::tr("derived particle allows content that is not allowed in the base particle");
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdparticlechecker_p.h b/src/xmlpatterns/schema/qxsdparticlechecker_p.h
new file mode 100644
index 0000000000..16a8d95254
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdparticlechecker_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdParticleChecker_H
+#define Patternist_XsdParticleChecker_H
+
+#include "qxsdelement_p.h"
+#include "qxsdparticle_p.h"
+#include "qxsdschemacontext_p.h"
+#include "qxsdwildcard_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A helper class to check validity of particles.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdParticleChecker
+ {
+ public:
+ /**
+ * Checks whether the given @p particle has two or more element
+ * declarations with the same name but different type definitions.
+ */
+ static bool hasDuplicatedElements(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool, XsdElement::Ptr &conflictingElement);
+
+ /**
+ * Checks whether the given @p particle is valid according the
+ * UPA (http://www.w3.org/TR/xmlschema-1/#cos-nonambig) constraint.
+ */
+ static bool isUPAConform(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool);
+
+ /**
+ * Checks whether the given @p particle subsumes the given @p derivedParticle.
+ * (http://www.w3.org/TR/xmlschema-1/#cos-particle-restrict)
+ */
+ static bool subsumes(const XsdParticle::Ptr &particle, const XsdParticle::Ptr &derivedParticle, const XsdSchemaContext::Ptr &context, QString &errorMsg);
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdreference.cpp b/src/xmlpatterns/schema/qxsdreference.cpp
new file mode 100644
index 0000000000..0a934ddaf1
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdreference.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdreference_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+bool XsdReference::isReference() const
+{
+ return true;
+}
+
+void XsdReference::setType(Type type)
+{
+ m_type = type;
+}
+
+XsdReference::Type XsdReference::type() const
+{
+ return m_type;
+}
+
+void XsdReference::setReferenceName(const QXmlName &referenceName)
+{
+ m_referenceName = referenceName;
+}
+
+QXmlName XsdReference::referenceName() const
+{
+ return m_referenceName;
+}
+
+void XsdReference::setSourceLocation(const QSourceLocation &location)
+{
+ m_sourceLocation = location;
+}
+
+QSourceLocation XsdReference::sourceLocation() const
+{
+ return m_sourceLocation;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdreference_p.h b/src/xmlpatterns/schema/qxsdreference_p.h
new file mode 100644
index 0000000000..afcca25f46
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdreference_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdReference_H
+#define Patternist_XsdReference_H
+
+#include "qxsdterm_p.h"
+
+#include <QtXmlPatterns/QSourceLocation>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A helper class for element and group reference resolving.
+ *
+ * For easy resolving of element and group references, we have this class
+ * that can be used as a place holder for the real element or group
+ * object it is referring to.
+ * So whenever the parser detects an element or group reference, it creates
+ * a XsdReference and returns it instead of the XsdElement or XsdModelGroup.
+ * During a later phase, the resolver will look for all XsdReferences
+ * in the schema and will replace them with their referring XsdElement or
+ * XsdModelGroup objects.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdReference : public XsdTerm
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdReference> Ptr;
+
+ /**
+ * Describes the type of the reference.
+ */
+ enum Type
+ {
+ Element, ///< The reference points to an element.
+ ModelGroup ///< The reference points to a model group.
+ };
+
+ /**
+ * Returns always @c true, used to avoid dynamic casts.
+ */
+ virtual bool isReference() const;
+
+ /**
+ * Sets the @p type of the reference.
+ *
+ * @see Type
+ */
+ void setType(Type type);
+
+ /**
+ * Returns the type of the reference.
+ */
+ Type type() const;
+
+ /**
+ * Sets the @p name of the referenced object.
+ *
+ * The name can either be a top-level element declaration
+ * or a top-level group declaration.
+ */
+ void setReferenceName(const QXmlName &ame);
+
+ /**
+ * Returns the name of the referenced object.
+ */
+ QXmlName referenceName() const;
+
+ /**
+ * Sets the source @p location where the reference is located.
+ */
+ void setSourceLocation(const QSourceLocation &location);
+
+ /**
+ * Returns the source location where the reference is located.
+ */
+ QSourceLocation sourceLocation() const;
+
+ private:
+ Type m_type;
+ QXmlName m_referenceName;
+ QSourceLocation m_sourceLocation;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschema.cpp b/src/xmlpatterns/schema/qxsdschema.cpp
new file mode 100644
index 0000000000..260b06b5ad
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschema.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdschema_p.h"
+
+#include <QtCore/QReadLocker>
+#include <QtCore/QWriteLocker>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchema::XsdSchema(const NamePool::Ptr &namePool)
+ : m_namePool(namePool)
+{
+}
+
+XsdSchema::~XsdSchema()
+{
+}
+
+NamePool::Ptr XsdSchema::namePool() const
+{
+ return m_namePool;
+}
+
+void XsdSchema::setTargetNamespace(const QString &targetNamespace)
+{
+ m_targetNamespace = targetNamespace;
+}
+
+QString XsdSchema::targetNamespace() const
+{
+ return m_targetNamespace;
+}
+
+void XsdSchema::addElement(const XsdElement::Ptr &element)
+{
+ const QWriteLocker locker(&m_lock);
+
+ m_elements.insert(element->name(m_namePool), element);
+}
+
+XsdElement::Ptr XsdSchema::element(const QXmlName &name) const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_elements.value(name);
+}
+
+XsdElement::List XsdSchema::elements() const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_elements.values();
+}
+
+void XsdSchema::addAttribute(const XsdAttribute::Ptr &attribute)
+{
+ const QWriteLocker locker(&m_lock);
+
+ m_attributes.insert(attribute->name(m_namePool), attribute);
+}
+
+XsdAttribute::Ptr XsdSchema::attribute(const QXmlName &name) const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_attributes.value(name);
+}
+
+XsdAttribute::List XsdSchema::attributes() const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_attributes.values();
+}
+
+void XsdSchema::addType(const SchemaType::Ptr &type)
+{
+ const QWriteLocker locker(&m_lock);
+
+ m_types.insert(type->name(m_namePool), type);
+}
+
+SchemaType::Ptr XsdSchema::type(const QXmlName &name) const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_types.value(name);
+}
+
+SchemaType::List XsdSchema::types() const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_types.values();
+}
+
+XsdSimpleType::List XsdSchema::simpleTypes() const
+{
+ QReadLocker locker(&m_lock);
+
+ XsdSimpleType::List retval;
+
+ const SchemaType::List types = m_types.values();
+ for (int i = 0; i < types.count(); ++i) {
+ if (types.at(i)->isSimpleType() && types.at(i)->isDefinedBySchema())
+ retval.append(types.at(i));
+ }
+
+ return retval;
+}
+
+XsdComplexType::List XsdSchema::complexTypes() const
+{
+ QReadLocker locker(&m_lock);
+
+ XsdComplexType::List retval;
+
+ const SchemaType::List types = m_types.values();
+ for (int i = 0; i < types.count(); ++i) {
+ if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema())
+ retval.append(types.at(i));
+ }
+
+ return retval;
+}
+
+void XsdSchema::addAnonymousType(const SchemaType::Ptr &type)
+{
+ const QWriteLocker locker(&m_lock);
+
+ // search for not used anonymous type name
+ QXmlName typeName = type->name(m_namePool);
+ while (m_anonymousTypes.contains(typeName)) {
+ typeName = m_namePool->allocateQName(QString(), QLatin1String("merged_") + m_namePool->stringForLocalName(typeName.localName()), QString());
+ }
+
+ m_anonymousTypes.insert(typeName, type);
+}
+
+SchemaType::List XsdSchema::anonymousTypes() const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_anonymousTypes.values();
+}
+
+void XsdSchema::addAttributeGroup(const XsdAttributeGroup::Ptr &group)
+{
+ const QWriteLocker locker(&m_lock);
+
+ m_attributeGroups.insert(group->name(m_namePool), group);
+}
+
+XsdAttributeGroup::Ptr XsdSchema::attributeGroup(const QXmlName name) const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_attributeGroups.value(name);
+}
+
+XsdAttributeGroup::List XsdSchema::attributeGroups() const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_attributeGroups.values();
+}
+
+void XsdSchema::addElementGroup(const XsdModelGroup::Ptr &group)
+{
+ const QWriteLocker locker(&m_lock);
+
+ m_elementGroups.insert(group->name(m_namePool), group);
+}
+
+XsdModelGroup::Ptr XsdSchema::elementGroup(const QXmlName &name) const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_elementGroups.value(name);
+}
+
+XsdModelGroup::List XsdSchema::elementGroups() const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_elementGroups.values();
+}
+
+void XsdSchema::addNotation(const XsdNotation::Ptr &notation)
+{
+ const QWriteLocker locker(&m_lock);
+
+ m_notations.insert(notation->name(m_namePool), notation);
+}
+
+XsdNotation::Ptr XsdSchema::notation(const QXmlName &name) const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_notations.value(name);
+}
+
+XsdNotation::List XsdSchema::notations() const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_notations.values();
+}
+
+void XsdSchema::addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint)
+{
+ const QWriteLocker locker(&m_lock);
+
+ m_identityConstraints.insert(constraint->name(m_namePool), constraint);
+}
+
+XsdIdentityConstraint::Ptr XsdSchema::identityConstraint(const QXmlName &name) const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_identityConstraints.value(name);
+}
+
+XsdIdentityConstraint::List XsdSchema::identityConstraints() const
+{
+ const QReadLocker locker(&m_lock);
+
+ return m_identityConstraints.values();
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschema_p.h b/src/xmlpatterns/schema/qxsdschema_p.h
new file mode 100644
index 0000000000..b41a2d5248
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschema_p.h
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchema_H
+#define Patternist_XsdSchema_H
+
+#include "qschematype_p.h"
+#include "qxsdannotated_p.h"
+#include "qxsdattribute_p.h"
+#include "qxsdattributegroup_p.h"
+#include "qxsdcomplextype_p.h"
+#include "qxsdelement_p.h"
+#include "qxsdidentityconstraint_p.h"
+#include "qxsdmodelgroup_p.h"
+#include "qxsdnotation_p.h"
+#include "qxsdsimpletype_p.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QReadWriteLock>
+
+/**
+ * @defgroup Patternist_schema XML Schema Processing
+ */
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD schema object.
+ *
+ * The class provides access to all components of a parsed XSD.
+ *
+ * @note In the documentation of this class objects, which are direct
+ * children of the <em>schema</em> object, are called top-level objects.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSModel">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSchema : public QSharedData, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdSchema> Ptr;
+ typedef QList<XsdSchema::Ptr> List;
+
+ /**
+ * Creates a new schema object.
+ *
+ * @param namePool The namepool that should be used for names of
+ * all schema components.
+ */
+ XsdSchema(const NamePool::Ptr &namePool);
+
+ /**
+ * Destroys the schema object.
+ */
+ ~XsdSchema();
+
+ /**
+ * Returns the namepool that is used for names of
+ * all schema components.
+ */
+ NamePool::Ptr namePool() const;
+
+ /**
+ * Sets the @p targetNamespace of the schema.
+ */
+ void setTargetNamespace(const QString &targetNamespace);
+
+ /**
+ * Returns the target namespace of the schema.
+ */
+ QString targetNamespace() const;
+
+ /**
+ * Adds a new top-level @p element to the schema.
+ *
+ * @param element The new element.
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#declare-element">Element Declaration</a>
+ */
+ void addElement(const XsdElement::Ptr &element);
+
+ /**
+ * Returns the top-level element of the schema with
+ * the given @p name or an empty pointer if none exist.
+ */
+ XsdElement::Ptr element(const QXmlName &name) const;
+
+ /**
+ * Returns the list of all top-level elements.
+ */
+ XsdElement::List elements() const;
+
+ /**
+ * Adds a new top-level @p attribute to the schema.
+ *
+ * @param attribute The new attribute.
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#declare-attribute">Attribute Declaration</a>
+ */
+ void addAttribute(const XsdAttribute::Ptr &attribute);
+
+ /**
+ * Returns the top-level attribute of the schema with
+ * the given @p name or an empty pointer if none exist.
+ */
+ XsdAttribute::Ptr attribute(const QXmlName &name) const;
+
+ /**
+ * Returns the list of all top-level attributes.
+ */
+ XsdAttribute::List attributes() const;
+
+ /**
+ * Adds a new top-level @p type to the schema.
+ * That can be a simple or a complex type.
+ *
+ * @param type The new type.
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#declare-datatype">Simple Type Declaration</a>
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#declare-type">Complex Type Declaration</a>
+ */
+ void addType(const SchemaType::Ptr &type);
+
+ /**
+ * Returns the top-level type of the schema with
+ * the given @p name or an empty pointer if none exist.
+ */
+ SchemaType::Ptr type(const QXmlName &name) const;
+
+ /**
+ * Returns the list of all top-level types.
+ */
+ SchemaType::List types() const;
+
+ /**
+ * Returns the list of all top-level simple types.
+ */
+ XsdSimpleType::List simpleTypes() const;
+
+ /**
+ * Returns the list of all top-level complex types.
+ */
+ XsdComplexType::List complexTypes() const;
+
+ /**
+ * Adds an anonymous @p type to the schema.
+ * Anonymous types have no name and are declared
+ * locally inside an element object.
+ *
+ * @param type The new anonymous type.
+ */
+ void addAnonymousType(const SchemaType::Ptr &type);
+
+ /**
+ * Returns the list of all anonymous types.
+ */
+ SchemaType::List anonymousTypes() const;
+
+ /**
+ * Adds a new top-level attribute @p group to the schema.
+ *
+ * @param group The new attribute group.
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#declare-attributeGroup">Attribute Group Declaration</a>
+ */
+ void addAttributeGroup(const XsdAttributeGroup::Ptr &group);
+
+ /**
+ * Returns the top-level attribute group of the schema with
+ * the given @p name or an empty pointer if none exist.
+ */
+ XsdAttributeGroup::Ptr attributeGroup(const QXmlName name) const;
+
+ /**
+ * Returns the list of all top-level attribute groups.
+ */
+ XsdAttributeGroup::List attributeGroups() const;
+
+ /**
+ * Adds a new top-level element @p group to the schema.
+ *
+ * @param group The new element group.
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#declare-namedModelGroup">Element Group Declaration</a>
+ */
+ void addElementGroup(const XsdModelGroup::Ptr &group);
+
+ /**
+ * Returns the top-level element group of the schema with
+ * the given @p name or an empty pointer if none exist.
+ */
+ XsdModelGroup::Ptr elementGroup(const QXmlName &name) const;
+
+ /**
+ * Returns the list of all top-level element groups.
+ */
+ XsdModelGroup::List elementGroups() const;
+
+ /**
+ * Adds a new top-level @p notation to the schema.
+ *
+ * @param notation The new notation.
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#declare-notation">Notation Declaration</a>
+ */
+ void addNotation(const XsdNotation::Ptr &notation);
+
+ /**
+ * Returns the top-level notation of the schema with
+ * the given @p name or an empty pointer if none exist.
+ */
+ XsdNotation::Ptr notation(const QXmlName &name) const;
+
+ /**
+ * Returns the list of all top-level notations.
+ */
+ XsdNotation::List notations() const;
+
+ /**
+ * Adds a new identity @p constraint to the schema.
+ */
+ void addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint);
+
+ /**
+ * Returns the identity constraint with the given @p name
+ * or an empty pointer if none exist.
+ */
+ XsdIdentityConstraint::Ptr identityConstraint(const QXmlName &name) const;
+
+ /**
+ * Returns the list of all identity constraints in this schema.
+ */
+ XsdIdentityConstraint::List identityConstraints() const;
+
+ private:
+ NamePool::Ptr m_namePool;
+ QString m_targetNamespace;
+ QHash<QXmlName, XsdElement::Ptr> m_elements;
+ QHash<QXmlName, XsdAttribute::Ptr> m_attributes;
+ QHash<QXmlName, SchemaType::Ptr> m_types;
+ QHash<QXmlName, SchemaType::Ptr> m_anonymousTypes;
+ QHash<QXmlName, XsdAttributeGroup::Ptr> m_attributeGroups;
+ QHash<QXmlName, XsdModelGroup::Ptr> m_elementGroups;
+ QHash<QXmlName, XsdNotation::Ptr> m_notations;
+ QHash<QXmlName, XsdIdentityConstraint::Ptr> m_identityConstraints;
+ mutable QReadWriteLock m_lock;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschemachecker.cpp b/src/xmlpatterns/schema/qxsdschemachecker.cpp
new file mode 100644
index 0000000000..2a6432792c
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemachecker.cpp
@@ -0,0 +1,2031 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdschemachecker_p.h"
+
+#include "qderivedinteger_p.h"
+#include "qderivedstring_p.h"
+#include "qpatternplatform_p.h"
+#include "qqnamevalue_p.h"
+#include "qsourcelocationreflection_p.h"
+#include "qvaluefactory_p.h"
+#include "qxsdattributereference_p.h"
+#include "qxsdparticlechecker_p.h"
+#include "qxsdreference_p.h"
+#include "qxsdschemacontext_p.h"
+#include "qxsdschemahelper_p.h"
+#include "qxsdschemaparsercontext_p.h"
+#include "qxsdschematypesfactory_p.h"
+#include "qxsdtypechecker_p.h"
+
+#include "qxsdschemachecker_helper.cpp"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchemaChecker::XsdSchemaChecker(const QExplicitlySharedDataPointer<XsdSchemaContext> &context, const XsdSchemaParserContext *parserContext)
+ : m_context(context)
+ , m_namePool(parserContext->namePool())
+ , m_schema(parserContext->schema())
+{
+ setupAllowedAtomicFacets();
+}
+
+XsdSchemaChecker::~XsdSchemaChecker()
+{
+}
+
+/*
+ * This method is called after the resolver has set the base type for every
+ * type and information about deriavtion and 'is simple type vs. is complex type'
+ * are available.
+ */
+void XsdSchemaChecker::basicCheck()
+{
+ // first check that there is no circular inheritance, only the
+ // wxsSuperType is used here
+ checkBasicCircularInheritances();
+
+ // check the basic constraints like simple type can not inherit from complex type etc.
+ checkBasicSimpleTypeConstraints();
+ checkBasicComplexTypeConstraints();
+}
+
+void XsdSchemaChecker::check()
+{
+ checkCircularInheritances();
+ checkInheritanceRestrictions();
+ checkSimpleDerivationRestrictions();
+ checkSimpleTypeConstraints();
+ checkComplexTypeConstraints();
+ checkDuplicatedAttributeUses();
+
+ checkElementConstraints();
+ checkAttributeConstraints();
+ checkAttributeUseConstraints();
+// checkElementDuplicates();
+}
+
+void XsdSchemaChecker::addComponentLocationHash(const ComponentLocationHash &hash)
+{
+ m_componentLocationHash.unite(hash);
+}
+
+/**
+ * Checks whether the @p otherType is the same as @p myType or if one of its
+ * ancestors is the same as @p myType.
+ */
+static bool matchesType(const SchemaType::Ptr &myType, const SchemaType::Ptr &otherType, QSet<SchemaType::Ptr> visitedTypes)
+{
+ bool retval = false;
+
+ if (otherType) {
+ if (visitedTypes.contains(otherType)) {
+ return true;
+ } else {
+ visitedTypes.insert(otherType);
+ }
+ // simple types can have different varieties, so we have to check each of them
+ if (otherType->isSimpleType()) {
+ const XsdSimpleType::Ptr simpleType = otherType;
+ if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
+ // for atomic type we use the same test as in SchemaType::wxsTypeMatches
+ retval = (myType == simpleType ? true : matchesType(myType, simpleType->wxsSuperType(), visitedTypes));
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
+ // for list type we test against the itemType property
+ retval = (myType == simpleType->itemType() ? true : matchesType(myType, simpleType->itemType()->wxsSuperType(), visitedTypes));
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
+ // for union type we test against each member type
+ const XsdSimpleType::List members = simpleType->memberTypes();
+ for (int i = 0; i < members.count(); ++i) {
+ if (myType == members.at(i) ? true : matchesType(myType, members.at(i)->wxsSuperType(), visitedTypes)) {
+ retval = true;
+ break;
+ }
+ }
+ } else {
+ // reached xsAnySimple type whichs category is None
+ retval = false;
+ }
+ } else {
+ // if no simple type we handle it like in SchemaType::wxsTypeMatches
+ retval = (myType == otherType ? true : matchesType(myType, otherType->wxsSuperType(), visitedTypes));
+ }
+ } else // if otherType is null it doesn't match
+ retval = false;
+
+ return retval;
+}
+
+/**
+ * Checks whether there is a circular inheritance for the union inheritance.
+ */
+static bool hasCircularUnionInheritance(const XsdSimpleType::Ptr &type, const SchemaType::Ptr &otherType, NamePool::Ptr &namePool)
+{
+ if (type == otherType) {
+ return true;
+ }
+
+ if (!otherType->isSimpleType() || !otherType->isDefinedBySchema()) {
+ return false;
+ }
+
+ const XsdSimpleType::Ptr simpleOtherType = otherType;
+
+ if (simpleOtherType->category() == XsdSimpleType::SimpleTypeUnion) {
+ const XsdSimpleType::List memberTypes = simpleOtherType->memberTypes();
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ if (otherType->wxsSuperType() == type) {
+ return true;
+ }
+ if (hasCircularUnionInheritance(type, memberTypes.at(i), namePool)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static inline bool wxsTypeMatches(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, QSet<SchemaType::Ptr> &visitedTypes, SchemaType::Ptr &conflictingType)
+{
+ if (!otherType)
+ return false;
+
+ if (visitedTypes.contains(otherType)) { // inheritance loop detected
+ conflictingType = otherType;
+ return true;
+ } else {
+ visitedTypes.insert(otherType);
+ }
+
+ if (type == otherType)
+ return true;
+
+ return wxsTypeMatches(type, otherType->wxsSuperType(), visitedTypes, conflictingType);
+}
+
+void XsdSchemaChecker::checkBasicCircularInheritances()
+{
+ // check all global types...
+ SchemaType::List types = m_schema->types();
+
+ // .. and anonymous types
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+ const QSourceLocation location = sourceLocationForType(type);
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 3)
+
+ // check normal base type inheritance
+ QSet<SchemaType::Ptr> visitedTypes;
+ SchemaType::Ptr conflictingType;
+
+ if (wxsTypeMatches(type, type->wxsSuperType(), visitedTypes, conflictingType)) {
+ if (conflictingType)
+ m_context->error(QtXmlPatterns::tr("%1 has inheritance loop in its base type %2")
+ .arg(formatType(m_namePool, type))
+ .arg(formatType(m_namePool, conflictingType)),
+ XsdSchemaContext::XSDError, location);
+ else
+ m_context->error(QtXmlPatterns::tr("circular inheritance of base type %1").arg(formatType(m_namePool, type)), XsdSchemaContext::XSDError, location);
+
+ return;
+ }
+ }
+}
+
+void XsdSchemaChecker::checkCircularInheritances()
+{
+ // check all global types...
+ SchemaType::List types = m_schema->types();
+
+ // .. and anonymous types
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+ const QSourceLocation location = sourceLocationForType(type);
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 3)
+
+ // check normal base type inheritance
+ QSet<SchemaType::Ptr> visitedTypes;
+ if (matchesType(type, type->wxsSuperType(), visitedTypes)) {
+ m_context->error(QtXmlPatterns::tr("circular inheritance of base type %1").arg(formatType(m_namePool, type)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // check union member inheritance
+ if (type->isSimpleType() && type->isDefinedBySchema()) {
+ const XsdSimpleType::Ptr simpleType = type;
+ if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
+ const XsdSimpleType::List memberTypes = simpleType->memberTypes();
+ for (int j = 0; j < memberTypes.count(); ++j) {
+ if (hasCircularUnionInheritance(simpleType, memberTypes.at(j), m_namePool)) {
+ m_context->error(QtXmlPatterns::tr("circular inheritance of union %1").arg(formatType(m_namePool, type)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+void XsdSchemaChecker::checkInheritanceRestrictions()
+{
+ // check all global types...
+ SchemaType::List types = m_schema->types();
+
+ // .. and anonymous types
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+ const QSourceLocation location = sourceLocationForType(type);
+
+ // check inheritance restrictions given by final property of base class
+ const SchemaType::Ptr baseType = type->wxsSuperType();
+ if (baseType->isDefinedBySchema()) {
+ if ((type->derivationMethod() == SchemaType::DerivationRestriction) && (baseType->derivationConstraints() & SchemaType::RestrictionConstraint)) {
+ m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by restriction as the latter defines it as final")
+ .arg(formatType(m_namePool, type))
+ .arg(formatType(m_namePool, baseType)), XsdSchemaContext::XSDError, location);
+ return;
+ } else if ((type->derivationMethod() == SchemaType::DerivationExtension) && (baseType->derivationConstraints() & SchemaType::ExtensionConstraint)) {
+ m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by extension as the latter defines it as final")
+ .arg(formatType(m_namePool, type))
+ .arg(formatType(m_namePool, baseType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ }
+}
+
+void XsdSchemaChecker::checkBasicSimpleTypeConstraints()
+{
+ // check all global types...
+ SchemaType::List types = m_schema->types();
+
+ // .. and anonymous types
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+
+ if (!type->isSimpleType())
+ continue;
+
+ const XsdSimpleType::Ptr simpleType = type;
+
+ const QSourceLocation location = sourceLocation(simpleType);
+
+ // check inheritance restrictions of simple type defined by schema constraints
+ const SchemaType::Ptr baseType = simpleType->wxsSuperType();
+
+ if (baseType->isComplexType() && (simpleType->name(m_namePool) != BuiltinTypes::xsAnySimpleType->name(m_namePool))) {
+ m_context->error(QtXmlPatterns::tr("base type of simple type %1 cannot be complex type %2")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatType(m_namePool, baseType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ if (baseType == BuiltinTypes::xsAnyType) {
+ if (type->name(m_namePool) != BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
+ m_context->error(QtXmlPatterns::tr("simple type %1 cannot have direct base type %2")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatType(m_namePool, BuiltinTypes::xsAnyType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ }
+}
+
+void XsdSchemaChecker::checkSimpleTypeConstraints()
+{
+ // check all global types...
+ SchemaType::List types = m_schema->types();
+
+ // .. and anonymous types
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+
+ if (!type->isSimpleType())
+ continue;
+
+ const XsdSimpleType::Ptr simpleType = type;
+
+ const QSourceLocation location = sourceLocation(simpleType);
+
+ if (simpleType->category() == XsdSimpleType::None) {
+ // additional checks
+ // check that no user defined type has xs:AnySimpleType as base type (except xs:AnyAtomicType)
+ if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
+ if (simpleType->name(m_namePool) != BuiltinTypes::xsAnyAtomicType->name(m_namePool)) {
+ m_context->error(QtXmlPatterns::tr("simple type %1 is not allowed to have base type %2")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatType(m_namePool, simpleType->wxsSuperType())),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ // check that no user defined type has xs:AnyAtomicType as base type
+ if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnyAtomicType->name(m_namePool)) {
+ m_context->error(QtXmlPatterns::tr("simple type %1 is not allowed to have base type %2")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatType(m_namePool, simpleType->wxsSuperType())),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#d0e37310
+ if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
+ // 1.1
+ if ((simpleType->wxsSuperType()->category() != XsdSimpleType::SimpleTypeAtomic) && (simpleType->name(m_namePool) != BuiltinTypes::xsAnyAtomicType->name(m_namePool))) {
+ m_context->error(QtXmlPatterns::tr("simple type %1 can only have simple atomic type as base type")
+ .arg(formatType(m_namePool, simpleType)),
+ XsdSchemaContext::XSDError, location);
+ }
+ // 1.2
+ if (simpleType->wxsSuperType()->derivationConstraints() & SchemaType::RestrictionConstraint) {
+ m_context->error(QtXmlPatterns::tr("simple type %1 cannot derive from %2 as the latter defines restriction as final")
+ .arg(formatType(m_namePool, simpleType->wxsSuperType()))
+ .arg(formatType(m_namePool, simpleType)),
+ XsdSchemaContext::XSDError, location);
+ }
+
+ // 1.3
+ // checked by checkConstrainingFacets already
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
+ const AnySimpleType::Ptr itemType = simpleType->itemType();
+
+ // 2.1 or @see http://www.w3.org/TR/xmlschema-2/#cos-list-of-atomic
+ if (itemType->category() != SchemaType::SimpleTypeAtomic && itemType->category() != SchemaType::SimpleTypeUnion) {
+ m_context->error(QtXmlPatterns::tr("variety of item type of %1 must be either atomic or union").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 2.1 second part
+ if (itemType->category() == SchemaType::SimpleTypeUnion && itemType->isDefinedBySchema()) {
+ const XsdSimpleType::Ptr simpleItemType = itemType;
+ const AnySimpleType::List memberTypes = simpleItemType->memberTypes();
+ for (int j = 0; j < memberTypes.count(); ++j) {
+ if (memberTypes.at(j)->category() != SchemaType::SimpleTypeAtomic) {
+ m_context->error(QtXmlPatterns::tr("variety of member types of %1 must be atomic").arg(formatType(m_namePool, simpleItemType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ }
+
+ // 2.2.1
+ if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
+ if (itemType->isSimpleType() && itemType->isDefinedBySchema()) {
+ const XsdSimpleType::Ptr simpleItemType = itemType;
+
+ // 2.2.1.1
+ if (simpleItemType->derivationConstraints() & XsdSimpleType::ListConstraint) {
+ m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by list as the latter defines it as final")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatType(m_namePool, simpleItemType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 2.2.1.2
+ const XsdFacet::Hash facets = simpleType->facets();
+ XsdFacet::HashIterator it(facets);
+
+ bool invalidFacetFound = false;
+ while (it.hasNext()) {
+ it.next();
+ if (it.key() != XsdFacet::WhiteSpace) {
+ invalidFacetFound = true;
+ break;
+ }
+ }
+
+ if (invalidFacetFound) {
+ m_context->error(QtXmlPatterns::tr("simple type %1 is only allowed to have %2 facet")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatKeyword("whiteSpace")),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ } else { // 2.2.2
+ // 2.2.2.1
+ if (simpleType->wxsSuperType()->category() != XsdSimpleType::SimpleTypeList) {
+ m_context->error(QtXmlPatterns::tr("base type of simple type %1 must have variety of type list").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 2.2.2.2
+ if (simpleType->wxsSuperType()->derivationConstraints() & SchemaType::RestrictionConstraint) {
+ m_context->error(QtXmlPatterns::tr("base type of simple type %1 has defined derivation by restriction as final").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 2.2.2.3
+ if (!XsdSchemaHelper::isSimpleDerivationOk(itemType, XsdSimpleType::Ptr(simpleType->wxsSuperType())->itemType(), SchemaType::DerivationConstraints())) {
+ m_context->error(QtXmlPatterns::tr("item type of base type does not match item type of %1").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 2.2.2.4
+ const XsdFacet::Hash facets = simpleType->facets();
+ XsdFacet::HashIterator it(facets);
+
+ bool invalidFacetFound = false;
+ XsdFacet::Type invalidFacetType = XsdFacet::None;
+ while (it.hasNext()) {
+ it.next();
+ const XsdFacet::Type facetType = it.key();
+ if (facetType != XsdFacet::Length &&
+ facetType != XsdFacet::MinimumLength &&
+ facetType != XsdFacet::MaximumLength &&
+ facetType != XsdFacet::WhiteSpace &&
+ facetType != XsdFacet::Pattern &&
+ facetType != XsdFacet::Enumeration) {
+ invalidFacetType = facetType;
+ invalidFacetFound = true;
+ break;
+ }
+ }
+
+ if (invalidFacetFound) {
+ m_context->error(QtXmlPatterns::tr("simple type %1 contains not allowed facet type %2")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatKeyword(XsdFacet::typeName(invalidFacetType))),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 2.2.2.5
+ // TODO: check value constraints
+ }
+
+
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
+ const AnySimpleType::List memberTypes = simpleType->memberTypes();
+
+ if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) { // 3.1.1
+ // 3.3.1.1
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ const AnySimpleType::Ptr memberType = memberTypes.at(i);
+
+ if (memberType->derivationConstraints() & XsdSimpleType::UnionConstraint) {
+ m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by union as the latter defines it as final")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatType(m_namePool, memberType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+
+ // 3.3.1.2
+ if (!simpleType->facets().isEmpty()) {
+ m_context->error(QtXmlPatterns::tr("%1 is not allowed to have any facets")
+ .arg(formatType(m_namePool, simpleType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ } else {
+ // 3.1.2.1
+ if (simpleType->wxsSuperType()->category() != SchemaType::SimpleTypeUnion) {
+ m_context->error(QtXmlPatterns::tr("base type %1 of simple type %2 must have variety of union")
+ .arg(formatType(m_namePool, simpleType->wxsSuperType()))
+ .arg(formatType(m_namePool, simpleType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 3.1.2.2
+ if (simpleType->wxsSuperType()->derivationConstraints() & SchemaType::DerivationRestriction) {
+ m_context->error(QtXmlPatterns::tr("base type %1 of simple type %2 is not allowed to have restriction in %3 attribute")
+ .arg(formatType(m_namePool, simpleType->wxsSuperType()))
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatAttribute("final")),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ //3.1.2.3
+ if (simpleType->wxsSuperType()->isDefinedBySchema()) {
+ const XsdSimpleType::Ptr simpleBaseType(simpleType->wxsSuperType());
+
+ AnySimpleType::List baseMemberTypes = simpleBaseType->memberTypes();
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ const AnySimpleType::Ptr memberType = memberTypes.at(i);
+ const AnySimpleType::Ptr baseMemberType = baseMemberTypes.at(i);
+
+ if (!XsdSchemaHelper::isSimpleDerivationOk(memberType, baseMemberType, SchemaType::DerivationConstraints())) {
+ m_context->error(QtXmlPatterns::tr("member type %1 cannot be derived from member type %2 of %3's base type %4")
+ .arg(formatType(m_namePool, memberType))
+ .arg(formatType(m_namePool, baseMemberType))
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatType(m_namePool, simpleBaseType)),
+ XsdSchemaContext::XSDError, location);
+ }
+ }
+ }
+
+ // 3.1.2.4
+ const XsdFacet::Hash facets = simpleType->facets();
+ XsdFacet::HashIterator it(facets);
+
+ bool invalidFacetFound = false;
+ XsdFacet::Type invalidFacetType = XsdFacet::None;
+ while (it.hasNext()) {
+ it.next();
+ const XsdFacet::Type facetType = it.key();
+ if (facetType != XsdFacet::Pattern &&
+ facetType != XsdFacet::Enumeration) {
+ invalidFacetType = facetType;
+ invalidFacetFound = true;
+ break;
+ }
+ }
+
+ if (invalidFacetFound) {
+ m_context->error(QtXmlPatterns::tr("simple type %1 contains not allowed facet type %2")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatKeyword(XsdFacet::typeName(invalidFacetType))),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 3.1.2.5
+ // TODO: check value constraints
+ }
+ }
+ }
+}
+
+void XsdSchemaChecker::checkBasicComplexTypeConstraints()
+{
+ // check all global types...
+ SchemaType::List types = m_schema->types();
+
+ // .. and anonymous types
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+
+ if (!type->isComplexType() || !type->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType = type;
+
+ const QSourceLocation location = sourceLocation(complexType);
+
+ // check inheritance restrictions of complex type defined by schema constraints
+ const SchemaType::Ptr baseType = complexType->wxsSuperType();
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 2)
+ if (baseType->isSimpleType() && (complexType->derivationMethod() != XsdComplexType::DerivationExtension)) {
+ m_context->error(QtXmlPatterns::tr("derivation method of %1 must be extension because the base type %2 is a simple type")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, baseType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+}
+
+void XsdSchemaChecker::checkComplexTypeConstraints()
+{
+ // check all global types...
+ SchemaType::List types = m_schema->types();
+
+ // .. and anonymous types
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+
+ if (!type->isComplexType() || !type->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType = type;
+
+ const QSourceLocation location = sourceLocation(complexType);
+
+ if (complexType->contentType()->particle()) {
+ XsdElement::Ptr duplicatedElement;
+ if (XsdParticleChecker::hasDuplicatedElements(complexType->contentType()->particle(), m_namePool, duplicatedElement)) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 has duplicated element %2 in its content model")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatKeyword(duplicatedElement->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ if (!XsdParticleChecker::isUPAConform(complexType->contentType()->particle(), m_namePool)) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 has non-deterministic content")
+ .arg(formatType(m_namePool, complexType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+
+ // check inheritance restrictions of complex type defined by schema constraints
+ const SchemaType::Ptr baseType = complexType->wxsSuperType();
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-ct-extends
+ if (complexType->derivationMethod() == XsdComplexType::DerivationExtension) {
+ if (baseType->isComplexType() && baseType->isDefinedBySchema()) {
+ const XsdComplexType::Ptr complexBaseType = baseType;
+
+ // we can skip 1.1 here, as it is tested in checkInheritanceRestrictions() already
+
+ // 1.2 and 1.3
+ QString errorMsg;
+ if (!XsdSchemaHelper::isValidAttributeUsesExtension(complexType->attributeUses(), complexBaseType->attributeUses(),
+ complexType->attributeWildcard(), complexBaseType->attributeWildcard(), m_context, errorMsg)) {
+ m_context->error(QtXmlPatterns::tr("attributes of complex type %1 are not a valid extension of the attributes of base type %2: %3")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, baseType))
+ .arg(errorMsg),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 1.4
+ bool validContentType = false;
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
+ if (complexType->contentType()->simpleType() == complexBaseType->contentType()->simpleType()) {
+ validContentType = true; // 1.4.1
+ }
+ } else if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Empty) {
+ validContentType = true; // 1.4.2
+ } else { // 1.4.3
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) { // 1.4.3.1
+ if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Empty) {
+ validContentType = true; // 1.4.3.2.1
+ } else { // 1.4.3.2.2
+ if (complexType->contentType()->particle()) { // our own check
+ if ((complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) ||
+ (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) { // 1.4.3.2.2.1
+ if (isValidParticleExtension(complexType->contentType()->particle(), complexBaseType->contentType()->particle())) {
+ validContentType = true; // 1.4.3.2.2.2
+ }
+ }
+ }
+ // 1.4.3.2.2.3 and 1.4.3.2.2.4 handle 'open content' that we do not support yet
+ }
+ }
+ }
+
+ // 1.5 WTF?!?
+
+ if (!validContentType) {
+ m_context->error(QtXmlPatterns::tr("content model of complex type %1 is not a valid extension of content model of %2")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, complexBaseType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ } else if (baseType->isSimpleType()) {
+ // 2.1
+ if (complexType->contentType()->variety() != XsdComplexType::ContentType::Simple) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 must have simple content")
+ .arg(formatType(m_namePool, complexType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ if (complexType->contentType()->simpleType() != baseType) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 must have the same simple type as its base class %2")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, baseType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // 2.2 tested in checkInheritanceRestrictions() already
+ }
+ } else if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) {
+ // @see http://www.w3.org/TR/xmlschema11-1/#d0e21402
+ const SchemaType::Ptr baseType(complexType->wxsSuperType());
+
+ bool derivationOk = false;
+ QString errorMsg;
+
+ // we can partly skip 1 here, as it is tested in checkInheritanceRestrictions() already
+ if (baseType->isComplexType()) {
+
+ // 2.1
+ if (baseType->name(m_namePool) == BuiltinTypes::xsAnyType->name(m_namePool)) {
+ derivationOk = true;
+ }
+
+ if (baseType->isDefinedBySchema()) {
+ const XsdComplexType::Ptr complexBaseType(baseType);
+
+ // 2.2.1
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
+ // 2.2.2.1
+ if (XsdSchemaHelper::isSimpleDerivationOk(complexType->contentType()->simpleType(), complexBaseType->contentType()->simpleType(), SchemaType::DerivationConstraints()))
+ derivationOk = true;
+
+ // 2.2.2.2
+ if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed) {
+ if (XsdSchemaHelper::isParticleEmptiable(complexBaseType->contentType()->particle()))
+ derivationOk = true;
+ }
+ }
+
+ // 2.3.1
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty) {
+ // 2.3.2.1
+ if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Empty)
+ derivationOk = true;
+
+ // 2.3.2.2
+ if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed) {
+ if (XsdSchemaHelper::isParticleEmptiable(complexBaseType->contentType()->particle()))
+ derivationOk = true;
+ }
+ }
+
+ // 2.4.1.1
+ if (((complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) &&
+ (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) ||
+ // 2.4.1.2
+ (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) {
+
+ // 2.4.2
+ if (XsdParticleChecker::subsumes(complexBaseType->contentType()->particle(), complexType->contentType()->particle(), m_context, errorMsg))
+ derivationOk = true;
+ }
+ }
+ }
+
+ if (!derivationOk) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 cannot be derived from base type %2%3")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, baseType))
+ .arg(errorMsg.isEmpty() ? QString() : QLatin1String(": ") + errorMsg),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ if (baseType->isDefinedBySchema()) {
+ const XsdComplexType::Ptr complexBaseType(baseType);
+
+ QString errorMsg;
+ if (!XsdSchemaHelper::isValidAttributeUsesRestriction(complexType->attributeUses(), complexBaseType->attributeUses(),
+ complexType->attributeWildcard(), complexBaseType->attributeWildcard(), m_context, errorMsg)) {
+ m_context->error(QtXmlPatterns::tr("attributes of complex type %1 are not a valid restriction from the attributes of base type %2: %3")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, baseType))
+ .arg(errorMsg),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ }
+
+ // check that complex type with simple content is not allowed to inherit from
+ // built in complex type xs:AnyType
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
+ if (baseType->name(m_namePool) == BuiltinTypes::xsAnyType->name(m_namePool)) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 with simple content cannot be derived from complex base type %2")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, baseType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ }
+}
+
+void XsdSchemaChecker::checkSimpleDerivationRestrictions()
+{
+ // check all global types...
+ SchemaType::List types = m_schema->types();
+
+ // .. and anonymous types
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+
+ if (type->isComplexType())
+ continue;
+
+ if (type->category() != SchemaType::SimpleTypeList && type->category() != SchemaType::SimpleTypeUnion)
+ continue;
+
+ const XsdSimpleType::Ptr simpleType = type;
+ const QSourceLocation location = sourceLocation(simpleType);
+
+ // check all simple types derived by list
+ if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
+ const AnySimpleType::Ptr itemType = simpleType->itemType();
+
+ if (itemType->isComplexType()) {
+ m_context->error(QtXmlPatterns::tr("item type of simple type %1 cannot be a complex type")
+ .arg(formatType(m_namePool, simpleType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+
+ if (itemType->isSimpleType() && itemType->isDefinedBySchema()) {
+ const XsdSimpleType::Ptr simpleItemType = itemType;
+ if (simpleItemType->derivationConstraints() & XsdSimpleType::ListConstraint) {
+ m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by list as the latter defines it as final")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatType(m_namePool, simpleItemType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#cos-list-of-atomic
+ if (itemType->category() != SchemaType::SimpleTypeAtomic && itemType->category() != SchemaType::SimpleTypeUnion) {
+ m_context->error(QtXmlPatterns::tr("variety of item type of %1 must be either atomic or union").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ if (itemType->category() == SchemaType::SimpleTypeUnion && itemType->isDefinedBySchema()) {
+ const XsdSimpleType::Ptr simpleItemType = itemType;
+ const AnySimpleType::List memberTypes = simpleItemType->memberTypes();
+ for (int j = 0; j < memberTypes.count(); ++j) {
+ if (memberTypes.at(j)->category() != SchemaType::SimpleTypeAtomic) {
+ m_context->error(QtXmlPatterns::tr("variety of member types of %1 must be atomic").arg(formatType(m_namePool, simpleItemType)), XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ }
+ }
+
+ // check all simple types derived by union
+ if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
+ const AnySimpleType::List memberTypes = simpleType->memberTypes();
+
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ const AnySimpleType::Ptr memberType = memberTypes.at(i);
+
+ if (memberType->isComplexType()) {
+ m_context->error(QtXmlPatterns::tr("member type of simple type %1 cannot be a complex type")
+ .arg(formatType(m_namePool, simpleType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#cos-no-circular-unions
+ if (simpleType->name(m_namePool) == memberType->name(m_namePool)) {
+ m_context->error(QtXmlPatterns::tr("%1 is not allowed to have a member type with the same name as itself")
+ .arg(formatType(m_namePool, simpleType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+
+ if (memberType->isSimpleType() && memberType->isDefinedBySchema()) {
+ const XsdSimpleType::Ptr simpleMemberType = memberType;
+ if (simpleMemberType->derivationConstraints() & XsdSimpleType::UnionConstraint) {
+ m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by union as the latter defines it as final")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatType(m_namePool, simpleMemberType)),
+ XsdSchemaContext::XSDError, location);
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+void XsdSchemaChecker::checkConstrainingFacets()
+{
+ // first the global simple types
+ const SchemaType::List types = m_schema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ if (!(types.at(i)->isSimpleType()) || !(types.at(i)->isDefinedBySchema()))
+ continue;
+
+ const XsdSimpleType::Ptr simpleType = types.at(i);
+ checkConstrainingFacets(simpleType->facets(), simpleType);
+ }
+
+ // and afterwards all anonymous simple types
+ const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
+ for (int i = 0; i < anonymousTypes.count(); ++i) {
+ if (!(anonymousTypes.at(i)->isSimpleType()) || !(anonymousTypes.at(i)->isDefinedBySchema()))
+ continue;
+
+ const XsdSimpleType::Ptr simpleType = anonymousTypes.at(i);
+ checkConstrainingFacets(simpleType->facets(), simpleType);
+ }
+}
+
+void XsdSchemaChecker::checkConstrainingFacets(const XsdFacet::Hash &facets, const XsdSimpleType::Ptr &simpleType)
+{
+ if (facets.isEmpty())
+ return;
+
+ SchemaType::Ptr comparableBaseType;
+ if (!simpleType->wxsSuperType()->isDefinedBySchema())
+ comparableBaseType = simpleType->wxsSuperType();
+ else
+ comparableBaseType = simpleType->primitiveType();
+
+ const XsdSchemaSourceLocationReflection reflection(sourceLocation(simpleType));
+
+ // start checks
+ if (facets.contains(XsdFacet::Length)) {
+ const XsdFacet::Ptr lengthFacet = facets.value(XsdFacet::Length);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr lengthValue = lengthFacet->value();
+
+ // @see http://www.w3.org/TR/xmlschema-2/#length-minLength-maxLength
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ const XsdFacet::Ptr minLengthFacet = facets.value(XsdFacet::MinimumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr minLengthValue = minLengthFacet->value();
+
+ bool foundSuperMinimumLength = false;
+ SchemaType::Ptr baseType = simpleType->wxsSuperType();
+ while (baseType) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(baseType);
+ if (baseFacets.contains(XsdFacet::MinimumLength) && !baseFacets.contains(XsdFacet::Length)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr superValue(baseFacets.value(XsdFacet::MinimumLength)->value());
+ if (minLengthValue->toInteger() == superValue->toInteger()) {
+ foundSuperMinimumLength = true;
+ break;
+ }
+ }
+
+ baseType = baseType->wxsSuperType();
+ }
+
+ if ((minLengthValue->toInteger() > lengthValue->toInteger()) || !foundSuperMinimumLength) {
+ m_context->error(QtXmlPatterns::tr("%1 facet collides with %2 facet")
+ .arg(formatKeyword("length"))
+ .arg(formatKeyword("minLength")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#length-minLength-maxLength
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr maxLengthValue = maxLengthFacet->value();
+
+ bool foundSuperMaximumLength = false;
+ SchemaType::Ptr baseType = simpleType->wxsSuperType();
+ while (baseType) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(baseType);
+ if (baseFacets.contains(XsdFacet::MaximumLength) && !baseFacets.contains(XsdFacet::Length)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr superValue(baseFacets.value(XsdFacet::MaximumLength)->value());
+ if (maxLengthValue->toInteger() == superValue->toInteger()) {
+ foundSuperMaximumLength = true;
+ break;
+ }
+ }
+
+ baseType = baseType->wxsSuperType();
+ }
+
+ if ((maxLengthValue->toInteger() < lengthValue->toInteger()) || !foundSuperMaximumLength) {
+ m_context->error(QtXmlPatterns::tr("%1 facet collides with %2 facet")
+ .arg(formatKeyword("length"))
+ .arg(formatKeyword("maxLength")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#length-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::Length)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue = baseFacets.value(XsdFacet::Length)->value();
+ if (lengthValue->toInteger() != baseValue->toInteger()) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must have the same value as %2 facet of base type")
+ .arg(formatKeyword("length"))
+ .arg(formatKeyword("length")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ const XsdFacet::Ptr minLengthFacet = facets.value(XsdFacet::MinimumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr minLengthValue = minLengthFacet->value();
+
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr maxLengthValue = maxLengthFacet->value();
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minLength-less-than-equal-to-maxLength
+ if (maxLengthValue->toInteger() < minLengthValue->toInteger()) {
+ m_context->error(QtXmlPatterns::tr("%1 facet collides with %2 facet")
+ .arg(formatKeyword("minLength"))
+ .arg(formatKeyword("maxLength")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minLength-valid-restriction
+ //TODO: check parent facets
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minLength-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::MinimumLength)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue = baseFacets.value(XsdFacet::MinimumLength)->value();
+ if (minLengthValue->toInteger() < baseValue->toInteger()) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be equal or greater than %2 facet of base type")
+ .arg(formatKeyword("minLength"))
+ .arg(formatKeyword("minLength")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr maxLengthValue = maxLengthFacet->value();
+
+ // @see http://www.w3.org/TR/xmlschema-2/#maxLength-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::MaximumLength)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue(baseFacets.value(XsdFacet::MaximumLength)->value());
+ if (maxLengthValue->toInteger() > baseValue->toInteger()) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type")
+ .arg(formatKeyword("maxLength"))
+ .arg(formatKeyword("maxLength")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ // we keep the patterns in separated facets
+ // @see http://www.w3.org/TR/xmlschema-2/#src-multiple-patterns
+
+ // @see http://www.w3.org/TR/xmlschema-2/#cvc-pattern-valid
+ const XsdFacet::Ptr patternFacet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = patternFacet->multiValue();
+
+ for (int i = 0; i < multiValue.count(); ++i) {
+ const DerivedString<TypeString>::Ptr value = multiValue.at(i);
+ const QRegExp exp = PatternPlatform::parsePattern(value->stringValue(), m_context, &reflection);
+ if (!exp.isValid()) {
+ m_context->error(QtXmlPatterns::tr("%1 facet contains invalid regular expression").arg(formatKeyword("pattern")), XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ // @see http://www.w3.org/TR/xmlschema-2/#src-multiple-enumerations
+
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+
+ if (BuiltinTypes::xsNOTATION->wxsTypeMatches(simpleType)) {
+ const AtomicValue::List notationNames = facet->multiValue();
+ for (int k = 0; k < notationNames.count(); ++k) {
+ const QNameValue::Ptr notationName = notationNames.at(k);
+ if (!m_schema->notation(notationName->qName())) {
+ m_context->error(QtXmlPatterns::tr("unknown notation %1 used in %2 facet")
+ .arg(formatKeyword(m_namePool, notationName->qName()))
+ .arg(formatKeyword("enumeration")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ }
+ }
+ } else if (BuiltinTypes::xsQName->wxsTypeMatches(simpleType)) {
+ } else {
+ const XsdTypeChecker checker(m_context, QVector<QXmlName>(), sourceLocation(simpleType));
+
+ const AnySimpleType::Ptr baseType = simpleType->wxsSuperType();
+ const XsdFacet::Hash baseFacets = XsdTypeChecker::mergedFacetsForType(baseType, m_context);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ for (int k = 0; k < multiValue.count(); ++k) {
+ const QString stringValue = multiValue.at(k)->as<DerivedString<TypeString> >()->stringValue();
+ const QString actualValue = XsdTypeChecker::normalizedValue(stringValue, baseFacets);
+
+ QString errorMsg;
+ if (!checker.isValidString(actualValue, baseType, errorMsg)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet contains invalid value %2: %3")
+ .arg(formatKeyword("enumeration"))
+ .arg(formatData(stringValue))
+ .arg(errorMsg),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::WhiteSpace)) {
+ const XsdFacet::Ptr whiteSpaceFacet = facets.value(XsdFacet::WhiteSpace);
+ const DerivedString<TypeString>::Ptr whiteSpaceValue = whiteSpaceFacet->value();
+
+ // @see http://www.w3.org/TR/xmlschema-2/#whiteSpace-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::WhiteSpace)) {
+ const QString value = whiteSpaceValue->stringValue();
+ const QString baseValue = DerivedString<TypeString>::Ptr(baseFacets.value(XsdFacet::WhiteSpace)->value())->stringValue();
+ if (value == XsdSchemaToken::toString(XsdSchemaToken::Replace) || value == XsdSchemaToken::toString(XsdSchemaToken::Preserve)) {
+ if (baseValue == XsdSchemaToken::toString(XsdSchemaToken::Collapse)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet cannot be %2 or %3 if %4 facet of base type is %5")
+ .arg(formatKeyword("whiteSpace"))
+ .arg(formatData("replace"))
+ .arg(formatData("preserve"))
+ .arg(formatKeyword("whiteSpace"))
+ .arg(formatData("collapse")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ if (value == XsdSchemaToken::toString(XsdSchemaToken::Preserve) && baseValue == XsdSchemaToken::toString(XsdSchemaToken::Replace)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet cannot be %2 if %3 facet of base type is %4")
+ .arg(formatKeyword("whiteSpace"))
+ .arg(formatData("preserve"))
+ .arg(formatKeyword("whiteSpace"))
+ .arg(formatData("replace")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumInclusive);
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-less-than-equal-to-maxInclusive
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumInclusive);
+
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, maxFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet")
+ .arg(formatKeyword("minInclusive"))
+ .arg(formatKeyword("maxInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#maxInclusive-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type")
+ .arg(formatKeyword("maxInclusive"))
+ .arg(formatKeyword("maxInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (baseFacets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet of base type")
+ .arg(formatKeyword("maxInclusive"))
+ .arg(formatKeyword("maxExclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumExclusive);
+
+ // @see http://www.w3.org/TR/xmlschema-2/#maxInclusive-maxExclusive
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet and %2 facet cannot appear together")
+ .arg(formatKeyword("maxExclusive"))
+ .arg(formatKeyword("maxInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minExclusive-less-than-equal-to-maxExclusive
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumExclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, maxFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet")
+ .arg(formatKeyword("minExclusive"))
+ .arg(formatKeyword("maxExclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#maxExclusive-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type")
+ .arg(formatKeyword("maxExclusive"))
+ .arg(formatKeyword("maxExclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (baseFacets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type")
+ .arg(formatKeyword("maxExclusive"))
+ .arg(formatKeyword("maxInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (baseFacets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumInclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorLessOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be greater than %2 facet of base type")
+ .arg(formatKeyword("maxExclusive"))
+ .arg(formatKeyword("minInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (baseFacets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumExclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorLessOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be greater than %2 facet of base type")
+ .arg(formatKeyword("maxExclusive"))
+ .arg(formatKeyword("minExclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumExclusive);
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-minExclusive
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet and %2 facet cannot appear together")
+ .arg(formatKeyword("minExclusive"))
+ .arg(formatKeyword("minInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minExclusive-less-than-maxInclusive
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumInclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, maxFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet")
+ .arg(formatKeyword("minExclusive"))
+ .arg(formatKeyword("maxInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minExclusive-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumExclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorLessThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be greater than or equal to %2 facet of base type")
+ .arg(formatKeyword("minExclusive"))
+ .arg(formatKeyword("minExclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (baseFacets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet of base type")
+ .arg(formatKeyword("minExclusive"))
+ .arg(formatKeyword("maxExclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (baseFacets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type")
+ .arg(formatKeyword("minExclusive"))
+ .arg(formatKeyword("maxInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumInclusive);
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-less-than-maxExclusive
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumExclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, maxFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet")
+ .arg(formatKeyword("minInclusive"))
+ .arg(formatKeyword("maxExclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumInclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorLessThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be greater than or equal to %2 facet of base type")
+ .arg(formatKeyword("minInclusive"))
+ .arg(formatKeyword("minInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (baseFacets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumExclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorLessOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be greater than %2 facet of base type")
+ .arg(formatKeyword("minInclusive"))
+ .arg(formatKeyword("minExclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (baseFacets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type")
+ .arg(formatKeyword("minInclusive"))
+ .arg(formatKeyword("maxInclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ if (baseFacets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive);
+ if (comparableBaseType) {
+ if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet of base type")
+ .arg(formatKeyword("minInclusive"))
+ .arg(formatKeyword("maxExclusive")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::TotalDigits)) {
+ const XsdFacet::Ptr totalDigitsFacet = facets.value(XsdFacet::TotalDigits);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr totalDigitsValue = totalDigitsFacet->value();
+
+ // @see http://www.w3.org/TR/xmlschema-2/#totalDigits-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::TotalDigits)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::TotalDigits);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue = baseFacet->value();
+
+ if (totalDigitsValue->toInteger() > baseValue->toInteger()) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type")
+ .arg(formatKeyword("totalDigits"))
+ .arg(formatKeyword("totalDigits")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ if (facets.contains(XsdFacet::FractionDigits)) {
+ const XsdFacet::Ptr fractionDigitsFacet = facets.value(XsdFacet::FractionDigits);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr fractionDigitsValue = fractionDigitsFacet->value();
+
+ // http://www.w3.org/TR/xmlschema-2/#fractionDigits-totalDigits
+ if (facets.contains(XsdFacet::TotalDigits)) {
+ const XsdFacet::Ptr totalDigitsFacet = facets.value(XsdFacet::TotalDigits);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr totalDigitsValue = totalDigitsFacet->value();
+
+ if (fractionDigitsValue->toInteger() > totalDigitsValue->toInteger()) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet")
+ .arg(formatKeyword("fractionDigits"))
+ .arg(formatKeyword("totalDigits")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#fractionDigits-valid-restriction
+ if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) {
+ const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType());
+ if (baseFacets.contains(XsdFacet::FractionDigits)) {
+ const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::FractionDigits);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr baseValue = baseFacet->value();
+
+ if (fractionDigitsValue->toInteger() > baseValue->toInteger()) {
+ m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type")
+ .arg(formatKeyword("fractionDigits"))
+ .arg(formatKeyword("fractionDigits")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+
+
+ // check whether facets are allowed for simple types variety
+ if (simpleType->wxsSuperType()->category() == SchemaType::SimpleTypeAtomic) {
+ if (simpleType->primitiveType()) {
+ const QXmlName primitiveTypeName = simpleType->primitiveType()->name(m_namePool);
+ if (m_allowedAtomicFacets.contains(primitiveTypeName)) {
+ const QSet<XsdFacet::Type> allowedFacets = m_allowedAtomicFacets.value(primitiveTypeName);
+ QSet<XsdFacet::Type> availableFacets = facets.keys().toSet();
+
+ if (!availableFacets.subtract(allowedFacets).isEmpty()) {
+ m_context->error(QtXmlPatterns::tr("simple type contains not allowed facet %1")
+ .arg(formatKeyword(XsdFacet::typeName(availableFacets.toList().first()))),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ } else if (simpleType->wxsSuperType()->category() == SchemaType::SimpleTypeList) {
+ if (facets.contains(XsdFacet::MaximumInclusive) || facets.contains(XsdFacet::MinimumInclusive) ||
+ facets.contains(XsdFacet::MaximumExclusive) || facets.contains(XsdFacet::MinimumExclusive) ||
+ facets.contains(XsdFacet::TotalDigits) || facets.contains(XsdFacet::FractionDigits))
+ {
+ m_context->error(QtXmlPatterns::tr("%1, %2, %3, %4, %5 and %6 facets are not allowed when derived by list")
+ .arg(formatKeyword("maxInclusive"))
+ .arg(formatKeyword("maxExclusive"))
+ .arg(formatKeyword("minInclusive"))
+ .arg(formatKeyword("minExclusive"))
+ .arg(formatKeyword("totalDigits"))
+ .arg(formatKeyword("fractionDigits")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ }
+ } else if (simpleType->wxsSuperType()->category() == SchemaType::SimpleTypeUnion) {
+ if (facets.contains(XsdFacet::MaximumInclusive) || facets.contains(XsdFacet::MinimumInclusive) ||
+ facets.contains(XsdFacet::MaximumExclusive) || facets.contains(XsdFacet::MinimumExclusive) ||
+ facets.contains(XsdFacet::TotalDigits) || facets.contains(XsdFacet::FractionDigits) ||
+ facets.contains(XsdFacet::MinimumLength) || facets.contains(XsdFacet::MaximumLength) ||
+ facets.contains(XsdFacet::Length) || facets.contains(XsdFacet::WhiteSpace))
+ {
+ m_context->error(QtXmlPatterns::tr("only %1 and %2 facets are allowed when derived by union")
+ .arg(formatKeyword("pattern"))
+ .arg(formatKeyword("enumeration")),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ }
+ }
+
+ // check whether value of facet matches the value space of the simple types base type
+ const SchemaType::Ptr baseType = simpleType->wxsSuperType();
+ if (!baseType->isDefinedBySchema()) {
+ const XsdSchemaSourceLocationReflection reflection(sourceLocation(simpleType));
+
+ XsdFacet::HashIterator it(facets);
+ while (it.hasNext()) {
+ it.next();
+ const XsdFacet::Ptr facet = it.value();
+ if (facet->type() == XsdFacet::MaximumInclusive ||
+ facet->type() == XsdFacet::MaximumExclusive ||
+ facet->type() == XsdFacet::MinimumInclusive ||
+ facet->type() == XsdFacet::MinimumExclusive) {
+ const DerivedString<TypeString>::Ptr stringValue = facet->value();
+ const AtomicValue::Ptr value = ValueFactory::fromLexical(stringValue->stringValue(), baseType, m_context, &reflection);
+ if (value->hasError()) {
+ m_context->error(QtXmlPatterns::tr("%1 contains %2 facet with invalid data: %3")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatKeyword(XsdFacet::typeName(facet->type())))
+ .arg(formatData(stringValue->stringValue())),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+
+ // @see http://www.w3.org/TR/xmlschema-2/#enumeration-valid-restriction
+ if (facet->type() == XsdFacet::Enumeration && baseType != BuiltinTypes::xsNOTATION) {
+ const AtomicValue::List multiValue = facet->multiValue();
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString stringValue = DerivedString<TypeString>::Ptr(multiValue.at(j))->stringValue();
+ const AtomicValue::Ptr value = ValueFactory::fromLexical(stringValue, baseType, m_context, &reflection);
+ if (value->hasError()) {
+ m_context->error(QtXmlPatterns::tr("%1 contains %2 facet with invalid data: %3")
+ .arg(formatType(m_namePool, simpleType))
+ .arg(formatKeyword(XsdFacet::typeName(XsdFacet::Enumeration)))
+ .arg(formatData(stringValue)),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+void XsdSchemaChecker::checkDuplicatedAttributeUses()
+{
+ // first all global attribute groups
+ const XsdAttributeGroup::List attributeGroups = m_schema->attributeGroups();
+ for (int i = 0; i < attributeGroups.count(); ++i) {
+ const XsdAttributeGroup::Ptr attributeGroup = attributeGroups.at(i);
+ const XsdAttributeUse::List uses = attributeGroup->attributeUses();
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 4)
+ XsdAttribute::Ptr conflictingAttribute;
+ if (hasDuplicatedAttributeUses(uses, conflictingAttribute)) {
+ m_context->error(QtXmlPatterns::tr("attribute group %1 contains attribute %2 twice")
+ .arg(formatKeyword(attributeGroup->displayName(m_namePool)))
+ .arg(formatKeyword(conflictingAttribute->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, sourceLocation(attributeGroup));
+ return;
+ }
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 5)
+ if (hasMultipleIDAttributeUses(uses)) {
+ m_context->error(QtXmlPatterns::tr("attribute group %1 contains two different attributes that both have types derived from %2")
+ .arg(formatKeyword(attributeGroup->displayName(m_namePool)))
+ .arg(formatType(m_namePool, BuiltinTypes::xsID)),
+ XsdSchemaContext::XSDError, sourceLocation(attributeGroup));
+ return;
+ }
+
+ if (hasConstraintIDAttributeUse(uses, conflictingAttribute)) {
+ m_context->error(QtXmlPatterns::tr("attribute group %1 contains attribute %2 that has value constraint but type that inherits from %3")
+ .arg(formatKeyword(attributeGroup->displayName(m_namePool)))
+ .arg(formatKeyword(conflictingAttribute->displayName(m_namePool)))
+ .arg(formatType(m_namePool, BuiltinTypes::xsID)),
+ XsdSchemaContext::XSDError, sourceLocation(attributeGroup));
+ return;
+ }
+ }
+
+ // then the global and anonymous complex types
+ SchemaType::List types = m_schema->types();
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType = types.at(i);
+ const XsdAttributeUse::List attributeUses = complexType->attributeUses();
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 4)
+ XsdAttribute::Ptr conflictingAttribute;
+ if (hasDuplicatedAttributeUses(attributeUses, conflictingAttribute)) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 contains attribute %2 twice")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatKeyword(conflictingAttribute->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 5)
+ if (hasMultipleIDAttributeUses(attributeUses)) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 contains two different attributes that both have types derived from %2")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, BuiltinTypes::xsID)),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+
+ if (hasConstraintIDAttributeUse(attributeUses, conflictingAttribute)) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 contains attribute %2 that has value constraint but type that inherits from %3")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatKeyword(conflictingAttribute->displayName(m_namePool)))
+ .arg(formatType(m_namePool, BuiltinTypes::xsID)),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+ }
+}
+
+void XsdSchemaChecker::checkElementConstraints()
+{
+ const QSet<XsdElement::Ptr> elements = collectAllElements(m_schema);
+ QSetIterator<XsdElement::Ptr> it(elements);
+ while (it.hasNext()) {
+ const XsdElement::Ptr element = it.next();
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#e-props-correct
+
+ // 2 and xs:ID check
+ if (element->valueConstraint()) {
+ const SchemaType::Ptr type = element->type();
+
+ AnySimpleType::Ptr targetType;
+ if (type->isSimpleType() && type->category() == SchemaType::SimpleTypeAtomic) {
+ targetType = type;
+
+ // if it is a XsdSimpleType, use its primitive type as target type
+ if (type->isDefinedBySchema())
+ targetType = XsdSimpleType::Ptr(type)->primitiveType();
+
+ } else if (type->isComplexType() && type->isDefinedBySchema()) {
+ const XsdComplexType::Ptr complexType(type);
+
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
+ const AnySimpleType::Ptr simpleType = complexType->contentType()->simpleType();
+ if (simpleType->category() == AnySimpleType::SimpleTypeAtomic) {
+ targetType = simpleType;
+
+ if (simpleType->isDefinedBySchema())
+ targetType = XsdSimpleType::Ptr(simpleType)->primitiveType();
+ }
+ } else if (complexType->contentType()->variety() != XsdComplexType::ContentType::Mixed) {
+ m_context->error(QtXmlPatterns::tr("element %1 is not allowed to have a value constraint if its base type is complex")
+ .arg(formatKeyword(element->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, sourceLocation(element));
+ return;
+ }
+ }
+ if ((targetType == BuiltinTypes::xsID) || BuiltinTypes::xsID->wxsTypeMatches(type)) {
+ m_context->error(QtXmlPatterns::tr("element %1 is not allowed to have a value constraint if its type is derived from %2")
+ .arg(formatKeyword(element->displayName(m_namePool)))
+ .arg(formatType(m_namePool, BuiltinTypes::xsID)),
+ XsdSchemaContext::XSDError, sourceLocation(element));
+ return;
+ }
+
+ if (type->isSimpleType()) {
+ QString errorMsg;
+ if (!isValidValue(element->valueConstraint()->value(), type, errorMsg)) {
+ m_context->error(QtXmlPatterns::tr("value constraint of element %1 is not of elements type: %2")
+ .arg(formatKeyword(element->displayName(m_namePool)))
+ .arg(errorMsg),
+ XsdSchemaContext::XSDError, sourceLocation(element));
+ return;
+ }
+ } else if (type->isComplexType() && type->isDefinedBySchema()) {
+ const XsdComplexType::Ptr complexType(type);
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
+ QString errorMsg;
+ if (!isValidValue(element->valueConstraint()->value(), complexType->contentType()->simpleType(), errorMsg)) {
+ m_context->error(QtXmlPatterns::tr("value constraint of element %1 is not of elements type: %2")
+ .arg(formatKeyword(element->displayName(m_namePool)))
+ .arg(errorMsg),
+ XsdSchemaContext::XSDError, sourceLocation(element));
+ return;
+ }
+ }
+ }
+ }
+
+ if (!element->substitutionGroupAffiliations().isEmpty()) {
+ // 3
+ if (!element->scope() || element->scope()->variety() != XsdElement::Scope::Global) {
+ m_context->error(QtXmlPatterns::tr("element %1 is not allowed to have substitution group affiliation as it is no global element").arg(formatKeyword(element->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, sourceLocation(element));
+ return;
+ }
+
+ // 4
+ const XsdElement::List affiliations = element->substitutionGroupAffiliations();
+ for (int i = 0; i < affiliations.count(); ++i) {
+ const XsdElement::Ptr affiliation = affiliations.at(i);
+
+ bool derivationOk = false;
+ if (element->type()->isComplexType() && affiliation->type()->isComplexType()) {
+ if (XsdSchemaHelper::isComplexDerivationOk(element->type(), affiliation->type(), affiliation->substitutionGroupExclusions())) {
+ derivationOk = true;
+ }
+ }
+ if (element->type()->isComplexType() && affiliation->type()->isSimpleType()) {
+ if (XsdSchemaHelper::isComplexDerivationOk(element->type(), affiliation->type(), affiliation->substitutionGroupExclusions())) {
+ derivationOk = true;
+ }
+ }
+ if (element->type()->isSimpleType()) {
+ if (XsdSchemaHelper::isSimpleDerivationOk(element->type(), affiliation->type(), affiliation->substitutionGroupExclusions())) {
+ derivationOk = true;
+ }
+ }
+
+ if (!derivationOk) {
+ m_context->error(QtXmlPatterns::tr("type of element %1 cannot be derived from type of substitution group affiliation").arg(formatKeyword(element->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, sourceLocation(element));
+ return;
+ }
+ }
+
+ // 5 was checked in XsdSchemaResolver::resolveSubstitutionGroupAffiliations() already
+ }
+ }
+}
+
+void XsdSchemaChecker::checkAttributeConstraints()
+{
+ // all global attributes
+ XsdAttribute::List attributes = m_schema->attributes();
+
+ // and all local attributes
+ SchemaType::List types = m_schema->types();
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ if (!types.at(i)->isComplexType() || !types.at(i)->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType(types.at(i));
+ const XsdAttributeUse::List uses = complexType->attributeUses();
+ for (int j = 0; j < uses.count(); ++j)
+ attributes.append(uses.at(j)->attribute());
+ }
+
+ for (int i = 0; i < attributes.count(); ++i) {
+ const XsdAttribute::Ptr attribute = attributes.at(i);
+
+ if (!attribute->valueConstraint())
+ continue;
+
+ if (attribute->valueConstraint()->variety() == XsdAttribute::ValueConstraint::Default || attribute->valueConstraint()->variety() == XsdAttribute::ValueConstraint::Fixed) {
+ const SchemaType::Ptr type = attribute->type();
+
+ QString errorMsg;
+ if (!isValidValue(attribute->valueConstraint()->value(), attribute->type(), errorMsg)) {
+ m_context->error(QtXmlPatterns::tr("value constraint of attribute %1 is not of attributes type: %2")
+ .arg(formatKeyword(attribute->displayName(m_namePool)))
+ .arg(errorMsg),
+ XsdSchemaContext::XSDError, sourceLocation(attribute));
+ return;
+ }
+ }
+
+ if (BuiltinTypes::xsID->wxsTypeMatches(attribute->type())) {
+ m_context->error(QtXmlPatterns::tr("attribute %1 has value constraint but has type derived from %2")
+ .arg(formatKeyword(attribute->displayName(m_namePool)))
+ .arg(formatType(m_namePool, BuiltinTypes::xsID)),
+ XsdSchemaContext::XSDError, sourceLocation(attribute));
+ return;
+ }
+ }
+}
+
+bool XsdSchemaChecker::isValidValue(const QString &stringValue, const AnySimpleType::Ptr &type, QString &errorMsg) const
+{
+ if (BuiltinTypes::xsAnySimpleType->name(m_namePool) == type->name(m_namePool))
+ return true; // no need to check xs:anyType content
+
+ const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(type, m_context);
+ const QString actualValue = XsdTypeChecker::normalizedValue(stringValue, facets);
+
+ const XsdTypeChecker checker(m_context, QVector<QXmlName>(), QSourceLocation(QUrl(QLatin1String("http://dummy.org")), 1, 1));
+ return checker.isValidString(actualValue, type, errorMsg);
+}
+
+void XsdSchemaChecker::checkAttributeUseConstraints()
+{
+ XsdComplexType::List complexTypes;
+
+ SchemaType::List types = m_schema->types();
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+ if (type->isComplexType() && type->isDefinedBySchema())
+ complexTypes.append(XsdComplexType::Ptr(type));
+ }
+
+ for (int i = 0; i < complexTypes.count(); ++i) {
+ const XsdComplexType::Ptr complexType(complexTypes.at(i));
+ const SchemaType::Ptr baseType = complexType->wxsSuperType();
+ if (!baseType || !baseType->isComplexType() || !baseType->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexBaseType(baseType);
+
+ const XsdAttributeUse::List attributeUses = complexType->attributeUses();
+ QHash<QXmlName, XsdAttributeUse::Ptr> lookupHash;
+ for (int j = 0; j < attributeUses.count(); ++j)
+ lookupHash.insert(attributeUses.at(j)->attribute()->name(m_namePool), attributeUses.at(j));
+
+ const XsdAttributeUse::List baseAttributeUses = complexBaseType->attributeUses();
+ for (int j = 0; j < baseAttributeUses.count(); ++j) {
+ const XsdAttributeUse::Ptr baseAttributeUse = baseAttributeUses.at(j);
+
+ if (lookupHash.contains(baseAttributeUse->attribute()->name(m_namePool))) {
+ const XsdAttributeUse::Ptr attributeUse = lookupHash.value(baseAttributeUse->attribute()->name(m_namePool));
+
+ if (baseAttributeUse->useType() == XsdAttributeUse::RequiredUse) {
+ if (attributeUse->useType() == XsdAttributeUse::OptionalUse || attributeUse->useType() == XsdAttributeUse::ProhibitedUse) {
+ m_context->error(QtXmlPatterns::tr("%1 attribute in derived complex type must be %2 like in base type")
+ .arg(formatAttribute("use"))
+ .arg(formatData("required")),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+ }
+
+ if (baseAttributeUse->valueConstraint()) {
+ if (baseAttributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Fixed) {
+ if (!attributeUse->valueConstraint()) {
+ m_context->error(QtXmlPatterns::tr("attribute %1 in derived complex type must have %2 value constraint like in base type")
+ .arg(formatKeyword(attributeUse->attribute()->displayName(m_namePool)))
+ .arg(formatData("fixed")),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ } else {
+ if (attributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Fixed) {
+ const XsdTypeChecker checker(m_context, QVector<QXmlName>(), sourceLocation(complexType));
+ if (!checker.valuesAreEqual(attributeUse->valueConstraint()->value(), baseAttributeUse->valueConstraint()->value(), attributeUse->attribute()->type())) {
+ m_context->error(QtXmlPatterns::tr("attribute %1 in derived complex type must have the same %2 value constraint like in base type")
+ .arg(formatKeyword(attributeUse->attribute()->displayName(m_namePool)))
+ .arg(formatData("fixed")),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+ } else {
+ m_context->error(QtXmlPatterns::tr("attribute %1 in derived complex type must have %2 value constraint")
+ .arg(formatKeyword(attributeUse->attribute()->displayName(m_namePool)))
+ .arg(formatData("fixed")),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // additional check that process content property of attribute wildcard in derived type is
+ // not weaker than the wildcard in base type
+ const XsdWildcard::Ptr baseWildcard(complexBaseType->attributeWildcard());
+ const XsdWildcard::Ptr derivedWildcard(complexType->attributeWildcard());
+ if (baseWildcard && derivedWildcard) {
+ if (!XsdSchemaHelper::checkWildcardProcessContents(baseWildcard, derivedWildcard)) {
+ m_context->error(QtXmlPatterns::tr("processContent of base wildcard must be weaker than derived wildcard"), XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+ }
+ }
+}
+
+void XsdSchemaChecker::checkElementDuplicates()
+{
+ // check all global types...
+ SchemaType::List types = m_schema->types();
+
+ // .. and anonymous types
+ types << m_schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ const SchemaType::Ptr type = types.at(i);
+
+ if (!type->isComplexType() || !type->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType(type);
+
+ if ((complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) || (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) {
+ DuplicatedElementMap elementMap;
+ DuplicatedWildcardMap wildcardMap;
+
+ checkElementDuplicates(complexType->contentType()->particle(), elementMap, wildcardMap);
+ }
+ }
+}
+
+void XsdSchemaChecker::checkElementDuplicates(const XsdParticle::Ptr &particle, DuplicatedElementMap &elementMap, DuplicatedWildcardMap &wildcardMap)
+{
+ if (particle->term()->isElement()) {
+ const XsdElement::Ptr element(particle->term());
+
+ if (elementMap.contains(element->name(m_namePool))) {
+ if (element->type() != elementMap.value(element->name(m_namePool))) {
+ m_context->error(QtXmlPatterns::tr("element %1 exists twice with different types")
+ .arg(formatKeyword(element->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, sourceLocation(element));
+ return;
+ }
+ } else {
+ elementMap.insert(element->name(m_namePool), element->type());
+ }
+
+ // check substitution group affiliation
+ const XsdElement::List substElements = element->substitutionGroupAffiliations();
+ for (int i = 0; i < substElements.count(); ++i) {
+ const XsdElement::Ptr substElement = substElements.at(i);
+ if (elementMap.contains(substElement->name(m_namePool))) {
+ if (substElement->type() != elementMap.value(substElement->name(m_namePool))) {
+ m_context->error(QtXmlPatterns::tr("element %1 exists twice with different types")
+ .arg(formatKeyword(substElement->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, sourceLocation(element));
+ return;
+ }
+ } else {
+ elementMap.insert(substElement->name(m_namePool), substElement->type());
+ }
+ }
+ } else if (particle->term()->isModelGroup()) {
+ const XsdModelGroup::Ptr group(particle->term());
+ const XsdParticle::List particles = group->particles();
+ for (int i = 0; i < particles.count(); ++i)
+ checkElementDuplicates(particles.at(i), elementMap, wildcardMap);
+ } else if (particle->term()->isWildcard()) {
+ const XsdWildcard::Ptr wildcard(particle->term());
+
+ bool error = false;
+ if (!wildcardMap.contains(wildcard->namespaceConstraint()->variety())) {
+ if (!wildcardMap.isEmpty())
+ error = true;
+ } else {
+ const XsdWildcard::Ptr otherWildcard = wildcardMap.value(wildcard->namespaceConstraint()->variety());
+ if ((wildcard->processContents() != otherWildcard->processContents()) || (wildcard->namespaceConstraint()->namespaces() != otherWildcard->namespaceConstraint()->namespaces()))
+ error = true;
+ }
+
+ if (error) {
+ m_context->error(QtXmlPatterns::tr("particle contains non-deterministic wildcards"), XsdSchemaContext::XSDError, sourceLocation(wildcard));
+ return;
+ } else {
+ wildcardMap.insert(wildcard->namespaceConstraint()->variety(), wildcard);
+ }
+ }
+}
+
+QSourceLocation XsdSchemaChecker::sourceLocation(const NamedSchemaComponent::Ptr &component) const
+{
+ if (m_componentLocationHash.contains(component)) {
+ return m_componentLocationHash.value(component);
+ } else {
+ QSourceLocation location;
+ location.setLine(1);
+ location.setColumn(1);
+ location.setUri(QString::fromLatin1("dummyUri"));
+
+ return location;
+ }
+}
+
+QSourceLocation XsdSchemaChecker::sourceLocationForType(const SchemaType::Ptr &type) const
+{
+ if (type->isSimpleType())
+ return sourceLocation(XsdSimpleType::Ptr(type));
+ else
+ return sourceLocation(XsdComplexType::Ptr(type));
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp b/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp
new file mode 100644
index 0000000000..98c4c63dd7
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp
@@ -0,0 +1,276 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+bool XsdSchemaChecker::hasDuplicatedAttributeUses(const XsdAttributeUse::List &list, XsdAttribute::Ptr &conflictingAttribute) const
+{
+ const int length = list.count();
+
+ for (int i = 0; i < length; ++i) {
+ for (int j = 0; j < length; ++j) {
+ if (i == j)
+ continue;
+
+ if (list.at(i)->attribute()->name(m_namePool) == list.at(j)->attribute()->name(m_namePool)) {
+ conflictingAttribute = list.at(i)->attribute();
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool XsdSchemaChecker::hasMultipleIDAttributeUses(const XsdAttributeUse::List &list) const
+{
+ const int length = list.count();
+
+ bool hasIdDerivedAttribute = false;
+ for (int i = 0; i < length; ++i) {
+ if (BuiltinTypes::xsID->wxsTypeMatches(list.at(i)->attribute()->type())) {
+ if (hasIdDerivedAttribute)
+ return true;
+ else
+ hasIdDerivedAttribute = true;
+ }
+ }
+
+ return false;
+}
+
+bool XsdSchemaChecker::hasConstraintIDAttributeUse(const XsdAttributeUse::List &list, XsdAttribute::Ptr &conflictingAttribute) const
+{
+ const int length = list.count();
+
+ for (int i = 0; i < length; ++i) {
+ const XsdAttributeUse::Ptr attributeUse(list.at(i));
+ if (BuiltinTypes::xsID->wxsTypeMatches(attributeUse->attribute()->type())) {
+ if (attributeUse->valueConstraint()) {
+ conflictingAttribute = attributeUse->attribute();
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool XsdSchemaChecker::particleEqualsRecursively(const XsdParticle::Ptr &particle, const XsdParticle::Ptr &otherParticle) const
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-particle-extend
+ //TODO: find out what 'properties' of a particle should be checked here...
+
+ if (particle->minimumOccurs() != otherParticle->minimumOccurs())
+ return false;
+
+ if (particle->maximumOccursUnbounded() != otherParticle->maximumOccursUnbounded())
+ return false;
+
+ if (particle->maximumOccurs() != otherParticle->maximumOccurs())
+ return false;
+
+ const XsdTerm::Ptr term = particle->term();
+ const XsdTerm::Ptr otherTerm = otherParticle->term();
+
+ if (term->isElement() && !(otherTerm->isElement()))
+ return false;
+
+ if (term->isModelGroup() && !(otherTerm->isModelGroup()))
+ return false;
+
+ if (term->isWildcard() && !(otherTerm->isWildcard()))
+ return false;
+
+ if (term->isElement()) {
+ const XsdElement::Ptr element = term;
+ const XsdElement::Ptr otherElement = otherTerm;
+
+ if (element->name(m_namePool) != otherElement->name(m_namePool))
+ return false;
+
+ if (element->type()->name(m_namePool) != otherElement->type()->name(m_namePool))
+ return false;
+ }
+
+ if (term->isModelGroup()) {
+ const XsdModelGroup::Ptr group = term;
+ const XsdModelGroup::Ptr otherGroup = otherTerm;
+
+ if (group->particles().count() != otherGroup->particles().count())
+ return false;
+
+ for (int i = 0; i < group->particles().count(); ++i) {
+ if (!particleEqualsRecursively(group->particles().at(i), otherGroup->particles().at(i)))
+ return false;
+ }
+ }
+
+ if (term->isWildcard()) {
+ }
+
+ return true;
+}
+
+bool XsdSchemaChecker::isValidParticleExtension(const XsdParticle::Ptr &extension, const XsdParticle::Ptr &base) const
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-particle-extend
+
+ // 1
+ if (extension == base)
+ return true;
+
+ // 2
+ if (extension->minimumOccurs() == 1 && extension->maximumOccurs() == 1 && extension->maximumOccursUnbounded() == false) {
+ if (extension->term()->isModelGroup()) {
+ const XsdModelGroup::Ptr modelGroup = extension->term();
+ if (modelGroup->compositor() == XsdModelGroup::SequenceCompositor) {
+ if (particleEqualsRecursively(modelGroup->particles().first(), base))
+ return true;
+ }
+ }
+ }
+
+ // 3
+ if (extension->minimumOccurs() == base->minimumOccurs()) { // 3.1
+ if (extension->term()->isModelGroup() && base->term()->isModelGroup()) {
+ const XsdModelGroup::Ptr extensionGroup(extension->term());
+ const XsdModelGroup::Ptr baseGroup(base->term());
+
+ if (extensionGroup->compositor() == XsdModelGroup::AllCompositor && baseGroup->compositor() == XsdModelGroup::AllCompositor) {
+ const XsdParticle::List extensionParticles = extensionGroup->particles();
+ const XsdParticle::List baseParticles = baseGroup->particles();
+ for (int i = 0; i < baseParticles.count() && i < extensionParticles.count(); ++i) {
+ if (baseParticles.at(i) != extensionParticles.at(i))
+ return false;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+QSet<XsdElement::Ptr> collectAllElements(const XsdParticle::Ptr &particle)
+{
+ QSet<XsdElement::Ptr> elements;
+
+ const XsdTerm::Ptr term(particle->term());
+ if (term->isElement()) {
+ elements.insert(XsdElement::Ptr(term));
+ } else if (term->isModelGroup()) {
+ const XsdModelGroup::Ptr group(term);
+
+ for (int i = 0; i < group->particles().count(); ++i)
+ elements.unite(collectAllElements(group->particles().at(i)));
+ }
+
+ return elements;
+}
+
+QSet<XsdElement::Ptr> collectAllElements(const XsdSchema::Ptr &schema)
+{
+ QSet<XsdElement::Ptr> elements;
+
+ // collect global elements
+ const XsdElement::List elementList = schema->elements();
+ for (int i = 0; i < elementList.count(); ++i)
+ elements.insert(elementList.at(i));
+
+ // collect all elements from global groups
+ const XsdModelGroup::List groupList = schema->elementGroups();
+ for (int i = 0; i < groupList.count(); ++i) {
+ const XsdModelGroup::Ptr group(groupList.at(i));
+
+ for (int j = 0; j < group->particles().count(); ++j)
+ elements.unite(collectAllElements(group->particles().at(j)));
+ }
+
+ // collect all elements from complex type definitions
+ SchemaType::List types;
+ types << schema->types() << schema->anonymousTypes();
+
+ for (int i = 0; i < types.count(); ++i) {
+ if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema()) {
+ const XsdComplexType::Ptr complexType(types.at(i));
+ if (complexType->contentType()->particle())
+ elements.unite(collectAllElements(complexType->contentType()->particle()));
+ }
+ }
+
+ return elements;
+}
+
+bool XsdSchemaChecker::elementSequenceAccepted(const XsdModelGroup::Ptr &sequence, const XsdParticle::Ptr &particle) const
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cvc-accept
+
+ if (particle->term()->isWildcard()) { // 1
+ const XsdWildcard::Ptr wildcard(particle->term());
+
+ // 1.1
+ if ((unsigned int)sequence->particles().count() < particle->minimumOccurs())
+ return false;
+
+ // 1.2
+ if (!particle->maximumOccursUnbounded()) {
+ if ((unsigned int)sequence->particles().count() > particle->maximumOccurs())
+ return false;
+ }
+
+ // 1.3
+ const XsdParticle::List particles(sequence->particles());
+ for (int i = 0; i < particles.count(); ++i) {
+ if (particles.at(i)->term()->isElement()) {
+ if (!XsdSchemaHelper::wildcardAllowsExpandedName(XsdElement::Ptr(particles.at(i)->term())->name(m_namePool), wildcard, m_namePool))
+ return false;
+ }
+ }
+ } else if (particle->term()->isElement()) { // 2
+ const XsdElement::Ptr element(particle->term());
+
+ // 2.1
+ if ((unsigned int)sequence->particles().count() < particle->minimumOccurs())
+ return false;
+
+ // 2.2
+ if (!particle->maximumOccursUnbounded()) {
+ if ((unsigned int)sequence->particles().count() > particle->maximumOccurs())
+ return false;
+ }
+
+ // 2.3
+ const XsdParticle::List particles(sequence->particles());
+ for (int i = 0; i < particles.count(); ++i) {
+ bool isValid = false;
+ if (particles.at(i)->term()->isElement()) {
+ const XsdElement::Ptr seqElement(particles.at(i)->term());
+
+ // 2.3.1
+ if (element->name(m_namePool) == seqElement->name(m_namePool))
+ isValid = true;
+
+ // 2.3.2
+ if (element->scope() && element->scope()->variety() == XsdElement::Scope::Global) {
+ if (!(element->disallowedSubstitutions() & NamedSchemaComponent::SubstitutionConstraint)) {
+ //TODO: continue
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemachecker_p.h b/src/xmlpatterns/schema/qxsdschemachecker_p.h
new file mode 100644
index 0000000000..65fb87fe43
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemachecker_p.h
@@ -0,0 +1,254 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchemaChecker_H
+#define Patternist_XsdSchemaChecker_H
+
+#include "qschematype_p.h"
+#include "qxsdattribute_p.h"
+#include "qxsdattributegroup_p.h"
+#include "qxsdelement_p.h"
+#include "qxsdmodelgroup_p.h"
+#include "qxsdnotation_p.h"
+#include "qxsdschema_p.h"
+#include "qxsdsimpletype_p.h"
+
+#include <QtCore/QExplicitlySharedDataPointer>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ class XsdSchemaContext;
+ class XsdSchemaParserContext;
+
+ /**
+ * @short Encapsulates the checking of schema valitity after reference resolving has finished.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSchemaChecker : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdSchemaChecker> Ptr;
+
+ /**
+ * Creates a new schema checker.
+ *
+ * @param context The context that is used for customization.
+ * @param parserContext The context that contains all the data structures.
+ */
+ XsdSchemaChecker(const QExplicitlySharedDataPointer<XsdSchemaContext> &context, const XsdSchemaParserContext *parserContext);
+
+ /**
+ * Destroys the schema checker.
+ */
+ ~XsdSchemaChecker();
+
+ /**
+ * Starts a basic check process.
+ *
+ * This check only validates the basic super type inheritance
+ * of simple and complex types.
+ */
+ void basicCheck();
+
+ /**
+ * Starts the real check process.
+ */
+ void check();
+
+ /**
+ * Checks the constraining facets of all global and anonymous simple types for validity.
+ */
+ void checkConstrainingFacets();
+
+ /**
+ * Adds the component location hash, so the checker is able to report meaning full
+ * error messages.
+ */
+ void addComponentLocationHash(const QHash<NamedSchemaComponent::Ptr, QSourceLocation> &hash);
+
+ private:
+ void checkSimpleRestrictionBaseType();
+
+ /**
+ * Checks that no simple or complex type inherits itself.
+ */
+ void checkBasicCircularInheritances();
+
+ /**
+ * Checks the advanced circular inheritance.
+ */
+ void checkCircularInheritances();
+
+ /**
+ * Checks for inheritance restrictions given by final or finalDefault
+ * attributes.
+ */
+ void checkInheritanceRestrictions();
+
+ /**
+ * Checks for various constraints for simple types defined by schema.
+ */
+ void checkBasicSimpleTypeConstraints();
+ void checkSimpleTypeConstraints();
+
+ /**
+ * Checks for various constraints for complex types defined by schema.
+ */
+ void checkBasicComplexTypeConstraints();
+ void checkComplexTypeConstraints();
+
+ /**
+ * Checks for list and union derivation restrictions given by final or finalDefault
+ * attributes.
+ */
+ void checkSimpleDerivationRestrictions();
+
+ /**
+ * Checks the set of constraining @p facets that belongs to @p simpleType for validity.
+ */
+ void checkConstrainingFacets(const XsdFacet::Hash &facets, const XsdSimpleType::Ptr &simpleType);
+
+ /**
+ * Checks for duplicated attribute uses (attributes with the same name) inside a complex type.
+ */
+ void checkDuplicatedAttributeUses();
+
+ /**
+ * Check the element constraints.
+ */
+ void checkElementConstraints();
+
+ /**
+ * Check the attribute constraints.
+ */
+ void checkAttributeConstraints();
+
+ /**
+ * Check the attribute use constraints.
+ */
+ void checkAttributeUseConstraints();
+
+ /**
+ * A map used to find duplicated elements inside a model group.
+ */
+ typedef QHash<QXmlName, SchemaType::Ptr> DuplicatedElementMap;
+
+ /**
+ * A map used to find duplicated wildcards inside a model group.
+ */
+ typedef QHash<XsdWildcard::NamespaceConstraint::Variety, XsdWildcard::Ptr> DuplicatedWildcardMap;
+
+ /**
+ * Check for duplicated elements and element wildcards in all complex type particles.
+ */
+ void checkElementDuplicates();
+
+ /**
+ * Check for duplicated elements and element wildcards in the given @p particle.
+ *
+ * @param particle The particle to check.
+ * @param elementMap A map to find the duplicated elements.
+ * @param wildcardMap A map to find the duplicated element wildcards.
+ */
+ void checkElementDuplicates(const XsdParticle::Ptr &particle, DuplicatedElementMap &elementMap, DuplicatedWildcardMap &wildcardMap);
+
+ /**
+ * Setup fast lookup list for allowed facets of atomic simple types.
+ */
+ void setupAllowedAtomicFacets();
+
+ /**
+ * Returns the source location of the given schema @p component or a dummy
+ * source location if the component is not found in the component location hash.
+ */
+ QSourceLocation sourceLocation(const NamedSchemaComponent::Ptr &component) const;
+
+ /**
+ * Returns the source location of the given schema @p type or a dummy
+ * source location if the type is not found in the component location hash.
+ */
+ QSourceLocation sourceLocationForType(const SchemaType::Ptr &type) const;
+
+ /**
+ * Checks that the string @p value is valid according the value space of @p type
+ * for the given @p component.
+ */
+ bool isValidValue(const QString &value, const AnySimpleType::Ptr &type, QString &errorMsg) const;
+
+ /**
+ * Returns the list of facets for the given @p type.
+ */
+ XsdFacet::Hash facetsForType(const SchemaType::Ptr &type) const;
+
+ /**
+ * Returns whether the given @p list of attribute uses contains two (or more) attribute
+ * uses that point to attributes with the same name. @p conflictingAttribute
+ * will contain the conflicting attribute in that case.
+ */
+ bool hasDuplicatedAttributeUses(const XsdAttributeUse::List &list, XsdAttribute::Ptr &conflictingAttribute) const;
+
+ /**
+ * Returns whether the given @p list of attribute uses contains two (or more) attribute
+ * uses that have a type inherited by xs:ID.
+ */
+ bool hasMultipleIDAttributeUses(const XsdAttributeUse::List &list) const;
+
+ /**
+ * Returns whether the given @p list of attribute uses contains an attribute
+ * uses that has a type inherited by xs:ID with a value constraint. @p conflictingAttribute
+ * will contain the conflicting attribute in that case.
+ */
+ bool hasConstraintIDAttributeUse(const XsdAttributeUse::List &list, XsdAttribute::Ptr &conflictingAttribute) const;
+
+ /**
+ * Checks whether the @p particle equals the @p otherParticle recursively.
+ */
+ bool particleEqualsRecursively(const XsdParticle::Ptr &particle, const XsdParticle::Ptr &otherParticle) const;
+
+ /**
+ * Checks whether the @p extension particle is a valid extension of the @p base particle.
+ */
+ bool isValidParticleExtension(const XsdParticle::Ptr &extension, const XsdParticle::Ptr &base) const;
+
+ /**
+ * Checks whether the @p sequence of elements is accepted by the given @p particle.
+ */
+ bool elementSequenceAccepted(const XsdModelGroup::Ptr &sequence, const XsdParticle::Ptr &particle) const;
+
+ QExplicitlySharedDataPointer<XsdSchemaContext> m_context;
+ NamePool::Ptr m_namePool;
+ XsdSchema::Ptr m_schema;
+ QHash<QXmlName, QSet<XsdFacet::Type> > m_allowedAtomicFacets;
+ QHash<NamedSchemaComponent::Ptr, QSourceLocation> m_componentLocationHash;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschemachecker_setup.cpp b/src/xmlpatterns/schema/qxsdschemachecker_setup.cpp
new file mode 100644
index 0000000000..b027129a07
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemachecker_setup.cpp
@@ -0,0 +1,287 @@
+
+#include "qxsdschemachecker_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdSchemaChecker::setupAllowedAtomicFacets()
+{
+ // string
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Length
+ << XsdFacet::MinimumLength
+ << XsdFacet::MaximumLength
+ << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsString->name(m_namePool), facets);
+ }
+
+ // boolean
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::WhiteSpace
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsBoolean->name(m_namePool), facets);
+ }
+
+ // float
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsFloat->name(m_namePool), facets);
+ }
+
+ // double
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsDouble->name(m_namePool), facets);
+ }
+
+ // decimal
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::TotalDigits
+ << XsdFacet::FractionDigits
+ << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsDecimal->name(m_namePool), facets);
+ }
+
+ // duration
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsDuration->name(m_namePool), facets);
+ }
+
+ // dateTime
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsDateTime->name(m_namePool), facets);
+ }
+
+ // time
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsTime->name(m_namePool), facets);
+ }
+
+ // date
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsDate->name(m_namePool), facets);
+ }
+
+ // gYearMonth
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsGYearMonth->name(m_namePool), facets);
+ }
+
+ // gYear
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsGYear->name(m_namePool), facets);
+ }
+
+ // gMonthDay
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsGMonthDay->name(m_namePool), facets);
+ }
+
+ // gDay
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsGDay->name(m_namePool), facets);
+ }
+
+ // gMonth
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::MaximumInclusive
+ << XsdFacet::MaximumExclusive
+ << XsdFacet::MinimumInclusive
+ << XsdFacet::MinimumExclusive
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsGMonth->name(m_namePool), facets);
+ }
+
+ // hexBinary
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Length
+ << XsdFacet::MinimumLength
+ << XsdFacet::MaximumLength
+ << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsHexBinary->name(m_namePool), facets);
+ }
+
+ // base64Binary
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Length
+ << XsdFacet::MinimumLength
+ << XsdFacet::MaximumLength
+ << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsBase64Binary->name(m_namePool), facets);
+ }
+
+ // anyURI
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Length
+ << XsdFacet::MinimumLength
+ << XsdFacet::MaximumLength
+ << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsAnyURI->name(m_namePool), facets);
+ }
+
+ // QName
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Length
+ << XsdFacet::MinimumLength
+ << XsdFacet::MaximumLength
+ << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsQName->name(m_namePool), facets);
+ }
+
+ // NOTATION
+ {
+ QSet<XsdFacet::Type> facets;
+ facets << XsdFacet::Length
+ << XsdFacet::MinimumLength
+ << XsdFacet::MaximumLength
+ << XsdFacet::Pattern
+ << XsdFacet::Enumeration
+ << XsdFacet::WhiteSpace
+ << XsdFacet::Assertion;
+
+ m_allowedAtomicFacets.insert(BuiltinTypes::xsNOTATION->name(m_namePool), facets);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemacontext.cpp b/src/xmlpatterns/schema/qxsdschemacontext.cpp
new file mode 100644
index 0000000000..57736bdccd
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemacontext.cpp
@@ -0,0 +1,498 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdschemacontext_p.h"
+
+#include "qderivedinteger_p.h"
+#include "qderivedstring_p.h"
+#include "qxsdschematypesfactory_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchemaContext::XsdSchemaContext(const NamePool::Ptr &namePool)
+ : m_namePool(namePool)
+ , m_networkAccessManager(0)
+ , m_uriResolver(0)
+ , m_messageHandler(0)
+{
+}
+
+NamePool::Ptr XsdSchemaContext::namePool() const
+{
+ return m_namePool;
+}
+
+QUrl XsdSchemaContext::baseURI() const
+{
+ return m_baseURI;
+}
+
+void XsdSchemaContext::setBaseURI(const QUrl &uri)
+{
+ m_baseURI = uri;
+}
+
+void XsdSchemaContext::setNetworkAccessManager(QNetworkAccessManager *accessManager)
+{
+ m_networkAccessManager = accessManager;
+}
+
+QNetworkAccessManager* XsdSchemaContext::networkAccessManager() const
+{
+ return m_networkAccessManager;
+}
+
+void XsdSchemaContext::setMessageHandler(QAbstractMessageHandler *handler)
+{
+ m_messageHandler = handler;
+}
+
+QAbstractMessageHandler* XsdSchemaContext::messageHandler() const
+{
+ return m_messageHandler;
+}
+
+QSourceLocation XsdSchemaContext::locationFor(const SourceLocationReflection *const) const
+{
+ return QSourceLocation();
+}
+
+void XsdSchemaContext::setUriResolver(QAbstractUriResolver *uriResolver)
+{
+ m_uriResolver = uriResolver;
+}
+
+const QAbstractUriResolver* XsdSchemaContext::uriResolver() const
+{
+ return m_uriResolver;
+}
+
+XsdFacet::Hash XsdSchemaContext::facetsForType(const AnySimpleType::Ptr &type) const
+{
+ if (type->isDefinedBySchema())
+ return XsdSimpleType::Ptr(type)->facets();
+ else {
+ if (m_builtinTypesFacetList.isEmpty())
+ m_builtinTypesFacetList = setupBuiltinTypesFacetList();
+
+ return m_builtinTypesFacetList.value(type);
+ }
+}
+
+SchemaTypeFactory::Ptr XsdSchemaContext::schemaTypeFactory() const
+{
+ if (!m_schemaTypeFactory)
+ m_schemaTypeFactory = SchemaTypeFactory::Ptr(new XsdSchemaTypesFactory(m_namePool));
+
+ return m_schemaTypeFactory;
+}
+
+QHash<SchemaType::Ptr, XsdFacet::Hash> XsdSchemaContext::setupBuiltinTypesFacetList() const
+{
+ QHash<SchemaType::Ptr, XsdFacet::Hash> hash;
+
+ const XsdFacet::Ptr fixedCollapseWhiteSpace(new XsdFacet());
+ fixedCollapseWhiteSpace->setType(XsdFacet::WhiteSpace);
+ fixedCollapseWhiteSpace->setValue(DerivedString<TypeString>::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse)));
+ fixedCollapseWhiteSpace->setFixed(true);
+
+ const XsdFacet::Ptr collapseWhiteSpace(new XsdFacet());
+ collapseWhiteSpace->setType(XsdFacet::WhiteSpace);
+ collapseWhiteSpace->setValue(DerivedString<TypeString>::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse)));
+ collapseWhiteSpace->setFixed(false);
+
+ const XsdFacet::Ptr preserveWhiteSpace(new XsdFacet());
+ preserveWhiteSpace->setType(XsdFacet::WhiteSpace);
+ preserveWhiteSpace->setValue(DerivedString<TypeString>::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Preserve)));
+ preserveWhiteSpace->setFixed(false);
+
+ const XsdFacet::Ptr replaceWhiteSpace(new XsdFacet());
+ replaceWhiteSpace->setType(XsdFacet::WhiteSpace);
+ replaceWhiteSpace->setValue(DerivedString<TypeString>::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Replace)));
+ replaceWhiteSpace->setFixed(false);
+
+ const XsdFacet::Ptr fixedZeroFractionDigits(new XsdFacet());
+ fixedZeroFractionDigits->setType(XsdFacet::FractionDigits);
+ fixedZeroFractionDigits->setValue(DerivedInteger<TypeNonNegativeInteger>::fromValue(m_namePool, 0));
+ fixedZeroFractionDigits->setFixed(true);
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsString];
+ facets.insert(preserveWhiteSpace->type(), preserveWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsBoolean];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsDecimal];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsFloat];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsDouble];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsDuration];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsDateTime];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsTime];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsDate];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsGYearMonth];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsGYear];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsGMonthDay];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsGDay];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsGMonth];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsHexBinary];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsBase64Binary];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsAnyURI];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsQName];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsNOTATION];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsNormalizedString];
+ facets.insert(replaceWhiteSpace->type(), replaceWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsToken];
+ facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsLanguage];
+ facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace);
+
+ const XsdFacet::Ptr pattern(new XsdFacet());
+ pattern->setType(XsdFacet::Pattern);
+ pattern->setMultiValue(AtomicValue::List() << DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*")));
+ facets.insert(pattern->type(), pattern);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsNMTOKEN];
+ facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace);
+
+ const XsdFacet::Ptr pattern(new XsdFacet());
+ pattern->setType(XsdFacet::Pattern);
+ pattern->setMultiValue(AtomicValue::List() << DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("\\c+")));
+ facets.insert(pattern->type(), pattern);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsName];
+ facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace);
+
+ const XsdFacet::Ptr pattern(new XsdFacet());
+ pattern->setType(XsdFacet::Pattern);
+ pattern->setMultiValue(AtomicValue::List() << DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("\\i\\c*")));
+ facets.insert(pattern->type(), pattern);
+ }
+
+ const XsdFacet::Ptr ncNamePattern(new XsdFacet());
+ {
+ ncNamePattern->setType(XsdFacet::Pattern);
+ AtomicValue::List patterns;
+ patterns << DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("\\i\\c*"));
+ patterns << DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("[\\i-[:]][\\c-[:]]*"));
+ ncNamePattern->setMultiValue(patterns);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsNCName];
+ facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace);
+ facets.insert(ncNamePattern->type(), ncNamePattern);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsID];
+ facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace);
+ facets.insert(ncNamePattern->type(), ncNamePattern);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsIDREF];
+ facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace);
+ facets.insert(ncNamePattern->type(), ncNamePattern);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsENTITY];
+ facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace);
+ facets.insert(ncNamePattern->type(), ncNamePattern);
+ }
+
+ const XsdFacet::Ptr integerPattern(new XsdFacet());
+ integerPattern->setType(XsdFacet::Pattern);
+ integerPattern->setMultiValue(AtomicValue::List() << DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("[\\-+]?[0-9]+")));
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsInteger];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsNonPositiveInteger];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("0")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsNegativeInteger];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("-1")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsLong];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("9223372036854775807")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+
+ const XsdFacet::Ptr minInclusive(new XsdFacet());
+ minInclusive->setType(XsdFacet::MinimumInclusive);
+ minInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("-9223372036854775808")));
+ facets.insert(minInclusive->type(), minInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsInt];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("2147483647")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+
+ const XsdFacet::Ptr minInclusive(new XsdFacet());
+ minInclusive->setType(XsdFacet::MinimumInclusive);
+ minInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("-2147483648")));
+ facets.insert(minInclusive->type(), minInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsShort];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("32767")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+
+ const XsdFacet::Ptr minInclusive(new XsdFacet());
+ minInclusive->setType(XsdFacet::MinimumInclusive);
+ minInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("-32768")));
+ facets.insert(minInclusive->type(), minInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsByte];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("127")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+
+ const XsdFacet::Ptr minInclusive(new XsdFacet());
+ minInclusive->setType(XsdFacet::MinimumInclusive);
+ minInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("-128")));
+ facets.insert(minInclusive->type(), minInclusive);
+ }
+
+ const XsdFacet::Ptr unsignedMinInclusive(new XsdFacet());
+ unsignedMinInclusive->setType(XsdFacet::MinimumInclusive);
+ unsignedMinInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("0")));
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsNonNegativeInteger];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+ facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsUnsignedLong];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+ facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("18446744073709551615")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsUnsignedInt];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+ facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("4294967295")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsUnsignedShort];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+ facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("65535")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsUnsignedByte];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+ facets.insert(integerPattern->type(), integerPattern);
+ facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive);
+
+ const XsdFacet::Ptr maxInclusive(new XsdFacet());
+ maxInclusive->setType(XsdFacet::MaximumInclusive);
+ maxInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("255")));
+ facets.insert(maxInclusive->type(), maxInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsPositiveInteger];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+ facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits);
+
+ const XsdFacet::Ptr minInclusive(new XsdFacet());
+ minInclusive->setType(XsdFacet::MinimumInclusive);
+ minInclusive->setValue(DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("1")));
+ facets.insert(minInclusive->type(), minInclusive);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsYearMonthDuration];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+
+ const XsdFacet::Ptr pattern(new XsdFacet());
+ pattern->setType(XsdFacet::Pattern);
+ pattern->setMultiValue(AtomicValue::List() << DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("[^DT]*")));
+ facets.insert(pattern->type(), pattern);
+ }
+
+ {
+ XsdFacet::Hash &facets = hash[BuiltinTypes::xsDayTimeDuration];
+ facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace);
+
+ const XsdFacet::Ptr pattern(new XsdFacet());
+ pattern->setType(XsdFacet::Pattern);
+ pattern->setMultiValue(AtomicValue::List() << DerivedString<TypeString>::fromLexical(m_namePool, QString::fromLatin1("[^YM]*(T.*)?")));
+ facets.insert(pattern->type(), pattern);
+ }
+
+ return hash;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemacontext_p.h b/src/xmlpatterns/schema/qxsdschemacontext_p.h
new file mode 100644
index 0000000000..cf520283d5
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemacontext_p.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchemaContext_H
+#define Patternist_XsdSchemaContext_H
+
+#include "qnamedschemacomponent_p.h"
+#include "qreportcontext_p.h"
+#include "qschematypefactory_p.h"
+#include "qxsdschematoken_p.h"
+#include "qxsdschema_p.h"
+#include "qxsdschemachecker_p.h"
+#include "qxsdschemaresolver_p.h"
+
+#include <QtCore/QUrl>
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtXmlPatterns/QAbstractMessageHandler>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A context for schema parsing and validation.
+ *
+ * This class provides the infrastructure for error reporting and
+ * network access. Additionally it stores objects that are used by
+ * both, the parser and the validator.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSchemaContext : public ReportContext
+ {
+ public:
+ /**
+ * A smart pointer wrapping XsdSchemaContext instances.
+ */
+ typedef QExplicitlySharedDataPointer<XsdSchemaContext> Ptr;
+
+ /**
+ * Creates a new schema context object.
+ *
+ * @param namePool The name pool all names belong to.
+ */
+ XsdSchemaContext(const NamePool::Ptr &namePool);
+
+ /**
+ * Returns the name pool of the schema context.
+ */
+ virtual NamePool::Ptr namePool() const;
+
+ /**
+ * Sets the base URI for the main schema.
+ *
+ * The main schema is the one that includes resp. imports
+ * all the other schema files.
+ */
+ virtual void setBaseURI(const QUrl &uri);
+
+ /**
+ * Returns the base URI of the main schema.
+ */
+ virtual QUrl baseURI() const;
+
+ /**
+ * Sets the network access manager that should be used
+ * to access referenced schema definitions.
+ */
+ void setNetworkAccessManager(QNetworkAccessManager *accessManager);
+
+ /**
+ * Returns the network access manager that is used to
+ * access referenced schema definitions.
+ */
+ virtual QNetworkAccessManager* networkAccessManager() const;
+
+ /**
+ * Sets the message @p handler used by the context for error reporting.
+ */
+ void setMessageHandler(QAbstractMessageHandler *handler);
+
+ /**
+ * Returns the message handler used by the context for
+ * error reporting.
+ */
+ virtual QAbstractMessageHandler* messageHandler() const;
+
+ /**
+ * Always returns an empty source location.
+ */
+ virtual QSourceLocation locationFor(const SourceLocationReflection *const reflection) const;
+
+ /**
+ * Sets the uri @p resolver that is used for resolving URIs in the
+ * schema parser.
+ */
+ void setUriResolver(QAbstractUriResolver *resolver);
+
+ /**
+ * Returns the uri resolver that is used for resolving URIs in the
+ * schema parser.
+ */
+ virtual const QAbstractUriResolver* uriResolver() const;
+
+ /**
+ * Returns the list of facets for the given simple @p type.
+ */
+ XsdFacet::Hash facetsForType(const AnySimpleType::Ptr &type) const;
+
+ /**
+ * Returns a schema type factory that contains some predefined schema types.
+ */
+ SchemaTypeFactory::Ptr schemaTypeFactory() const;
+
+ /**
+ * The following variables should not be accessed directly.
+ */
+ mutable SchemaTypeFactory::Ptr m_schemaTypeFactory;
+ mutable QHash<SchemaType::Ptr, XsdFacet::Hash> m_builtinTypesFacetList;
+
+ private:
+ QHash<SchemaType::Ptr, XsdFacet::Hash> setupBuiltinTypesFacetList() const;
+
+ NamePool::Ptr m_namePool;
+ QNetworkAccessManager* m_networkAccessManager;
+ QUrl m_baseURI;
+ QAbstractUriResolver* m_uriResolver;
+ QAbstractMessageHandler* m_messageHandler;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschemadebugger.cpp b/src/xmlpatterns/schema/qxsdschemadebugger.cpp
new file mode 100644
index 0000000000..850192cc06
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemadebugger.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdschemadebugger_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchemaDebugger::XsdSchemaDebugger(const NamePool::Ptr &namePool)
+ : m_namePool(namePool)
+{
+}
+
+void XsdSchemaDebugger::dumpParticle(const XsdParticle::Ptr &particle, int level)
+{
+ QString prefix; prefix.fill(QLatin1Char(' '), level);
+
+ qDebug("%s min=%s max=%s", qPrintable(prefix), qPrintable(QString::number(particle->minimumOccurs())),
+ qPrintable(particle->maximumOccursUnbounded() ? QLatin1String("unbounded") : QString::number(particle->maximumOccurs())));
+
+ if (particle->term()->isElement()) {
+ qDebug("%selement (%s)", qPrintable(prefix), qPrintable(XsdElement::Ptr(particle->term())->displayName(m_namePool)));
+ } else if (particle->term()->isModelGroup()) {
+ const XsdModelGroup::Ptr group(particle->term());
+ if (group->compositor() == XsdModelGroup::SequenceCompositor) {
+ qDebug("%ssequence", qPrintable(prefix));
+ } else if (group->compositor() == XsdModelGroup::AllCompositor) {
+ qDebug("%sall", qPrintable(prefix));
+ } else if (group->compositor() == XsdModelGroup::ChoiceCompositor) {
+ qDebug("%schoice", qPrintable(prefix));
+ }
+
+ for (int i = 0; i < group->particles().count(); ++i)
+ dumpParticle(group->particles().at(i), level + 5);
+ } else if (particle->term()->isWildcard()) {
+ XsdWildcard::Ptr wildcard(particle->term());
+ qDebug("%swildcard (process=%d)", qPrintable(prefix), wildcard->processContents());
+ }
+}
+
+void XsdSchemaDebugger::dumpInheritance(const SchemaType::Ptr &type, int level)
+{
+ QString prefix; prefix.fill(QLatin1Char(' '), level);
+ qDebug("%s-->%s", qPrintable(prefix), qPrintable(type->displayName(m_namePool)));
+ if (type->wxsSuperType())
+ dumpInheritance(type->wxsSuperType(), ++level);
+}
+
+void XsdSchemaDebugger::dumpWildcard(const XsdWildcard::Ptr &wildcard)
+{
+ QVector<QString> varietyNames;
+ varietyNames.append(QLatin1String("Any"));
+ varietyNames.append(QLatin1String("Enumeration"));
+ varietyNames.append(QLatin1String("Not"));
+
+ QVector<QString> processContentsNames;
+ processContentsNames.append(QLatin1String("Strict"));
+ processContentsNames.append(QLatin1String("Lax"));
+ processContentsNames.append(QLatin1String("Skip"));
+
+ qDebug(" processContents: %s", qPrintable(processContentsNames.at((int)wildcard->processContents())));
+ const XsdWildcard::NamespaceConstraint::Ptr constraint = wildcard->namespaceConstraint();
+ qDebug(" variety: %s", qPrintable(varietyNames.at((int)constraint->variety())));
+ if (constraint->variety() != XsdWildcard::NamespaceConstraint::Any)
+ qDebug() << " namespaces:" << constraint->namespaces();
+}
+
+void XsdSchemaDebugger::dumpType(const SchemaType::Ptr &type)
+{
+ if (type->isComplexType()) {
+ const XsdComplexType::Ptr complexType(type);
+ qDebug("\n+++ Complex Type +++");
+ qDebug("Name: %s (abstract: %s)", qPrintable(complexType->displayName(m_namePool)), complexType->isAbstract() ? "yes" : "no");
+ if (complexType->wxsSuperType())
+ qDebug(" base type: %s", qPrintable(complexType->wxsSuperType()->displayName(m_namePool)));
+ else
+ qDebug(" base type: (none)");
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty)
+ qDebug(" content type: empty");
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple)
+ qDebug(" content type: simple");
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly)
+ qDebug(" content type: element-only");
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed)
+ qDebug(" content type: mixed");
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
+ if (complexType->contentType()->simpleType())
+ qDebug(" simple type: %s", qPrintable(complexType->contentType()->simpleType()->displayName(m_namePool)));
+ else
+ qDebug(" simple type: (none)");
+ }
+
+ const XsdAttributeUse::List uses = complexType->attributeUses();
+ qDebug(" %d attributes", uses.count());
+ for (int i = 0; i < uses.count(); ++i) {
+ qDebug(" attr: %s", qPrintable(uses.at(i)->attribute()->displayName(m_namePool)));
+ }
+ qDebug(" has attribute wildcard: %s", complexType->attributeWildcard() ? "yes" : "no");
+ if (complexType->attributeWildcard()) {
+ dumpWildcard(complexType->attributeWildcard());
+ }
+
+ if (complexType->contentType()->particle()) {
+ dumpParticle(complexType->contentType()->particle(), 5);
+ }
+ } else {
+ qDebug("\n+++ Simple Type +++");
+ qDebug("Name: %s", qPrintable(type->displayName(m_namePool)));
+ if (type->isDefinedBySchema()) {
+ const XsdSimpleType::Ptr simpleType(type);
+ if (simpleType->primitiveType())
+ qDebug(" primitive type: %s", qPrintable(simpleType->primitiveType()->displayName(m_namePool)));
+ else
+ qDebug(" primitive type: (none)");
+ }
+ dumpInheritance(type, 0);
+ }
+}
+
+
+void XsdSchemaDebugger::dumpElement(const XsdElement::Ptr &element)
+{
+ QStringList disallowedSubstGroup;
+ if (element->disallowedSubstitutions() & XsdElement::RestrictionConstraint)
+ disallowedSubstGroup << QLatin1String("restriction");
+ if (element->disallowedSubstitutions() & XsdElement::ExtensionConstraint)
+ disallowedSubstGroup << QLatin1String("extension");
+ if (element->disallowedSubstitutions() & XsdElement::SubstitutionConstraint)
+ disallowedSubstGroup << QLatin1String("substitution");
+
+
+ qDebug() << "Name:" << element->displayName(m_namePool);
+ qDebug() << "IsAbstract:" << (element->isAbstract() ? "yes" : "no");
+ qDebug() << "Type:" << element->type()->displayName(m_namePool);
+ qDebug() << "DisallowedSubstitutionGroups:" << disallowedSubstGroup.join(QLatin1String("' "));
+}
+
+void XsdSchemaDebugger::dumpAttribute(const XsdAttribute::Ptr &attribute)
+{
+ qDebug() << "Name:" << attribute->displayName(m_namePool);
+ qDebug() << "Type:" << attribute->type()->displayName(m_namePool);
+}
+
+void XsdSchemaDebugger::dumpSchema(const XsdSchema::Ptr &schema)
+{
+ qDebug() << "------------------------------ Schema -------------------------------";
+
+ // elements
+ {
+ qDebug() << "Global Elements:";
+ const XsdElement::List elements = schema->elements();
+ for (int i = 0; i < elements.count(); ++i) {
+ dumpElement(elements.at(i));
+ }
+ }
+
+ // attributes
+ {
+ qDebug() << "Global Attributes:";
+ const XsdAttribute::List attributes = schema->attributes();
+ for (int i = 0; i < attributes.count(); ++i) {
+ dumpAttribute(attributes.at(i));
+ }
+ }
+
+ // types
+ {
+ qDebug() << "Global Types:";
+ const SchemaType::List types = schema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ dumpType(types.at(i));
+ }
+ }
+
+ // anonymous types
+ {
+ qDebug() << "Anonymous Types:";
+ const SchemaType::List types = schema->anonymousTypes();
+ for (int i = 0; i < types.count(); ++i) {
+ dumpType(types.at(i));
+ }
+ }
+
+ qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemadebugger_p.h b/src/xmlpatterns/schema/qxsdschemadebugger_p.h
new file mode 100644
index 0000000000..8c12f0f4d3
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemadebugger_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchemaDebugger_H
+#define Patternist_XsdSchemaDebugger_H
+
+#include "qxsdschema_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * A helper class to print out the structure of a compiled schema.
+ */
+ class XsdSchemaDebugger
+ {
+ public:
+ /**
+ * Creates a new schema debugger.
+ *
+ * @param namePool The name pool that the schema uses.
+ */
+ XsdSchemaDebugger(const NamePool::Ptr &namePool);
+
+ /**
+ * Dumps the structure of the given @p particle.
+ *
+ * @param particle The particle to dump.
+ * @param level The level of indention.
+ */
+ void dumpParticle(const XsdParticle::Ptr &particle, int level = 0);
+
+ /**
+ * Dumps the inheritance path of the given @p type.
+ *
+ * @param type The type to dump.
+ * @param level The level of indention.
+ */
+ void dumpInheritance(const SchemaType::Ptr &type, int level = 0);
+
+ /**
+ * Dumps the structure of the given @p wildcard.
+ */
+ void dumpWildcard(const XsdWildcard::Ptr &wildcard);
+
+ /**
+ * Dumps the structure of the given @p type.
+ */
+ void dumpType(const SchemaType::Ptr &type);
+
+ /**
+ * Dumps the structure of the given @p element.
+ */
+ void dumpElement(const XsdElement::Ptr &element);
+
+ /**
+ * Dumps the structure of the given @p attribute.
+ */
+ void dumpAttribute(const XsdAttribute::Ptr &attribute);
+
+ /**
+ * Dumps the structure of the complete @p schema.
+ */
+ void dumpSchema(const XsdSchema::Ptr &schema);
+
+ private:
+ NamePool::Ptr m_namePool;
+ };
+
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschemahelper.cpp b/src/xmlpatterns/schema/qxsdschemahelper.cpp
new file mode 100644
index 0000000000..752af89467
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemahelper.cpp
@@ -0,0 +1,791 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdschemahelper_p.h"
+
+#include "qbuiltintypes_p.h"
+#include "qvaluefactory_p.h"
+#include "qxsdcomplextype_p.h"
+#include "qxsdmodelgroup_p.h"
+#include "qxsdsimpletype_p.h"
+#include "qxsdtypechecker_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+/*
+ * Calculates the effective total range minimum of the given @p particle as
+ * described by the algorithm in the schema spec.
+ */
+static inline unsigned int effectiveTotalRangeMinimum(const XsdParticle::Ptr &particle)
+{
+ const XsdModelGroup::Ptr group = particle->term();
+
+ if (group->compositor() == XsdModelGroup::ChoiceCompositor) {
+ // @see http://www.w3.org/TR/xmlschema11-1/# cos-choice-range
+
+ int minValue = -1;
+
+ const XsdParticle::List particles = group->particles();
+ if (particles.isEmpty())
+ minValue = 0;
+
+ for (int i = 0; i < particles.count(); ++i) {
+ const XsdParticle::Ptr particle = particles.at(i);
+
+ if (particle->term()->isElement() || particle->term()->isWildcard()) {
+ if (minValue == -1) {
+ minValue = particle->minimumOccurs();
+ } else {
+ minValue = qMin((unsigned int)minValue, particle->minimumOccurs());
+ }
+ } else if (particle->term()->isModelGroup()) {
+ if (minValue == -1) {
+ minValue = effectiveTotalRangeMinimum(particle);
+ } else {
+ minValue = qMin((unsigned int)minValue, effectiveTotalRangeMinimum(particle));
+ }
+ }
+ }
+
+ return (particle->minimumOccurs() * minValue);
+
+ } else {
+ // @see http://www.w3.org/TR/xmlschema11-1/# cos-seq-range
+
+ unsigned int sum = 0;
+ const XsdParticle::List particles = group->particles();
+ for (int i = 0; i < particles.count(); ++i) {
+ const XsdParticle::Ptr particle = particles.at(i);
+
+ if (particle->term()->isElement() || particle->term()->isWildcard())
+ sum += particle->minimumOccurs();
+ else if (particle->term()->isModelGroup())
+ sum += effectiveTotalRangeMinimum(particle);
+ }
+
+ return (particle->minimumOccurs() * sum);
+ }
+}
+
+bool XsdSchemaHelper::isParticleEmptiable(const XsdParticle::Ptr &particle)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-group-emptiable
+
+ if (particle->minimumOccurs() == 0)
+ return true;
+
+ if (!(particle->term()->isModelGroup()))
+ return false;
+
+ return (effectiveTotalRangeMinimum(particle) == 0);
+}
+
+bool XsdSchemaHelper::wildcardAllowsNamespaceName(const QString &nameSpace, const XsdWildcard::NamespaceConstraint::Ptr &constraint)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cvc-wildcard-namespace
+
+ // 1
+ if (constraint->variety() == XsdWildcard::NamespaceConstraint::Any)
+ return true;
+
+ // 2
+ if (constraint->variety() == XsdWildcard::NamespaceConstraint::Not) { // 2.1
+ if (!constraint->namespaces().contains(nameSpace)) // 2.2
+ if (nameSpace != XsdWildcard::absentNamespace()) // 2.3
+ return true;
+ }
+
+ // 3
+ if (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) {
+ if (constraint->namespaces().contains(nameSpace))
+ return true;
+ }
+
+ return false;
+}
+
+bool XsdSchemaHelper::wildcardAllowsExpandedName(const QXmlName &name, const XsdWildcard::Ptr &wildcard, const NamePool::Ptr &namePool)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cvc-wildcard-name
+
+ // 1
+ if (!wildcardAllowsNamespaceName(namePool->stringForNamespace(name.namespaceURI()), wildcard->namespaceConstraint()))
+ return false;
+
+ // 2, 3, 4
+ //TODO: we have no disallowed namespace yet
+
+ return true;
+}
+
+// small helper function that should be available in Qt 4.6
+template<class T>
+static inline bool containsSet(const QSet<T> &super, const QSet<T> &sub)
+{
+ QSetIterator<T> it(sub);
+ while (it.hasNext()) {
+ if (!super.contains(it.next()))
+ return false;
+ }
+
+ return true;
+}
+
+bool XsdSchemaHelper::isWildcardSubset(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-ns-subset
+ // wildcard =^ sub
+ // otherWildcard =^ super
+
+ const XsdWildcard::NamespaceConstraint::Ptr constraint(wildcard->namespaceConstraint());
+ const XsdWildcard::NamespaceConstraint::Ptr otherConstraint(otherWildcard->namespaceConstraint());
+
+ // 1
+ if (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Any)
+ return true;
+
+ // 2
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
+ if (containsSet<QString>(otherConstraint->namespaces(), constraint->namespaces()))
+ return true;
+ }
+
+ // 3
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) {
+ if (constraint->namespaces().intersect(otherConstraint->namespaces()).isEmpty())
+ return true;
+ }
+
+ // 4
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) {
+ if (containsSet<QString>(constraint->namespaces(), otherConstraint->namespaces()))
+ return true;
+ }
+
+ return false;
+}
+
+XsdWildcard::Ptr XsdSchemaHelper::wildcardUnion(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-aw-union
+
+ XsdWildcard::Ptr unionWildcard(new XsdWildcard());
+
+ const XsdWildcard::NamespaceConstraint::Ptr constraint(wildcard->namespaceConstraint());
+ const XsdWildcard::NamespaceConstraint::Ptr otherConstraint(otherWildcard->namespaceConstraint());
+
+ // 1
+ if ((constraint->variety() == otherConstraint->variety()) &&
+ (constraint->namespaces() == otherConstraint->namespaces())) {
+ unionWildcard->namespaceConstraint()->setVariety(constraint->variety());
+ unionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces());
+ return unionWildcard;
+ }
+
+ // 2
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Any) || (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Any)) {
+ unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ return unionWildcard;
+ }
+
+ // 3
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
+ unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
+ unionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces() + otherConstraint->namespaces());
+ return unionWildcard;
+ }
+
+ // 4
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) {
+ if (constraint->namespaces() != otherConstraint->namespaces()) {
+ unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
+ unionWildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
+ return unionWildcard;
+ }
+ }
+
+ // 5
+ QSet<QString> sSet, negatedSet;
+ bool matches5 = false;
+ if (((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && !constraint->namespaces().contains(XsdWildcard::absentNamespace()))
+ && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
+
+ negatedSet = constraint->namespaces();
+ sSet = otherConstraint->namespaces();
+ matches5 = true;
+ } else if (((otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not) && !otherConstraint->namespaces().contains(XsdWildcard::absentNamespace()))
+ && (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
+
+ negatedSet = otherConstraint->namespaces();
+ sSet = constraint->namespaces();
+ matches5 = true;
+ }
+
+ if (matches5) {
+ if (sSet.contains(negatedSet.values().first()) && sSet.contains(XsdWildcard::absentNamespace())) { // 5.1
+ unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ return unionWildcard;
+ }
+ if (sSet.contains(negatedSet.values().first()) && !sSet.contains(XsdWildcard::absentNamespace())) { // 5.2
+ unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
+ unionWildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
+ return unionWildcard;
+ }
+ if (!sSet.contains(negatedSet.values().first()) && sSet.contains(XsdWildcard::absentNamespace())) { // 5.3
+ return XsdWildcard::Ptr(); // not expressible
+ }
+ if (!sSet.contains(negatedSet.values().first()) && !sSet.contains(XsdWildcard::absentNamespace())) { // 5.4
+ unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
+ unionWildcard->namespaceConstraint()->setNamespaces(negatedSet);
+ return unionWildcard;
+ }
+ }
+
+ // 6
+ bool matches6 = false;
+ if (((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && constraint->namespaces().contains(XsdWildcard::absentNamespace()))
+ && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
+
+ negatedSet = constraint->namespaces();
+ sSet = otherConstraint->namespaces();
+ matches6 = true;
+ } else if (((otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not) && otherConstraint->namespaces().contains(XsdWildcard::absentNamespace()))
+ && (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
+
+ negatedSet = otherConstraint->namespaces();
+ sSet = constraint->namespaces();
+ matches6 = true;
+ }
+
+ if (matches6) {
+ if (sSet.contains(XsdWildcard::absentNamespace())) { // 6.1
+ unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ return unionWildcard;
+ }
+ if (!sSet.contains(XsdWildcard::absentNamespace())) { // 6.2
+ unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
+ unionWildcard->namespaceConstraint()->setNamespaces(QSet<QString>() += XsdWildcard::absentNamespace());
+ return unionWildcard;
+ }
+ }
+
+ return XsdWildcard::Ptr();
+}
+
+XsdWildcard::Ptr XsdSchemaHelper::wildcardIntersection(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-aw-intersect
+
+ const XsdWildcard::NamespaceConstraint::Ptr constraint(wildcard->namespaceConstraint());
+ const XsdWildcard::NamespaceConstraint::Ptr otherConstraint(otherWildcard->namespaceConstraint());
+
+ const XsdWildcard::Ptr intersectionWildcard(new XsdWildcard());
+
+ // 1
+ if ((constraint->variety() == otherConstraint->variety()) &&
+ (constraint->namespaces() == otherConstraint->namespaces())) {
+ intersectionWildcard->namespaceConstraint()->setVariety(constraint->variety());
+ intersectionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces());
+ return intersectionWildcard;
+ }
+
+ // 2
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Any) &&
+ (otherConstraint->variety() != XsdWildcard::NamespaceConstraint::Any)) {
+ intersectionWildcard->namespaceConstraint()->setVariety(otherConstraint->variety());
+ intersectionWildcard->namespaceConstraint()->setNamespaces(otherConstraint->namespaces());
+ return intersectionWildcard;
+ }
+
+ // 2
+ if ((constraint->variety() != XsdWildcard::NamespaceConstraint::Any) &&
+ (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Any)) {
+ intersectionWildcard->namespaceConstraint()->setVariety(constraint->variety());
+ intersectionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces());
+ return intersectionWildcard;
+ }
+
+ // 3
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) &&
+ (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
+
+ QSet<QString> set = otherConstraint->namespaces();
+ set.subtract(constraint->namespaces());
+ set.remove(XsdWildcard::absentNamespace());
+
+ intersectionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
+ intersectionWildcard->namespaceConstraint()->setNamespaces(set);
+
+ return intersectionWildcard;
+ }
+
+ // 3
+ if ((otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not) &&
+ (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
+
+ QSet<QString> set = constraint->namespaces();
+ set.subtract(otherConstraint->namespaces());
+ set.remove(XsdWildcard::absentNamespace());
+
+ intersectionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
+ intersectionWildcard->namespaceConstraint()->setNamespaces(set);
+
+ return intersectionWildcard;
+ }
+
+ // 4
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) &&
+ (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) {
+
+ QSet<QString> set = constraint->namespaces();
+ set.intersect(otherConstraint->namespaces());
+
+ intersectionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
+ intersectionWildcard->namespaceConstraint()->setNamespaces(set);
+
+ return intersectionWildcard;
+ }
+
+ // 6
+ if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) &&
+ (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) {
+ if (!(constraint->namespaces().contains(XsdWildcard::absentNamespace())) && otherConstraint->namespaces().contains(XsdWildcard::absentNamespace())) {
+ return wildcard;
+ }
+ if (constraint->namespaces().contains(XsdWildcard::absentNamespace()) && !(otherConstraint->namespaces().contains(XsdWildcard::absentNamespace()))) {
+ return otherWildcard;
+ }
+ }
+
+ // 5 as not expressible return empty wildcard
+ return XsdWildcard::Ptr();
+}
+
+static SchemaType::DerivationConstraints convertBlockingConstraints(const NamedSchemaComponent::BlockingConstraints &constraints)
+{
+ SchemaType::DerivationConstraints result = 0;
+
+ if (constraints & NamedSchemaComponent::RestrictionConstraint)
+ result |= SchemaType::RestrictionConstraint;
+ if (constraints & NamedSchemaComponent::ExtensionConstraint)
+ result |= SchemaType::ExtensionConstraint;
+
+ return result;
+}
+
+bool XsdSchemaHelper::isValidlySubstitutable(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, const SchemaType::DerivationConstraints &constraints)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#key-val-sub-type
+
+ // 1
+ if (type->isComplexType() && otherType->isComplexType()) {
+ SchemaType::DerivationConstraints keywords = constraints;
+ if (otherType->isDefinedBySchema())
+ keywords |= convertBlockingConstraints(XsdComplexType::Ptr(otherType)->prohibitedSubstitutions());
+
+ return isComplexDerivationOk(type, otherType, keywords);
+ }
+
+ // 2
+ if (type->isComplexType() && otherType->isSimpleType()) {
+ return isComplexDerivationOk(type, otherType, constraints);
+ }
+
+ // 3
+ if (type->isSimpleType() && otherType->isSimpleType()) {
+ return isSimpleDerivationOk(type, otherType, constraints);
+ }
+
+ return false;
+}
+
+bool XsdSchemaHelper::isSimpleDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-st-derived-ok
+
+ // 1
+ if (derivedType == baseType)
+ return true;
+
+ // 2.1
+ if ((constraints & SchemaType::RestrictionConstraint) || derivedType->wxsSuperType()->derivationConstraints() & SchemaType::RestrictionConstraint) {
+ return false;
+ }
+
+ // 2.2.1
+ if (derivedType->wxsSuperType() == baseType)
+ return true;
+
+ // 2.2.2
+ if (derivedType->wxsSuperType() != BuiltinTypes::xsAnyType) {
+ if (isSimpleDerivationOk(derivedType->wxsSuperType(), baseType, constraints))
+ return true;
+ }
+
+ // 2.2.3
+ if (derivedType->category() == SchemaType::SimpleTypeList || derivedType->category() == SchemaType::SimpleTypeUnion) {
+ if (baseType == BuiltinTypes::xsAnySimpleType)
+ return true;
+ }
+
+ // 2.2.4
+ if (baseType->category() == SchemaType::SimpleTypeUnion && baseType->isDefinedBySchema()) { // 2.2.4.1
+ const AnySimpleType::List memberTypes = XsdSimpleType::Ptr(baseType)->memberTypes();
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ if (isSimpleDerivationOk(derivedType, memberTypes.at(i), constraints)) { // 2.2.4.2
+ if (XsdSimpleType::Ptr(baseType)->facets().isEmpty()) { // 2.2.4.3
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool XsdSchemaHelper::isComplexDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints)
+{
+ if (!derivedType)
+ return false;
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-ct-derived-ok
+
+ // 1
+ if (derivedType != baseType) {
+ if ((derivedType->derivationMethod() == SchemaType::DerivationRestriction) && (constraints & SchemaType::RestrictionConstraint))
+ return false;
+ if ((derivedType->derivationMethod() == SchemaType::DerivationExtension) && (constraints & SchemaType::ExtensionConstraint))
+ return false;
+ }
+
+ // 2.1
+ if (derivedType == baseType)
+ return true;
+
+ // 2.2
+ if (derivedType->wxsSuperType() == baseType)
+ return true;
+
+ // 2.3
+ bool isOk = true;
+ if (derivedType->wxsSuperType() == BuiltinTypes::xsAnyType) { // 2.3.1
+ isOk = false;
+ } else { // 2.3.2
+ if (!derivedType->wxsSuperType())
+ return false;
+
+ if (derivedType->wxsSuperType()->isComplexType()) { // 2.3.2.1
+ isOk = isComplexDerivationOk(derivedType->wxsSuperType(), baseType, constraints);
+ } else { // 2.3.2.2
+ isOk = isSimpleDerivationOk(derivedType->wxsSuperType(), baseType, constraints);
+ }
+ }
+ if (isOk)
+ return true;
+
+ return false;
+}
+
+bool XsdSchemaHelper::constructAndCompare(const DerivedString<TypeString>::Ptr &operand1,
+ const AtomicComparator::Operator op,
+ const DerivedString<TypeString>::Ptr &operand2,
+ const SchemaType::Ptr &type,
+ const ReportContext::Ptr &context,
+ const SourceLocationReflection *const sourceLocationReflection)
+{
+ Q_ASSERT_X(type->category() == SchemaType::SimpleTypeAtomic, Q_FUNC_INFO,
+ "We can only compare atomic values.");
+
+ // we can not cast a xs:String to a xs:QName, so lets go the safe way
+ if (type->name(context->namePool()) == BuiltinTypes::xsQName->name(context->namePool()))
+ return false;
+
+ const AtomicValue::Ptr value1 = ValueFactory::fromLexical(operand1->stringValue(), type, context, sourceLocationReflection);
+ if (value1->hasError())
+ return false;
+
+ const AtomicValue::Ptr value2 = ValueFactory::fromLexical(operand2->stringValue(), type, context, sourceLocationReflection);
+ if (value2->hasError())
+ return false;
+
+ return ComparisonFactory::compare(value1, op, value2, type, context, sourceLocationReflection);
+}
+
+bool XsdSchemaHelper::checkWildcardProcessContents(const XsdWildcard::Ptr &baseWildcard, const XsdWildcard::Ptr &derivedWildcard)
+{
+ if (baseWildcard->processContents() == XsdWildcard::Strict) {
+ if (derivedWildcard->processContents() == XsdWildcard::Lax || derivedWildcard->processContents() == XsdWildcard::Skip) {
+ return false;
+ }
+ } else if (baseWildcard->processContents() == XsdWildcard::Lax) {
+ if (derivedWildcard->processContents() == XsdWildcard::Skip)
+ return false;
+ }
+
+ return true;
+}
+
+bool XsdSchemaHelper::foundSubstitutionGroupTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, QSet<XsdElement::Ptr> &visitedElements)
+{
+ if (visitedElements.contains(member))
+ return false;
+ else
+ visitedElements.insert(member);
+
+ if (member->substitutionGroupAffiliations().isEmpty())
+ return false;
+
+ if (member->substitutionGroupAffiliations().contains(head)) {
+ return true;
+ } else {
+ const XsdElement::List affiliations = member->substitutionGroupAffiliations();
+ for (int i = 0; i < affiliations.count(); ++i) {
+ if (foundSubstitutionGroupTransitive(head, affiliations.at(i), visitedElements))
+ return true;
+ }
+
+ return false;
+ }
+}
+
+void XsdSchemaHelper::foundSubstitutionGroupTypeInheritance(const SchemaType::Ptr &headType, const SchemaType::Ptr &memberType,
+ QSet<SchemaType::DerivationMethod> &derivationSet, NamedSchemaComponent::BlockingConstraints &blockSet)
+{
+ if (!memberType)
+ return;
+
+ if (memberType == headType)
+ return;
+
+ derivationSet.insert(memberType->derivationMethod());
+
+ if (memberType->isComplexType()) {
+ const XsdComplexType::Ptr complexType(memberType);
+ blockSet |= complexType->prohibitedSubstitutions();
+ }
+
+ foundSubstitutionGroupTypeInheritance(headType, memberType->wxsSuperType(), derivationSet, blockSet);
+}
+
+bool XsdSchemaHelper::substitutionGroupOkTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, const NamePool::Ptr &namePool)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-equiv-derived-ok-rec
+
+ // 1
+ if ((member->name(namePool) == head->name(namePool)) && (member->type() == head->type()))
+ return true;
+
+ // 2.1
+ if (head->disallowedSubstitutions() & NamedSchemaComponent::SubstitutionConstraint)
+ return false;
+
+ // 2.2
+ {
+ QSet<XsdElement::Ptr> visitedElements;
+ if (!foundSubstitutionGroupTransitive(head, member, visitedElements))
+ return false;
+ }
+
+ // 2.3
+ {
+ QSet<SchemaType::DerivationMethod> derivationSet;
+ NamedSchemaComponent::BlockingConstraints blockSet;
+
+ foundSubstitutionGroupTypeInheritance(head->type(), member->type(), derivationSet, blockSet);
+
+ NamedSchemaComponent::BlockingConstraints checkSet(blockSet);
+ checkSet |= head->disallowedSubstitutions();
+ if (head->type()->isComplexType()) {
+ const XsdComplexType::Ptr complexType(head->type());
+ checkSet |= complexType->prohibitedSubstitutions();
+ }
+
+ if ((checkSet & NamedSchemaComponent::RestrictionConstraint) && derivationSet.contains(SchemaType::DerivationRestriction))
+ return false;
+ if ((checkSet & NamedSchemaComponent::ExtensionConstraint) && derivationSet.contains(SchemaType::DerivationExtension))
+ return false;
+ if (checkSet & NamedSchemaComponent::SubstitutionConstraint)
+ return false;
+ }
+
+ return true;
+}
+
+bool XsdSchemaHelper::isValidAttributeGroupRestriction(const XsdAttributeGroup::Ptr &derivedAttributeGroup, const XsdAttributeGroup::Ptr &attributeGroup, const XsdSchemaContext::Ptr &context, QString &errorMsg)
+{
+ // @see http://www.w3.org/TR/xmlschema-1/#derivation-ok-restriction
+
+ const XsdAttributeUse::List derivedAttributeUses = derivedAttributeGroup->attributeUses();
+ const XsdAttributeUse::List baseAttributeUses = attributeGroup->attributeUses();
+
+ return isValidAttributeUsesRestriction(derivedAttributeUses, baseAttributeUses,
+ derivedAttributeGroup->wildcard(), attributeGroup->wildcard(), context, errorMsg);
+}
+
+bool XsdSchemaHelper::isValidAttributeUsesRestriction(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &baseAttributeUses,
+ const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg)
+{
+ const NamePool::Ptr namePool(context->namePool());
+
+ QHash<QXmlName, XsdAttributeUse::Ptr> baseAttributeUsesLookup;
+ for (int i = 0; i < baseAttributeUses.count(); ++i)
+ baseAttributeUsesLookup.insert(baseAttributeUses.at(i)->attribute()->name(namePool), baseAttributeUses.at(i));
+
+ QHash<QXmlName, XsdAttributeUse::Ptr> derivedAttributeUsesLookup;
+ for (int i = 0; i < derivedAttributeUses.count(); ++i)
+ derivedAttributeUsesLookup.insert(derivedAttributeUses.at(i)->attribute()->name(namePool), derivedAttributeUses.at(i));
+
+ // 2
+ for (int i = 0; i < derivedAttributeUses.count(); ++i) {
+ const XsdAttributeUse::Ptr derivedAttributeUse = derivedAttributeUses.at(i);
+
+ // prohibited attributes are no real attributes, so skip them in that test here
+ if (derivedAttributeUse->useType() == XsdAttributeUse::ProhibitedUse)
+ continue;
+
+ if (baseAttributeUsesLookup.contains(derivedAttributeUse->attribute()->name(namePool))) {
+ const XsdAttributeUse::Ptr baseAttributeUse(baseAttributeUsesLookup.value(derivedAttributeUse->attribute()->name(namePool)));
+
+ // 2.1.1
+ if (baseAttributeUse->isRequired() == true && derivedAttributeUse->isRequired() == false) {
+ errorMsg = QtXmlPatterns::tr("base attribute %1 is required but derived attribute is not").arg(formatAttribute(baseAttributeUse->attribute()->displayName(namePool)));
+ return false;
+ }
+
+ // 2.1.2
+ if (!isSimpleDerivationOk(derivedAttributeUse->attribute()->type(), baseAttributeUse->attribute()->type(), SchemaType::DerivationConstraints())) {
+ errorMsg = QtXmlPatterns::tr("type of derived attribute %1 cannot be validly derived from type of base attribute").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool)));
+ return false;
+ }
+
+ // 2.1.3
+ XsdAttributeUse::ValueConstraint::Ptr derivedConstraint;
+ if (derivedAttributeUse->valueConstraint())
+ derivedConstraint = derivedAttributeUse->valueConstraint();
+ else if (derivedAttributeUse->attribute()->valueConstraint())
+ derivedConstraint = XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(derivedAttributeUse->attribute()->valueConstraint());
+
+ XsdAttributeUse::ValueConstraint::Ptr baseConstraint;
+ if (baseAttributeUse->valueConstraint())
+ baseConstraint = baseAttributeUse->valueConstraint();
+ else if (baseAttributeUse->attribute()->valueConstraint())
+ baseConstraint = XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(baseAttributeUse->attribute()->valueConstraint());
+
+ bool ok = false;
+ if (!baseConstraint || baseConstraint->variety() == XsdAttributeUse::ValueConstraint::Default)
+ ok = true;
+
+ if (derivedConstraint && baseConstraint) {
+ const XsdTypeChecker checker(context, QVector<QXmlName>(), QSourceLocation(QUrl(QLatin1String("http://dummy.org")), 1, 1));
+ if (derivedConstraint->variety() == XsdAttributeUse::ValueConstraint::Fixed && checker.valuesAreEqual(derivedConstraint->value(), baseConstraint->value(), baseAttributeUse->attribute()->type()))
+ ok = true;
+ }
+
+ if (!ok) {
+ errorMsg = QtXmlPatterns::tr("value constraint of derived attribute %1 does not match value constraint of base attribute").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool)));
+ return false;
+ }
+ } else {
+ if (!wildcard) {
+ errorMsg = QtXmlPatterns::tr("derived attribute %1 does not exists in the base definition").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool)));
+ return false;
+ }
+
+ QXmlName name = derivedAttributeUse->attribute()->name(namePool);
+
+ // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
+ if (name.namespaceURI() == StandardNamespaces::empty)
+ name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace()));
+
+ if (!wildcardAllowsExpandedName(name, wildcard, namePool)) {
+ errorMsg = QtXmlPatterns::tr("derived attribute %1 does not match the wildcard in the base definition").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool)));
+ return false;
+ }
+ }
+ }
+
+ // 3
+ for (int i = 0; i < baseAttributeUses.count(); ++i) {
+ const XsdAttributeUse::Ptr baseAttributeUse = baseAttributeUses.at(i);
+
+ if (baseAttributeUse->isRequired()) {
+ if (derivedAttributeUsesLookup.contains(baseAttributeUse->attribute()->name(namePool))) {
+ if (!derivedAttributeUsesLookup.value(baseAttributeUse->attribute()->name(namePool))->isRequired()) {
+ errorMsg = QtXmlPatterns::tr("base attribute %1 is required but derived attribute is not").arg(formatAttribute(baseAttributeUse->attribute()->displayName(namePool)));
+ return false;
+ }
+ } else {
+ errorMsg = QtXmlPatterns::tr("base attribute %1 is required but missing in derived definition").arg(formatAttribute(baseAttributeUse->attribute()->displayName(namePool)));
+ return false;
+ }
+ }
+ }
+
+ // 4
+ if (derivedWildcard) {
+ if (!wildcard) {
+ errorMsg = QtXmlPatterns::tr("derived definition contains an %1 element that does not exists in the base definition").arg(formatElement("anyAttribute"));
+ return false;
+ }
+
+ if (!isWildcardSubset(derivedWildcard, wildcard)) {
+ errorMsg = QtXmlPatterns::tr("derived wildcard is not a subset of the base wildcard");
+ return false;
+ }
+
+ if (!checkWildcardProcessContents(wildcard, derivedWildcard)) {
+ errorMsg = QtXmlPatterns::tr("%1 of derived wildcard is not a valid restriction of %2 of base wildcard").arg(formatKeyword("processContents")).arg(formatKeyword("processContents"));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool XsdSchemaHelper::isValidAttributeUsesExtension(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses,
+ const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cos-ct-extends
+
+ const NamePool::Ptr namePool(context->namePool());
+
+ // 1.2
+ QHash<QXmlName, XsdAttribute::Ptr> lookupHash;
+ for (int i = 0; i < derivedAttributeUses.count(); ++i)
+ lookupHash.insert(derivedAttributeUses.at(i)->attribute()->name(namePool), derivedAttributeUses.at(i)->attribute());
+
+ for (int i = 0; i < attributeUses.count(); ++i) {
+ const QXmlName attributeName = attributeUses.at(i)->attribute()->name(namePool);
+ if (!lookupHash.contains(attributeName)) {
+ errorMsg = QtXmlPatterns::tr("attribute %1 from base type is missing in derived type").arg(formatKeyword(namePool->displayName(attributeName)));
+ return false;
+ }
+
+ if (lookupHash.value(attributeName)->type() != attributeUses.at(i)->attribute()->type()) {
+ errorMsg = QtXmlPatterns::tr("type of derived attribute %1 differs from type of base attribute").arg(formatKeyword(namePool->displayName(attributeName)));
+ return false;
+ }
+ }
+
+ // 1.3
+ if (wildcard) {
+ if (!derivedWildcard) {
+ errorMsg = QtXmlPatterns::tr("base definition contains an %1 element that is missing in the derived definition").arg(formatElement("anyAttribute"));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemahelper_p.h b/src/xmlpatterns/schema/qxsdschemahelper_p.h
new file mode 100644
index 0000000000..1722b4c63b
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemahelper_p.h
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchemaHelper_H
+#define Patternist_XsdSchemaHelper_H
+
+#include "qcomparisonfactory_p.h"
+#include "qschematype_p.h"
+#include "qxsdattributegroup_p.h"
+#include "qxsdelement_p.h"
+#include "qxsdparticle_p.h"
+#include "qxsdschemacontext_p.h"
+#include "qxsdwildcard_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+
+ /**
+ * @short Contains helper methods that are used by XsdSchemaParser, XsdSchemaResolver and XsdSchemaChecker.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSchemaHelper
+ {
+ public:
+ /**
+ * Checks whether the given @p particle is emptiable as defined by the
+ * algorithm in the schema spec.
+ */
+ static bool isParticleEmptiable(const XsdParticle::Ptr &particle);
+
+ /**
+ * Checks whether the given @p nameSpace is allowed by the given namespace @p constraint.
+ */
+ static bool wildcardAllowsNamespaceName(const QString &nameSpace, const XsdWildcard::NamespaceConstraint::Ptr &constraint);
+
+ /**
+ * Checks whether the given @p name is allowed by the namespace constraint of the given @p wildcard.
+ */
+ static bool wildcardAllowsExpandedName(const QXmlName &name, const XsdWildcard::Ptr &wildcard, const NamePool::Ptr &namePool);
+
+ /**
+ * Checks whether the @p wildcard is a subset of @p otherWildcard.
+ */
+ static bool isWildcardSubset(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard);
+
+ /**
+ * Returns the union of the given @p wildcard and @p otherWildcard.
+ */
+ static XsdWildcard::Ptr wildcardUnion(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard);
+
+ /**
+ * Returns the intersection of the given @p wildcard and @p otherWildcard.
+ */
+ static XsdWildcard::Ptr wildcardIntersection(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard);
+
+ /**
+ * Returns whether the given @p type is validly substitutable for an @p otherType
+ * under the given @p constraints.
+ */
+ static bool isValidlySubstitutable(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, const SchemaType::DerivationConstraints &constraints);
+
+ /**
+ * Returns whether the simple @p derivedType can be derived from the simple @p baseType
+ * under the given @p constraints.
+ */
+ static bool isSimpleDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints);
+
+ /**
+ * Returns whether the complex @p derivedType can be derived from the complex @p baseType
+ * under the given @p constraints.
+ */
+ static bool isComplexDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints);
+
+ /**
+ * This method takes the two string based operands @p operand1 and @p operand2 and converts them to instances of type @p type.
+ * If the conversion fails, @c false is returned, otherwise the instances are compared by the given operator @p op and the
+ * result of the comparison is returned.
+ */
+ static bool constructAndCompare(const DerivedString<TypeString>::Ptr &operand1,
+ const AtomicComparator::Operator op,
+ const DerivedString<TypeString>::Ptr &operand2,
+ const SchemaType::Ptr &type,
+ const ReportContext::Ptr &context,
+ const SourceLocationReflection *const sourceLocationReflection);
+
+ /**
+ * Returns whether the process content property of the @p derivedWildcard is valid
+ * according to the process content property of its @p baseWildcard.
+ */
+ static bool checkWildcardProcessContents(const XsdWildcard::Ptr &baseWildcard, const XsdWildcard::Ptr &derivedWildcard);
+
+ /**
+ * Checks whether @[ member is a member of the substitution group with the given @p head.
+ */
+ static bool foundSubstitutionGroupTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, QSet<XsdElement::Ptr> &visitedElements);
+
+ /**
+ * A helper method that iterates over the type hierarchy from @p memberType up to @p headType and collects all
+ * @p derivationSet and @p blockSet constraints that exists on the way there.
+ */
+ static void foundSubstitutionGroupTypeInheritance(const SchemaType::Ptr &headType, const SchemaType::Ptr &memberType,
+ QSet<SchemaType::DerivationMethod> &derivationSet, NamedSchemaComponent::BlockingConstraints &blockSet);
+
+ /**
+ * Checks if the @p member is transitive to @p head.
+ */
+ static bool substitutionGroupOkTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, const NamePool::Ptr &namePool);
+
+ /**
+ * Checks if @p derivedAttributeGroup is a valid restriction for @p attributeGroup.
+ */
+ static bool isValidAttributeGroupRestriction(const XsdAttributeGroup::Ptr &derivedAttributeGroup, const XsdAttributeGroup::Ptr &attributeGroup, const XsdSchemaContext::Ptr &context, QString &errorMsg);
+
+ /**
+ * Checks if @p derivedAttributeUses are a valid restriction for @p attributeUses.
+ */
+ static bool isValidAttributeUsesRestriction(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses,
+ const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg);
+
+ /**
+ * Checks if @p derivedAttributeUses are a valid extension for @p attributeUses.
+ */
+ static bool isValidAttributeUsesExtension(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses,
+ const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg);
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschemamerger.cpp b/src/xmlpatterns/schema/qxsdschemamerger.cpp
new file mode 100644
index 0000000000..a924c9c17c
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemamerger.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdschemamerger_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchemaMerger::XsdSchemaMerger(const XsdSchema::Ptr &schema, const XsdSchema::Ptr &otherSchema)
+{
+ merge(schema, otherSchema);
+}
+
+XsdSchema::Ptr XsdSchemaMerger::mergedSchema() const
+{
+ return m_mergedSchema;
+}
+
+void XsdSchemaMerger::merge(const XsdSchema::Ptr &schema, const XsdSchema::Ptr &otherSchema)
+{
+ m_mergedSchema = XsdSchema::Ptr(new XsdSchema(otherSchema->namePool()));
+
+ // first fill the merged schema with the values from schema
+ if (schema) {
+ const XsdElement::List elements = schema->elements();
+ for (int i = 0; i < elements.count(); ++i) {
+ m_mergedSchema->addElement(elements.at(i));
+ }
+
+ const XsdAttribute::List attributes = schema->attributes();
+ for (int i = 0; i < attributes.count(); ++i) {
+ m_mergedSchema->addAttribute(attributes.at(i));
+ }
+
+ const SchemaType::List types = schema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ m_mergedSchema->addType(types.at(i));
+ }
+
+ const SchemaType::List anonymousTypes = schema->anonymousTypes();
+ for (int i = 0; i < anonymousTypes.count(); ++i) {
+ m_mergedSchema->addAnonymousType(anonymousTypes.at(i));
+ }
+
+ const XsdModelGroup::List elementGroups = schema->elementGroups();
+ for (int i = 0; i < elementGroups.count(); ++i) {
+ m_mergedSchema->addElementGroup(elementGroups.at(i));
+ }
+
+ const XsdAttributeGroup::List attributeGroups = schema->attributeGroups();
+ for (int i = 0; i < attributeGroups.count(); ++i) {
+ m_mergedSchema->addAttributeGroup(attributeGroups.at(i));
+ }
+
+ const XsdNotation::List notations = schema->notations();
+ for (int i = 0; i < notations.count(); ++i) {
+ m_mergedSchema->addNotation(notations.at(i));
+ }
+
+ const XsdIdentityConstraint::List identityConstraints = schema->identityConstraints();
+ for (int i = 0; i < identityConstraints.count(); ++i) {
+ m_mergedSchema->addIdentityConstraint(identityConstraints.at(i));
+ }
+ }
+
+ // then merge in the values from the otherSchema
+ {
+ const XsdElement::List elements = otherSchema->elements();
+ for (int i = 0; i < elements.count(); ++i) {
+ if (!m_mergedSchema->element(elements.at(i)->name(otherSchema->namePool())))
+ m_mergedSchema->addElement(elements.at(i));
+ }
+
+ const XsdAttribute::List attributes = otherSchema->attributes();
+ for (int i = 0; i < attributes.count(); ++i) {
+ if (!m_mergedSchema->attribute(attributes.at(i)->name(otherSchema->namePool())))
+ m_mergedSchema->addAttribute(attributes.at(i));
+ }
+
+ const SchemaType::List types = otherSchema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ if (!m_mergedSchema->type(types.at(i)->name(otherSchema->namePool())))
+ m_mergedSchema->addType(types.at(i));
+ }
+
+ const SchemaType::List anonymousTypes = otherSchema->anonymousTypes();
+ for (int i = 0; i < anonymousTypes.count(); ++i) {
+ // add anonymous type as they are
+ m_mergedSchema->addAnonymousType(anonymousTypes.at(i));
+ }
+
+ const XsdModelGroup::List elementGroups = otherSchema->elementGroups();
+ for (int i = 0; i < elementGroups.count(); ++i) {
+ if (!m_mergedSchema->elementGroup(elementGroups.at(i)->name(otherSchema->namePool())))
+ m_mergedSchema->addElementGroup(elementGroups.at(i));
+ }
+
+ const XsdAttributeGroup::List attributeGroups = otherSchema->attributeGroups();
+ for (int i = 0; i < attributeGroups.count(); ++i) {
+ if (!m_mergedSchema->attributeGroup(attributeGroups.at(i)->name(otherSchema->namePool())))
+ m_mergedSchema->addAttributeGroup(attributeGroups.at(i));
+ }
+
+ const XsdNotation::List notations = otherSchema->notations();
+ for (int i = 0; i < notations.count(); ++i) {
+ if (!m_mergedSchema->notation(notations.at(i)->name(otherSchema->namePool())))
+ m_mergedSchema->addNotation(notations.at(i));
+ }
+
+ const XsdIdentityConstraint::List identityConstraints = otherSchema->identityConstraints();
+ for (int i = 0; i < identityConstraints.count(); ++i) {
+ if (!m_mergedSchema->identityConstraint(identityConstraints.at(i)->name(otherSchema->namePool())))
+ m_mergedSchema->addIdentityConstraint(identityConstraints.at(i));
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemamerger_p.h b/src/xmlpatterns/schema/qxsdschemamerger_p.h
new file mode 100644
index 0000000000..54cc0f2c3f
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemamerger_p.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchemaMerger_H
+#define Patternist_XsdSchemaMerger_H
+
+#include "qxsdschema_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A helper class that merges two schemas into one.
+ *
+ * This class is used in XsdValidatingInstanceReader to merge the schema
+ * given in the constructor with a schema defined in the instance document
+ * via xsi:schemaLocation or xsi:noNamespaceSchema location.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSchemaMerger : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdSchemaMerger> Ptr;
+
+ /**
+ * Creates a new schema merger object that merges @p schema with @p otherSchema.
+ */
+ XsdSchemaMerger(const XsdSchema::Ptr &schema, const XsdSchema::Ptr &otherSchema);
+
+ /**
+ * Returns the merged schema.
+ */
+ XsdSchema::Ptr mergedSchema() const;
+
+ private:
+ void merge(const XsdSchema::Ptr &schema, const XsdSchema::Ptr &otherSchema);
+
+ XsdSchema::Ptr m_mergedSchema;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschemaparser.cpp b/src/xmlpatterns/schema/qxsdschemaparser.cpp
new file mode 100644
index 0000000000..9f1e75d2f2
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemaparser.cpp
@@ -0,0 +1,6012 @@
+
+#include "qxsdschemaparser_p.h"
+
+#include "private/qxmlutils_p.h"
+#include "qacceltreeresourceloader_p.h"
+#include "qautoptr_p.h"
+#include "qboolean_p.h"
+#include "qderivedinteger_p.h"
+#include "qderivedstring_p.h"
+#include "qqnamevalue_p.h"
+#include "qxmlquery_p.h"
+#include "qxpathhelper_p.h"
+#include "qxsdattributereference_p.h"
+#include "qxsdreference_p.h"
+#include "qxsdschematoken_p.h"
+
+#include <QtCore/QFile>
+#include <QtXmlPatterns/QXmlQuery>
+
+QT_BEGIN_NAMESPACE
+
+/**
+ * @page schema_overview Overview
+ * @section structure_and_components Structure and Components
+ *
+ * The schema validator code consists of 4 major components
+ *
+ * <dl>
+ * <dt>The schema parser (QPatternist::XsdSchemaParser)</dt>
+ * <dd>This component parses a XML document that is supplied via a QIODevice. It creates
+ * a so called (incomplete) 'compiled schema', which is a representation of the XML Schema
+ * structure as C++ objects.
+ * As the parser is a streaming parser, it can't resolve references to types or elements/attributes
+ * in place, therefor it creates resolver tasks which are passed to the schema resolver component
+ * for resolving at a later point in time.
+ * The parser does furthermore the basic XML structure constraint checking, e.g. if all required
+ * attributes are available or the order of the elements is correct.</dd>
+ *
+ * <dt>The schema resolver (QPatternist::XsdSchemaResolver)</dt>
+ * <dd>This component is activated after the schema parser component has been finished the parsing
+ * of all schemas. The resolver has been supplied with resolve tasks by the schema parser that
+ * it will resolve in this step now. Between working on the single resolver tasks, the resolver
+ * calls check methods from the schema checker component to make sure that some assertions are
+ * valid (e.g. no circular inheritance of types), so that the resolver can work without hassle.
+ * During resoving references to attribute or element groups it also checks for circular references
+ * of these groups.
+ * At the end of that phase we have a compiled schema that is fully resolved (not necessarily valid though).</dd>
+ *
+ * <dt>The schema checker (QPatternist::XsdSchemaChecker)</dt>
+ * <dd>This component does all the schema constraint checking as given by the Schema specification.
+ * At the end of that phase we have fully resolved and valid compiled schema that can be used for validation
+ * of instance documents.</dd>
+ *
+ * <dt>The validator (QPatternist::XsdValidatingInstanceReader)</dt>
+ * <dd>This component is responsible for validating a XML instance document, provided via a QIODevice, against
+ * a valid compiled schema.</dd>
+ * </dl>
+ *
+ * @ingroup Patternist_schema
+ */
+
+using namespace QPatternist;
+
+namespace QPatternist
+{
+
+/**
+ * @short A helper class for automatically handling namespace scopes of elements.
+ *
+ * This class should be instantiated at the beginning of each parse XYZ method.
+ */
+class ElementNamespaceHandler
+{
+ public:
+ /**
+ * Creates a new element namespace handler object.
+ *
+ * It checks whether the @p parser is on the right @p tag and it creates a new namespace
+ * context that contains the inherited and local namespace declarations.
+ */
+ ElementNamespaceHandler(const XsdSchemaToken::NodeName &tag, XsdSchemaParser *parser)
+ : m_parser(parser)
+ {
+ Q_ASSERT(m_parser->isStartElement() && (XsdSchemaToken::toToken(m_parser->name()) == tag) && (XsdSchemaToken::toToken(m_parser->namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI));
+ m_parser->m_namespaceSupport.pushContext();
+ m_parser->m_namespaceSupport.setPrefixes(m_parser->namespaceDeclarations());
+ }
+
+ /**
+ * Destroys the element namespace handler object.
+ *
+ * It destroys the local namespace context.
+ */
+ ~ElementNamespaceHandler()
+ {
+ m_parser->m_namespaceSupport.popContext();
+ }
+
+ private:
+ XsdSchemaParser *m_parser;
+};
+
+/**
+ * A helper class that checks for the right occurrence of
+ * xml tags with the help of a DFA.
+ */
+class TagValidationHandler
+{
+ public:
+ TagValidationHandler(XsdTagScope::Type tag, XsdSchemaParser *parser, const NamePool::Ptr &namePool)
+ : m_parser(parser), m_machine(namePool)
+ {
+ Q_ASSERT(m_parser->m_stateMachines.contains(tag));
+
+ m_machine = m_parser->m_stateMachines.value(tag);
+ m_machine.reset();
+ }
+
+ void validate(XsdSchemaToken::NodeName token)
+ {
+ if (token == XsdSchemaToken::NoKeyword) {
+ m_parser->error(QtXmlPatterns::tr("can not process unknown element %1").arg(formatElement(m_parser->name().toString())));
+ return;
+ }
+
+ if (!m_machine.proceed(token)) {
+ m_parser->error(QtXmlPatterns::tr("element %1 is not allowed in this scope").arg(formatElement(XsdSchemaToken::toString(token))));
+ return;
+ }
+ }
+
+ void finalize() const
+ {
+ if (!m_machine.inEndState()) {
+ m_parser->error(QtXmlPatterns::tr("child element is missing in that scope"));
+ }
+ }
+
+ private:
+ XsdSchemaParser *m_parser;
+ XsdStateMachine<XsdSchemaToken::NodeName> m_machine;
+};
+
+}
+
+/**
+ * Returns a list of all particles with group references that appear at any level of
+ * the given unresolved @p group.
+ */
+static XsdParticle::List collectGroupRef(const XsdModelGroup::Ptr &group)
+{
+ XsdParticle::List refParticles;
+
+ XsdParticle::List particles = group->particles();
+ for (int i = 0; i < particles.count(); ++i) {
+ if (particles.at(i)->term()->isReference()) {
+ const XsdReference::Ptr reference(particles.at(i)->term());
+ if (reference->type() == XsdReference::ModelGroup)
+ refParticles.append(particles.at(i));
+ }
+ if (particles.at(i)->term()->isModelGroup()) {
+ refParticles << collectGroupRef(XsdModelGroup::Ptr(particles.at(i)->term()));
+ }
+ }
+
+ return refParticles;
+}
+
+/**
+ * Helper function that works around the limited facilities of
+ * QUrl/AnyURI::fromLexical to detect invalid URIs
+ */
+inline static bool isValidUri(const QString &string)
+{
+ // an empty URI points to the current document as defined in RFC 2396 (4.2)
+ if (string.isEmpty())
+ return true;
+
+ // explicit check as that is not checked by the code below
+ if (string.startsWith(QLatin1String("##")))
+ return false;
+
+ const AnyURI::Ptr uri = AnyURI::fromLexical(string);
+ return (!(uri->hasError()));
+}
+
+XsdSchemaParser::XsdSchemaParser(const XsdSchemaContext::Ptr &context, const XsdSchemaParserContext::Ptr &parserContext, QIODevice *device)
+ : MaintainingReader<XsdSchemaToken, XsdTagScope::Type>(parserContext->elementDescriptions(), QSet<XsdSchemaToken::NodeName>(), context, device)
+ , m_context(context)
+ , m_parserContext(parserContext)
+ , m_namePool(m_parserContext->namePool())
+ , m_namespaceSupport(m_namePool)
+{
+ m_schema = m_parserContext->schema();
+ m_schemaResolver = m_parserContext->resolver();
+ m_idCache = XsdIdCache::Ptr(new XsdIdCache());
+
+ setupStateMachines();
+ setupBuiltinTypeNames();
+}
+
+void XsdSchemaParser::setIncludedSchemas(const NamespaceSet &schemas)
+{
+ m_includedSchemas = schemas;
+}
+
+void XsdSchemaParser::setImportedSchemas(const NamespaceSet &schemas)
+{
+ m_importedSchemas = schemas;
+}
+
+void XsdSchemaParser::setRedefinedSchemas(const NamespaceSet &schemas)
+{
+ m_redefinedSchemas = schemas;
+}
+
+void XsdSchemaParser::setTargetNamespace(const QString &targetNamespace)
+{
+ m_targetNamespace = targetNamespace;
+}
+
+void XsdSchemaParser::setTargetNamespaceExtended(const QString &targetNamespace)
+{
+ m_targetNamespace = targetNamespace;
+ m_namespaceSupport.setTargetNamespace(m_namePool->allocateNamespace(m_targetNamespace));
+}
+
+void XsdSchemaParser::setDocumentURI(const QUrl &uri)
+{
+ qDebug("%s", qPrintable(uri.toString()));
+ m_documentURI = uri;
+
+ // prevent to get included/imported/redefined twice
+ m_includedSchemas.insert(uri);
+ m_importedSchemas.insert(uri);
+}
+
+QUrl XsdSchemaParser::documentURI() const
+{
+ return m_documentURI;
+}
+
+bool XsdSchemaParser::isAnyAttributeAllowed() const
+{
+ return false;
+}
+
+bool XsdSchemaParser::parse(ParserType parserType)
+{
+ m_componentLocationHash.clear();
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ if (isSchemaTag(XsdSchemaToken::Schema, token, namespaceToken)) {
+ parseSchema(parserType);
+ } else {
+ error(QtXmlPatterns::tr("document is not a XML schema"));
+ }
+ }
+ }
+
+ m_schemaResolver->addComponentLocationHash(m_componentLocationHash);
+ m_schemaResolver->setDefaultOpenContent(m_defaultOpenContent, m_defaultOpenContentAppliesToEmpty);
+
+ return true;
+}
+
+void XsdSchemaParser::error(const QString &msg)
+{
+ MaintainingReader<XsdSchemaToken, XsdTagScope::Type>::error(msg, XsdSchemaContext::XSDError);
+}
+
+void XsdSchemaParser::attributeContentError(const char *attributeName, const char *elementName, const QString &value, const SchemaType::Ptr &type)
+{
+ if (type) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element contains invalid content: {%3} is not a value of type %4")
+ .arg(formatAttribute(attributeName))
+ .arg(formatElement(elementName))
+ .arg(formatData(value))
+ .arg(formatType(m_namePool, type)));
+ } else {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element contains invalid content: {%3}")
+ .arg(formatAttribute(attributeName))
+ .arg(formatElement(elementName))
+ .arg(formatData(value)));
+ }
+}
+
+void XsdSchemaParser::parseSchema(ParserType parserType)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Schema, this);
+
+ validateElement(XsdTagScope::Schema);
+
+ // parse attributes
+
+ if (parserType == TopLevelParser) {
+ if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
+ m_targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
+ }
+ } else if (parserType == IncludeParser) {
+ // m_targetNamespace is set to the target namespace of the including schema at this point
+
+ if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
+ const QString targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
+
+ if (m_targetNamespace != targetNamespace) {
+ error(QtXmlPatterns::tr("target namespace %1 of included schema is different from the target namespace %2 as defined by the including schema")
+ .arg(formatURI(targetNamespace)).arg(formatURI(m_targetNamespace)));
+ return;
+ }
+ }
+ } else if (parserType == ImportParser) {
+ // m_targetNamespace is set to the target namespace from the namespace attribute of the <import> tag at this point
+
+ QString targetNamespace;
+ if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
+ targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
+ }
+
+ if (m_targetNamespace != targetNamespace) {
+ error(QtXmlPatterns::tr("target namespace %1 of imported schema is different from the target namespace %2 as defined by the importing schema")
+ .arg(formatURI(targetNamespace)).arg(formatURI(m_targetNamespace)));
+ return;
+ }
+ } else if (parserType == RedefineParser) {
+ // m_targetNamespace is set to the target namespace of the redefining schema at this point
+
+ if (hasAttribute(QString::fromLatin1("targetNamespace"))) {
+ const QString targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema");
+
+ if (m_targetNamespace != targetNamespace) {
+ error(QtXmlPatterns::tr("target namespace %1 of imported schema is different from the target namespace %2 as defined by the importing schema")
+ .arg(formatURI(targetNamespace)).arg(formatURI(m_targetNamespace)));
+ return;
+ }
+ }
+ }
+
+ if (hasAttribute(QString::fromLatin1("attributeFormDefault"))) {
+ const QString value = readAttribute(QString::fromLatin1("attributeFormDefault"));
+ if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
+ attributeContentError("attributeFormDefault", "schema", value);
+ return;
+ }
+
+ m_attributeFormDefault = value;
+ } else {
+ m_attributeFormDefault = QString::fromLatin1("unqualified");
+ }
+
+ if (hasAttribute(QString::fromLatin1("elementFormDefault"))) {
+ const QString value = readAttribute(QString::fromLatin1("elementFormDefault"));
+ if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
+ attributeContentError("elementFormDefault", "schema", value);
+ return;
+ }
+
+ m_elementFormDefault = value;
+ } else {
+ m_elementFormDefault = QString::fromLatin1("unqualified");
+ }
+
+ if (hasAttribute(QString::fromLatin1("blockDefault"))) {
+ const QString blockDefault = readAttribute(QString::fromLatin1("blockDefault"));
+ const QStringList blockDefaultList = blockDefault.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < blockDefaultList.count(); ++i) {
+ const QString value = blockDefaultList.at(i);
+ if (value != QString::fromLatin1("#all") &&
+ value != QString::fromLatin1("extension") &&
+ value != QString::fromLatin1("restriction") &&
+ value != QString::fromLatin1("substitution")) {
+ attributeContentError("blockDefault", "schema", value);
+ return;
+ }
+ }
+
+ m_blockDefault = blockDefault;
+ }
+
+ if (hasAttribute(QString::fromLatin1("finalDefault"))) {
+ const QString finalDefault = readAttribute(QString::fromLatin1("finalDefault"));
+ const QStringList finalDefaultList = finalDefault.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < finalDefaultList.count(); ++i) {
+ const QString value = finalDefaultList.at(i);
+ if (value != QString::fromLatin1("#all") &&
+ value != QString::fromLatin1("extension") &&
+ value != QString::fromLatin1("restriction") &&
+ value != QString::fromLatin1("list") &&
+ value != QString::fromLatin1("union")) {
+ attributeContentError("finalDefault", "schema", value);
+ return;
+ }
+ }
+
+ m_finalDefault = finalDefault;
+ }
+
+ if (hasAttribute(QString::fromLatin1("xpathDefaultNamespace"))) {
+ const QString xpathDefaultNamespace = readAttribute(QString::fromLatin1("xpathDefaultNamespace"));
+ if (xpathDefaultNamespace != QString::fromLatin1("##defaultNamespace") &&
+ xpathDefaultNamespace != QString::fromLatin1("##targetNamespace") &&
+ xpathDefaultNamespace != QString::fromLatin1("##local")) {
+ if (!isValidUri(xpathDefaultNamespace)) {
+ attributeContentError("xpathDefaultNamespace", "schema", xpathDefaultNamespace);
+ return;
+ }
+ }
+ m_xpathDefaultNamespace = xpathDefaultNamespace;
+ } else {
+ m_xpathDefaultNamespace = QString::fromLatin1("##local");
+ }
+
+ if (hasAttribute(QString::fromLatin1("defaultAttributes"))) {
+ const QString attrGroupName = readQNameAttribute(QString::fromLatin1("defaultAttributes"), "schema");
+ convertName(attrGroupName, NamespaceSupport::ElementName, m_defaultAttributes); // translate qualified name into QXmlName
+ }
+
+ if (hasAttribute(QString::fromLatin1("version"))) {
+ const QString version = readAttribute(QString::fromLatin1("version"));
+ }
+
+ if (hasAttribute(QString::fromLatin1("http://www.w3.org/XML/1998/namespace"), QString::fromLatin1("lang"))) {
+ const QString value = readAttribute(QString::fromLatin1("lang"), QString::fromLatin1("http://www.w3.org/XML/1998/namespace"));
+
+ const QRegExp exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*"));
+ if (!exp.exactMatch(value)) {
+ attributeContentError("xml:lang", "schema", value);
+ return;
+ }
+ }
+
+ validateIdAttribute("schema");
+
+ TagValidationHandler tagValidator(XsdTagScope::Schema, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Include, token, namespaceToken)) {
+ parseInclude();
+ } else if (isSchemaTag(XsdSchemaToken::Import, token, namespaceToken)) {
+ parseImport();
+ } else if (isSchemaTag(XsdSchemaToken::Redefine, token, namespaceToken)) {
+ parseRedefine();
+ } else if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ m_schema->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::DefaultOpenContent, token, namespaceToken)) {
+ parseDefaultOpenContent();
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ const XsdSimpleType::Ptr type = parseGlobalSimpleType();
+ addType(type);
+ } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
+ const XsdComplexType::Ptr type = parseGlobalComplexType();
+ addType(type);
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdModelGroup::Ptr group = parseNamedGroup();
+ addElementGroup(group);
+ } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
+ XsdAttributeGroup::Ptr attributeGroup = parseNamedAttributeGroup();
+ addAttributeGroup(attributeGroup);
+ } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
+ const XsdElement::Ptr element = parseGlobalElement();
+ addElement(element);
+ } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
+ const XsdAttribute::Ptr attribute = parseGlobalAttribute();
+ addAttribute(attribute);
+ } else if (isSchemaTag(XsdSchemaToken::Notation, token, namespaceToken)) {
+ const XsdNotation::Ptr notation = parseNotation();
+ addNotation(notation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ m_schema->setTargetNamespace(m_targetNamespace);
+}
+
+void XsdSchemaParser::parseInclude()
+{
+ Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Include &&
+ XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI);
+
+ validateElement(XsdTagScope::Include);
+
+ // parse attributes
+ const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation"));
+
+ QUrl url(schemaLocation);
+ if (url.isRelative()) {
+ Q_ASSERT(m_documentURI.isValid());
+
+ url = m_documentURI.resolved(url);
+ }
+
+ if (m_includedSchemas.contains(url)) {
+ // we have included that file already, according to the schema spec we are
+ // allowed to silently skip it.
+ } else {
+ m_includedSchemas.insert(url);
+
+ const AutoPtr<QNetworkReply> reply(AccelTreeResourceLoader::load(url, m_context->networkAccessManager(),
+ m_context, AccelTreeResourceLoader::ContinueOnError));
+ if (reply) {
+ // parse the included schema by a different parser but with the same context
+ XsdSchemaParser parser(m_context, m_parserContext, reply.data());
+ parser.setDocumentURI(url);
+ parser.setTargetNamespaceExtended(m_targetNamespace);
+ parser.setIncludedSchemas(m_includedSchemas);
+ parser.setImportedSchemas(m_importedSchemas);
+ parser.setRedefinedSchemas(m_redefinedSchemas);
+ if (!parser.parse(XsdSchemaParser::IncludeParser))
+ return;
+ }
+ }
+
+ validateIdAttribute("include");
+
+ TagValidationHandler tagValidator(XsdTagScope::Include, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ m_schema->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+}
+
+void XsdSchemaParser::parseImport()
+{
+ Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Import &&
+ XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI);
+
+ validateElement(XsdTagScope::Import);
+
+ // parse attributes
+ QString importNamespace;
+ if (hasAttribute(QString::fromLatin1("namespace"))) {
+ importNamespace = readAttribute(QString::fromLatin1("namespace"));
+ if (importNamespace == m_targetNamespace) {
+ error(QtXmlPatterns::tr("%1 element is not allowed to have the same %2 attribute value as the target namespace %3")
+ .arg(formatElement("import"))
+ .arg(formatAttribute("namespace"))
+ .arg(formatURI(m_targetNamespace)));
+ return;
+ }
+ } else {
+ if (m_targetNamespace.isEmpty()) {
+ error(QtXmlPatterns::tr("%1 element without %2 attribute is not allowed inside schema without target namespace")
+ .arg(formatElement("import"))
+ .arg(formatAttribute("namespace")));
+ return;
+ }
+ }
+
+ if (hasAttribute(QString::fromLatin1("schemaLocation"))) {
+ const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation"));
+
+ QUrl url(schemaLocation);
+ if (url.isRelative()) {
+ Q_ASSERT(m_documentURI.isValid());
+
+ url = m_documentURI.resolved(url);
+ }
+
+ if (m_importedSchemas.contains(url)) {
+ // we have imported that file already, according to the schema spec we are
+ // allowed to silently skip it.
+ } else {
+ m_importedSchemas.insert(url);
+
+ // as it is possible that well known schemas (e.g. XSD for XML) are only referenced by
+ // namespace we should add it as well
+ m_importedSchemas.insert(importNamespace);
+
+ AutoPtr<QNetworkReply> reply(AccelTreeResourceLoader::load(url, m_context->networkAccessManager(),
+ m_context, AccelTreeResourceLoader::ContinueOnError));
+ if (reply) {
+ // parse the included schema by a different parser but with the same context
+ XsdSchemaParser parser(m_context, m_parserContext, reply.data());
+ parser.setDocumentURI(url);
+ parser.setTargetNamespace(importNamespace);
+ parser.setIncludedSchemas(m_includedSchemas);
+ parser.setImportedSchemas(m_importedSchemas);
+ parser.setRedefinedSchemas(m_redefinedSchemas);
+ if (!parser.parse(XsdSchemaParser::ImportParser))
+ return;
+ }
+ }
+ } else {
+ // check whether it is a known namespace we have a builtin schema for
+ if (!importNamespace.isEmpty()) {
+ if (!m_importedSchemas.contains(importNamespace)) {
+ m_importedSchemas.insert(importNamespace);
+
+ QFile file(QString::fromLatin1(":") + importNamespace);
+ if (file.open(QIODevice::ReadOnly)) {
+ XsdSchemaParser parser(m_context, m_parserContext, &file);
+ parser.setDocumentURI(importNamespace);
+ parser.setTargetNamespace(importNamespace);
+ parser.setIncludedSchemas(m_includedSchemas);
+ parser.setImportedSchemas(m_importedSchemas);
+ parser.setRedefinedSchemas(m_redefinedSchemas);
+ if (!parser.parse(XsdSchemaParser::ImportParser))
+ return;
+ }
+ }
+ } else {
+ // we don't import anything... that is valid according to the schema
+ }
+ }
+
+ validateIdAttribute("import");
+
+ TagValidationHandler tagValidator(XsdTagScope::Import, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ m_schema->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+}
+
+void XsdSchemaParser::parseRedefine()
+{
+ Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Redefine &&
+ XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI);
+
+ validateElement(XsdTagScope::Redefine);
+
+ // parse attributes
+ validateIdAttribute("redefine");
+
+ const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation"));
+
+ TagValidationHandler tagValidator(XsdTagScope::Redefine, this, m_namePool);
+
+ XsdSimpleType::List redefinedSimpleTypes;
+ XsdComplexType::List redefinedComplexTypes;
+ XsdModelGroup::List redefinedGroups;
+ XsdAttributeGroup::List redefinedAttributeGroups;
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ m_schema->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ const XsdSimpleType::Ptr type = parseGlobalSimpleType();
+ redefinedSimpleTypes.append(type);
+
+ const QXmlName baseTypeName = m_parserContext->resolver()->baseTypeNameOfType(type);
+ if (baseTypeName != type->name(m_namePool)) {
+ error(QString::fromLatin1("redefined simple type %1 must have itself as base type").arg(formatType(m_namePool, type)));
+ return;
+ }
+ } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
+ const XsdComplexType::Ptr type = parseGlobalComplexType();
+ redefinedComplexTypes.append(type);
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
+
+ // 5
+ const QXmlName baseTypeName = m_parserContext->resolver()->baseTypeNameOfType(type);
+ if (baseTypeName != type->name(m_namePool)) {
+ error(QString::fromLatin1("redefined complex type %1 must have itself as base type").arg(formatType(m_namePool, type)));
+ return;
+ }
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdModelGroup::Ptr group = parseNamedGroup();
+ redefinedGroups.append(group);
+ } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
+ const XsdAttributeGroup::Ptr group = parseNamedAttributeGroup();
+ redefinedAttributeGroups.append(group);
+
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ bool locationMustResolve = false;
+ if (!redefinedSimpleTypes.isEmpty() || !redefinedComplexTypes.isEmpty() ||
+ !redefinedGroups.isEmpty() || !redefinedAttributeGroups.isEmpty()) {
+ locationMustResolve = true;
+ }
+
+ QUrl url(schemaLocation);
+ if (url.isRelative()) {
+ Q_ASSERT(m_documentURI.isValid());
+
+ url = m_documentURI.resolved(url);
+ }
+
+ // we parse the schema given in the redefine tag into its own context
+ const XsdSchemaParserContext::Ptr redefinedContext(new XsdSchemaParserContext(m_namePool, m_context));
+
+ if (m_redefinedSchemas.contains(url)) {
+ // we have redefined that file already, according to the schema spec we are
+ // allowed to silently skip it.
+ } else {
+ m_redefinedSchemas.insert(url);
+ QNetworkReply *reply = AccelTreeResourceLoader::load(url, m_context->networkAccessManager(),
+ m_context,
+ (locationMustResolve ? AccelTreeResourceLoader::FailOnError : AccelTreeResourceLoader::ContinueOnError));
+ if (reply) {
+ // parse the included schema by a different parser but with the same context
+ XsdSchemaParser parser(m_context, redefinedContext, reply);
+ parser.setDocumentURI(url);
+ parser.setTargetNamespaceExtended(m_targetNamespace);
+ parser.setIncludedSchemas(m_includedSchemas);
+ parser.setImportedSchemas(m_importedSchemas);
+ parser.setRedefinedSchemas(m_redefinedSchemas);
+ if (!parser.parse(XsdSchemaParser::RedefineParser))
+ return;
+
+ delete reply;
+ }
+ }
+
+ XsdSimpleType::List contextSimpleTypes = redefinedContext->schema()->simpleTypes();
+ XsdComplexType::List contextComplexTypes = redefinedContext->schema()->complexTypes();
+ XsdModelGroup::List contextGroups = redefinedContext->schema()->elementGroups();
+ XsdAttributeGroup::List contextAttributeGroups = redefinedContext->schema()->attributeGroups();
+
+ // now we do the actual redefinition:
+
+ // iterate over all redefined simple types
+ for (int i = 0; i < redefinedSimpleTypes.count(); ++i) {
+ XsdSimpleType::Ptr redefinedType = redefinedSimpleTypes.at(i);
+
+ //TODONEXT: validation
+
+ // search the definition they override in the context types
+ bool found = false;
+ for (int j = 0; j < contextSimpleTypes.count(); ++j) {
+ XsdSimpleType::Ptr contextType = contextSimpleTypes.at(j);
+
+ if (redefinedType->name(m_namePool) == contextType->name(m_namePool)) { // we found the right type
+ found = true;
+
+ // 1) set name of context type to empty name
+ contextType->setName(m_parserContext->createAnonymousName(QString()));
+
+ // 2) set the context type as base type for the redefined type
+ redefinedType->setWxsSuperType(contextType);
+
+ // 3) remove the base type resolving job from the resolver as
+ // we have set the base type here explicitely
+ m_parserContext->resolver()->removeSimpleRestrictionBase(redefinedType);
+
+ // 4) add the redefined type to the schema
+ addType(redefinedType);
+
+ // 5) add the context type as anonymous type, so the resolver
+ // can resolve it further.
+ addAnonymousType(contextType);
+
+ // 6) remove the context type from the list
+ contextSimpleTypes.removeAt(j);
+
+ break;
+ }
+ }
+
+ if (!found) {
+ error(QString::fromLatin1("no matching type found to redefine simple type %1").arg(formatType(m_namePool, redefinedType)));
+ return;
+ }
+ }
+
+ // add all remaining context simple types to the schema
+ for (int i = 0; i < contextSimpleTypes.count(); ++i) {
+ addType(contextSimpleTypes.at(i));
+ }
+
+ // iterate over all redefined complex types
+ for (int i = 0; i < redefinedComplexTypes.count(); ++i) {
+ XsdComplexType::Ptr redefinedType = redefinedComplexTypes.at(i);
+
+ //TODONEXT: validation
+
+ // search the definition they override in the context types
+ bool found = false;
+ for (int j = 0; j < contextComplexTypes.count(); ++j) {
+ XsdComplexType::Ptr contextType = contextComplexTypes.at(j);
+
+ if (redefinedType->name(m_namePool) == contextType->name(m_namePool)) { // we found the right type
+ found = true;
+
+ // 1) set name of context type to empty name
+ contextType->setName(m_parserContext->createAnonymousName(QString()));
+
+ // 2) set the context type as base type for the redefined type
+ redefinedType->setWxsSuperType(contextType);
+
+ // 3) remove the base type resolving job from the resolver as
+ // we have set the base type here explicitely
+ m_parserContext->resolver()->removeComplexBaseType(redefinedType);
+
+ // 4) add the redefined type to the schema
+ addType(redefinedType);
+
+ // 5) add the context type as anonymous type, so the resolver
+ // can resolve its attribute uses etc.
+ addAnonymousType(contextType);
+
+ // 6) remove the context type from the list
+ contextComplexTypes.removeAt(j);
+
+ break;
+ }
+ }
+
+ if (!found) {
+ error(QString::fromLatin1("no matching type found to redefine complex type %1").arg(formatType(m_namePool, redefinedType)));
+ return;
+ }
+ }
+
+ // iterate over all redefined element groups
+ for (int i = 0; i < redefinedGroups.count(); ++i) {
+ const XsdModelGroup::Ptr group(redefinedGroups.at(i));
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
+
+ // 6
+ const XsdParticle::List particles = collectGroupRef(group);
+ XsdParticle::Ptr referencedParticle;
+ int sameNameCounter = 0;
+ for (int i = 0; i < particles.count(); ++i) {
+ const XsdReference::Ptr ref(particles.at(i)->term());
+ if (ref->referenceName() == group->name(m_namePool)) {
+ referencedParticle = particles.at(i);
+
+ if (referencedParticle->minimumOccurs() != 1 || referencedParticle->maximumOccurs() != 1 || referencedParticle->maximumOccursUnbounded()) { // 6.1.2
+ error(QString::fromLatin1("redefined group %1 can not contain reference to itself with minOccurs or maxOccurs != 1").arg(formatKeyword(group->displayName(m_namePool))));
+ return;
+ }
+ sameNameCounter++;
+ }
+ }
+
+ // 6.1.1
+ if (sameNameCounter > 1) {
+ error(QString::fromLatin1("redefined group %1 can not contain multiple references to itself").arg(formatKeyword(group->displayName(m_namePool))));
+ return;
+ }
+
+ // search the group definition in the included schema (S2)
+ XsdModelGroup::Ptr contextGroup;
+ for (int j = 0; j < contextGroups.count(); ++j) {
+ if (group->name(m_namePool) == contextGroups.at(j)->name(m_namePool)) {
+ contextGroup = contextGroups.at(j);
+ break;
+ }
+ }
+
+ if (!contextGroup) { // 6.2.1
+ error(QString::fromLatin1("redefined group %1 has no occurrence in included schema").arg(formatKeyword(group->displayName(m_namePool))));
+ return;
+ }
+
+ if (sameNameCounter == 1) {
+ // there was a self reference in the redefined group, so use the
+ // group from the included schema
+
+ // set a anonymous name to the group of the included schema
+ contextGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(contextGroup->name(m_namePool).namespaceURI())));
+
+ // replace the self-reference with the group from the included schema
+ referencedParticle->setTerm(contextGroup);
+
+ addElementGroup(group);
+
+ addElementGroup(contextGroup);
+ contextGroups.removeAll(contextGroup);
+ } else {
+ // there was no self reference in the redefined group
+
+ // just add the redefined group...
+ addElementGroup(group);
+
+ // we have to add them, otherwise it is not resolved and we can't validate it later
+ contextGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(contextGroup->name(m_namePool).namespaceURI())));
+ addElementGroup(contextGroup);
+
+ m_schemaResolver->addRedefinedGroups(group, contextGroup);
+
+ // ...and forget about the group from the included schema
+ contextGroups.removeAll(contextGroup);
+ }
+ }
+
+ // iterate over all redefined attribute groups
+ for (int i = 0; i < redefinedAttributeGroups.count(); ++i) {
+ const XsdAttributeGroup::Ptr group(redefinedAttributeGroups.at(i));
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine
+
+ // 7
+
+ // 7.1
+ int sameNameCounter = 0;
+ for (int j = 0; j < group->attributeUses().count(); ++j) {
+ const XsdAttributeUse::Ptr attributeUse(group->attributeUses().at(j));
+ if (attributeUse->isReference()) {
+ const XsdAttributeReference::Ptr reference(attributeUse);
+ if (reference->type() == XsdAttributeReference::AttributeGroup) {
+ if (group->name(m_namePool) == reference->referenceName())
+ sameNameCounter++;
+ }
+ }
+ }
+ if (sameNameCounter > 1) {
+ error(QString::fromLatin1("redefined attribute group %1 can not contain multiple references to itself").arg(formatKeyword(group->displayName(m_namePool))));
+ return;
+ }
+
+ // search the attribute group definition in the included schema (S2)
+ XsdAttributeGroup::Ptr baseGroup;
+ for (int j = 0; j < contextAttributeGroups.count(); ++j) {
+ const XsdAttributeGroup::Ptr contextGroup(contextAttributeGroups.at(j));
+ if (group->name(m_namePool) == contextGroup->name(m_namePool)) {
+ baseGroup = contextGroup;
+ break;
+ }
+ }
+
+ if (!baseGroup) { // 7.2.1
+ error(QString::fromLatin1("redefined attribute group %1 has no occurrence in included schema").arg(formatKeyword(group->displayName(m_namePool))));
+ return;
+ }
+
+ if (sameNameCounter == 1) {
+
+ // first set an anonymous name to the attribute group from the included
+ // schema
+ baseGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(baseGroup->name(m_namePool).namespaceURI())));
+
+ // iterate over the attribute uses of the redefined attribute group
+ // and replace the self-reference with the attribute group from the
+ // included schema
+ for (int j = 0; j < group->attributeUses().count(); ++j) {
+ const XsdAttributeUse::Ptr attributeUse(group->attributeUses().at(j));
+ if (attributeUse->isReference()) {
+ const XsdAttributeReference::Ptr reference(attributeUse);
+ if (reference->type() == XsdAttributeReference::AttributeGroup) {
+ if (group->name(m_namePool) == reference->referenceName()) {
+ reference->setReferenceName(baseGroup->name(m_namePool));
+ break;
+ }
+ }
+ }
+ }
+
+ // add both groups to the target schema
+ addAttributeGroup(baseGroup);
+ addAttributeGroup(group);
+
+ contextAttributeGroups.removeAll(baseGroup);
+ }
+
+ if (sameNameCounter == 0) { // 7.2
+
+ // we have to add them, otherwise it is not resolved and we can't validate it later
+ baseGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(baseGroup->name(m_namePool).namespaceURI())));
+ addAttributeGroup(baseGroup);
+
+ m_schemaResolver->addRedefinedAttributeGroups(group, baseGroup);
+
+ // just add the redefined attribute group to the target schema...
+ addAttributeGroup(group);
+
+ // ... and forget about the one from the included schema
+ contextAttributeGroups.removeAll(baseGroup);
+ }
+ }
+
+ // add all remaining context complex types to the schema
+ for (int i = 0; i < contextComplexTypes.count(); ++i) {
+ addType(contextComplexTypes.at(i));
+ }
+
+ // add all remaining context element groups to the schema
+ for (int i = 0; i < contextGroups.count(); ++i) {
+ addElementGroup(contextGroups.at(i));
+ }
+
+ // add all remaining context attribute groups to the schema
+ for (int i = 0; i < contextAttributeGroups.count(); ++i) {
+ addAttributeGroup(contextAttributeGroups.at(i));
+ }
+
+ // copy all elements, attributes and notations
+ const XsdElement::List contextElements = redefinedContext->schema()->elements();
+ for (int i = 0; i < contextElements.count(); ++i) {
+ addElement(contextElements.at(i));
+ }
+
+ const XsdAttribute::List contextAttributes = redefinedContext->schema()->attributes();
+ for (int i = 0; i < contextAttributes.count(); ++i) {
+ addAttribute(contextAttributes.at(i));
+ }
+
+ const XsdNotation::List contextNotations = redefinedContext->schema()->notations();
+ for (int i = 0; i < contextNotations.count(); ++i) {
+ addNotation(contextNotations.at(i));
+ }
+
+ // push all data to resolve from the context resolver to our resolver
+ redefinedContext->resolver()->copyDataTo(m_parserContext->resolver());
+
+ tagValidator.finalize();
+}
+
+XsdAnnotation::Ptr XsdSchemaParser::parseAnnotation()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Annotation, this);
+
+ validateElement(XsdTagScope::Annotation);
+
+ // parse attributes
+ validateIdAttribute("annotation");
+
+ TagValidationHandler tagValidator(XsdTagScope::Annotation, this, m_namePool);
+
+ const XsdAnnotation::Ptr annotation(new XsdAnnotation());
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Appinfo, token, namespaceToken)) {
+ const XsdApplicationInformation::Ptr info = parseAppInfo();
+ annotation->addApplicationInformation(info);
+ } else if (isSchemaTag(XsdSchemaToken::Documentation, token, namespaceToken)) {
+ const XsdDocumentation::Ptr documentation = parseDocumentation();
+ annotation->addDocumentation(documentation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return annotation;
+}
+
+XsdApplicationInformation::Ptr XsdSchemaParser::parseAppInfo()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Appinfo, this);
+
+ validateElement(XsdTagScope::AppInfo);
+
+ const XsdApplicationInformation::Ptr info(new XsdApplicationInformation());
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("source"))) {
+ const QString value = readAttribute(QString::fromLatin1("source"));
+
+ if (!isValidUri(value)) {
+ attributeContentError("source", "appinfo", value, BuiltinTypes::xsAnyURI);
+ return info;
+ }
+
+ if (!value.isEmpty()) {
+ const AnyURI::Ptr source = AnyURI::fromLexical(value);
+ info->setSource(source);
+ }
+ }
+
+ while (!atEnd()) { //EVAL: can be anything... what to do?
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement())
+ parseUnknownDocumentation();
+ }
+
+ return info;
+}
+
+XsdDocumentation::Ptr XsdSchemaParser::parseDocumentation()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Documentation, this);
+
+ validateElement(XsdTagScope::Documentation);
+
+ const XsdDocumentation::Ptr documentation(new XsdDocumentation());
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("source"))) {
+ const QString value = readAttribute(QString::fromLatin1("source"));
+
+ if (!isValidUri(value)) {
+ attributeContentError("source", "documentation", value, BuiltinTypes::xsAnyURI);
+ return documentation;
+ }
+
+ if (!value.isEmpty()) {
+ const AnyURI::Ptr source = AnyURI::fromLexical(value);
+ documentation->setSource(source);
+ }
+ }
+
+ if (hasAttribute(QString::fromLatin1("http://www.w3.org/XML/1998/namespace"), QString::fromLatin1("lang"))) {
+ const QString value = readAttribute(QString::fromLatin1("lang"), QString::fromLatin1("http://www.w3.org/XML/1998/namespace"));
+
+ const QRegExp exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*"));
+ if (!exp.exactMatch(value)) {
+ attributeContentError("xml:lang", "documentation", value);
+ return documentation;
+ }
+ }
+
+ while (!atEnd()) { //EVAL: can by any... what to do?
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement())
+ parseUnknownDocumentation();
+ }
+
+ return documentation;
+}
+
+void XsdSchemaParser::parseDefaultOpenContent()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::DefaultOpenContent, this);
+
+ validateElement(XsdTagScope::DefaultOpenContent);
+
+ m_defaultOpenContent = XsdComplexType::OpenContent::Ptr(new XsdComplexType::OpenContent());
+
+ if (hasAttribute(QString::fromLatin1("appliesToEmpty"))) {
+ const QString value = readAttribute(QString::fromLatin1("appliesToEmpty"));
+ const Boolean::Ptr appliesToEmpty = Boolean::fromLexical(value);
+ if (appliesToEmpty->hasError()) {
+ attributeContentError("appliesToEmpty", "defaultOpenContent", value, BuiltinTypes::xsBoolean);
+ return;
+ }
+
+ m_defaultOpenContentAppliesToEmpty = appliesToEmpty->as<Boolean>()->value();
+ } else {
+ m_defaultOpenContentAppliesToEmpty = false;
+ }
+
+ if (hasAttribute(QString::fromLatin1("mode"))) {
+ const QString mode = readAttribute(QString::fromLatin1("mode"));
+
+ if (mode == QString::fromLatin1("interleave")) {
+ m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave);
+ } else if (mode == QString::fromLatin1("suffix")) {
+ m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Suffix);
+ } else {
+ attributeContentError("mode", "defaultOpenContent", mode);
+ return;
+ }
+ } else {
+ m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave);
+ }
+
+ validateIdAttribute("defaultOpenContent");
+
+ TagValidationHandler tagValidator(XsdTagScope::DefaultOpenContent, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ m_defaultOpenContent->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
+ const XsdParticle::Ptr particle;
+ const XsdWildcard::Ptr wildcard = parseAny(particle);
+ m_defaultOpenContent->setWildcard(wildcard);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+}
+
+XsdSimpleType::Ptr XsdSchemaParser::parseGlobalSimpleType()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleType, this);
+
+ validateElement(XsdTagScope::GlobalSimpleType);
+
+ const XsdSimpleType::Ptr simpleType(new XsdSimpleType());
+ simpleType->setCategory(XsdSimpleType::SimpleTypeAtomic); // just to make sure it's not invalid
+
+ // parse attributes
+ const SchemaType::DerivationConstraints allowedConstraints(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint | SchemaType::ListConstraint | SchemaType::UnionConstraint);
+ simpleType->setDerivationConstraints(readDerivationConstraintAttribute(allowedConstraints, "simpleType"));
+
+ const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("simpleType"));
+ simpleType->setName(objectName);
+
+ validateIdAttribute("simpleType");
+
+ TagValidationHandler tagValidator(XsdTagScope::GlobalSimpleType, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ simpleType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
+ parseSimpleRestriction(simpleType);
+ } else if (isSchemaTag(XsdSchemaToken::List, token, namespaceToken)) {
+ parseList(simpleType);
+ } else if (isSchemaTag(XsdSchemaToken::Union, token, namespaceToken)) {
+ parseUnion(simpleType);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return simpleType;
+}
+
+XsdSimpleType::Ptr XsdSchemaParser::parseLocalSimpleType()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleType, this);
+
+ validateElement(XsdTagScope::LocalSimpleType);
+
+ const XsdSimpleType::Ptr simpleType(new XsdSimpleType());
+ simpleType->setCategory(XsdSimpleType::SimpleTypeAtomic); // just to make sure it's not invalid
+ simpleType->setName(m_parserContext->createAnonymousName(m_targetNamespace));
+
+ validateIdAttribute("simpleType");
+
+ TagValidationHandler tagValidator(XsdTagScope::LocalSimpleType, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ simpleType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
+ parseSimpleRestriction(simpleType);
+ } else if (isSchemaTag(XsdSchemaToken::List, token, namespaceToken)) {
+ parseList(simpleType);
+ } else if (isSchemaTag(XsdSchemaToken::Union, token, namespaceToken)) {
+ parseUnion(simpleType);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return simpleType;
+}
+
+void XsdSchemaParser::parseSimpleRestriction(const XsdSimpleType::Ptr &ptr)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
+
+ validateElement(XsdTagScope::SimpleRestriction);
+
+ ptr->setDerivationMethod(XsdSimpleType::DerivationRestriction);
+
+ // The base attribute and simpleType member are mutually exclusive,
+ // so we keep track of that
+ bool hasBaseAttribute = false;
+ bool hasBaseTypeSpecified = false;
+
+ QXmlName baseName;
+ if (hasAttribute(QString::fromLatin1("base"))) {
+ const QString base = readQNameAttribute(QString::fromLatin1("base"), "restriction");
+ convertName(base, NamespaceSupport::ElementName, baseName); // translate qualified name into QXmlName
+ m_schemaResolver->addSimpleRestrictionBase(ptr, baseName, currentSourceLocation()); // add to resolver
+
+ hasBaseAttribute = true;
+ hasBaseTypeSpecified = true;
+ }
+ validateIdAttribute("restriction");
+
+ XsdFacet::Hash facets;
+ QList<XsdFacet::Ptr> patternFacets;
+ QList<XsdFacet::Ptr> enumerationFacets;
+ QList<XsdFacet::Ptr> assertionFacets;
+
+ TagValidationHandler tagValidator(XsdTagScope::SimpleRestriction, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ ptr->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ if (hasBaseAttribute) {
+ error(QtXmlPatterns::tr("%1 element is not allowed inside %2 element if %3 attribute is present")
+ .arg(formatElement("simpleType"))
+ .arg(formatElement("restriction"))
+ .arg(formatAttribute("base")));
+ return;
+ }
+
+ const XsdSimpleType::Ptr type = parseLocalSimpleType();
+ type->setContext(ptr);
+ ptr->setWxsSuperType(type);
+ ptr->setCategory(type->category());
+ hasBaseTypeSpecified = true;
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+ } else if (isSchemaTag(XsdSchemaToken::MinExclusive, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMinExclusiveFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::MinInclusive, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMinInclusiveFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::MaxExclusive, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMaxExclusiveFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::MaxInclusive, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMaxInclusiveFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::TotalDigits, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseTotalDigitsFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::FractionDigits, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseFractionDigitsFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::Length, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseLengthFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::MinLength, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMinLengthFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::MaxLength, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMaxLengthFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::Enumeration, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseEnumerationFacet();
+ enumerationFacets.append(facet);
+ } else if (isSchemaTag(XsdSchemaToken::WhiteSpace, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseWhiteSpaceFacet();
+ addFacet(facet, facets, ptr);
+ } else if (isSchemaTag(XsdSchemaToken::Pattern, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parsePatternFacet();
+ patternFacets.append(facet);
+ } else if (isSchemaTag(XsdSchemaToken::Assertion, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseAssertionFacet();
+ assertionFacets.append(facet);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ if (!hasBaseTypeSpecified) {
+ error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element")
+ .arg(formatElement("restriction"))
+ .arg(formatAttribute("base"))
+ .arg(formatElement("simpleType")));
+ return;
+ }
+
+ // merge all pattern facets into one multi value facet
+ if (!patternFacets.isEmpty()) {
+ const XsdFacet::Ptr patternFacet(new XsdFacet());
+ patternFacet->setType(XsdFacet::Pattern);
+
+ AtomicValue::List multiValue;
+ for (int i = 0; i < patternFacets.count(); ++i)
+ multiValue << patternFacets.at(i)->multiValue();
+
+ patternFacet->setMultiValue(multiValue);
+ addFacet(patternFacet, facets, ptr);
+ }
+
+ // merge all enumeration facets into one multi value facet
+ if (!enumerationFacets.isEmpty()) {
+ const XsdFacet::Ptr enumerationFacet(new XsdFacet());
+ enumerationFacet->setType(XsdFacet::Enumeration);
+
+ AtomicValue::List multiValue;
+ for (int i = 0; i < enumerationFacets.count(); ++i)
+ multiValue << enumerationFacets.at(i)->multiValue();
+
+ enumerationFacet->setMultiValue(multiValue);
+ addFacet(enumerationFacet, facets, ptr);
+ }
+
+ // merge all assertion facets into one facet
+ if (!assertionFacets.isEmpty()) {
+ const XsdFacet::Ptr assertionFacet(new XsdFacet());
+ assertionFacet->setType(XsdFacet::Assertion);
+
+ XsdAssertion::List assertions;
+ for (int i = 0; i < assertionFacets.count(); ++i)
+ assertions << assertionFacets.at(i)->assertions();
+
+ assertionFacet->setAssertions(assertions);
+ addFacet(assertionFacet, facets, ptr);
+ }
+
+ ptr->setFacets(facets);
+
+ tagValidator.finalize();
+}
+
+void XsdSchemaParser::parseList(const XsdSimpleType::Ptr &ptr)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::List, this);
+
+ validateElement(XsdTagScope::List);
+
+ ptr->setCategory(XsdSimpleType::SimpleTypeList);
+ ptr->setDerivationMethod(XsdSimpleType::DerivationList);
+ ptr->setWxsSuperType(BuiltinTypes::xsAnySimpleType);
+
+ // The itemType attribute and simpleType member are mutually exclusive,
+ // so we keep track of that
+ bool hasItemTypeAttribute = false;
+ bool hasItemTypeSpecified = false;
+
+ if (hasAttribute(QString::fromLatin1("itemType"))) {
+ const QString itemType = readQNameAttribute(QString::fromLatin1("itemType"), "list");
+ QXmlName typeName;
+ convertName(itemType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ m_schemaResolver->addSimpleListType(ptr, typeName, currentSourceLocation()); // add to resolver
+
+ hasItemTypeAttribute = true;
+ hasItemTypeSpecified = true;
+ }
+
+ validateIdAttribute("list");
+
+ TagValidationHandler tagValidator(XsdTagScope::List, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ ptr->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ if (hasItemTypeAttribute) {
+ error(QtXmlPatterns::tr("%1 element is not allowed inside %2 element if %3 attribute is present")
+ .arg(formatElement("simpleType"))
+ .arg(formatElement("list"))
+ .arg(formatAttribute("itemType")));
+ return;
+ }
+
+ const XsdSimpleType::Ptr type = parseLocalSimpleType();
+ type->setContext(ptr);
+ ptr->setItemType(type);
+
+ hasItemTypeSpecified = true;
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ if (!hasItemTypeSpecified) {
+ error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element")
+ .arg(formatElement("list"))
+ .arg(formatAttribute("itemType"))
+ .arg(formatElement("simpleType")));
+ return;
+ }
+
+ tagValidator.finalize();
+
+ // add the default white space facet that every simple type with list derivation has
+ const XsdFacet::Ptr defaultFacet(new XsdFacet());
+ defaultFacet->setType(XsdFacet::WhiteSpace);
+ defaultFacet->setFixed(true);
+ defaultFacet->setValue(DerivedString<TypeString>::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse)));
+ XsdFacet::Hash facets;
+ facets.insert(defaultFacet->type(), defaultFacet);
+ ptr->setFacets(facets);
+}
+
+void XsdSchemaParser::parseUnion(const XsdSimpleType::Ptr &ptr)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Union, this);
+
+ validateElement(XsdTagScope::Union);
+
+ ptr->setCategory(XsdSimpleType::SimpleTypeUnion);
+ ptr->setDerivationMethod(XsdSimpleType::DerivationUnion);
+ ptr->setWxsSuperType(BuiltinTypes::xsAnySimpleType);
+
+ // The memberTypes attribute is not allowed to be empty,
+ // so we keep track of that
+ bool hasMemberTypesAttribute = false;
+ bool hasMemberTypesSpecified = false;
+
+ if (hasAttribute(QString::fromLatin1("memberTypes"))) {
+ hasMemberTypesAttribute = true;
+
+ const QStringList memberTypes = readAttribute(QString::fromLatin1("memberTypes")).split(QLatin1Char(' '), QString::SkipEmptyParts);
+ QList<QXmlName> typeNames;
+
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ QXmlName typeName;
+ convertName(memberTypes.at(i), NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ typeNames.append(typeName);
+ }
+
+ if (!typeNames.isEmpty()) {
+ m_schemaResolver->addSimpleUnionTypes(ptr, typeNames, currentSourceLocation()); // add to resolver
+ hasMemberTypesSpecified = true;
+ }
+ }
+
+ validateIdAttribute("union");
+
+ AnySimpleType::List memberTypes;
+
+ TagValidationHandler tagValidator(XsdTagScope::Union, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ ptr->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ const XsdSimpleType::Ptr type = parseLocalSimpleType();
+ type->setContext(ptr);
+ memberTypes.append(type);
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ if (!memberTypes.isEmpty()) {
+ ptr->setMemberTypes(memberTypes);
+ hasMemberTypesSpecified = true;
+ }
+
+ if (!hasMemberTypesSpecified) {
+ error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element")
+ .arg(formatElement("union"))
+ .arg(formatAttribute("memberTypes"))
+ .arg(formatElement("simpleType")));
+ return;
+ }
+
+ tagValidator.finalize();
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseMinExclusiveFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinExclusive, this);
+
+ validateElement(XsdTagScope::MinExclusiveFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::MinimumExclusive);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "minExclusive", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ // as minExclusive can have a value of type anySimpleType, we just read
+ // the string here and store it for later intepretation
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
+ if (string->hasError()) {
+ attributeContentError("value", "minExclusive", value, BuiltinTypes::xsAnySimpleType);
+ return facet;
+ } else {
+ facet->setValue(string);
+ }
+
+ validateIdAttribute("minExclusive");
+
+ TagValidationHandler tagValidator(XsdTagScope::MinExclusiveFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseMinInclusiveFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinInclusive, this);
+
+ validateElement(XsdTagScope::MinInclusiveFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::MinimumInclusive);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "minInclusive", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ // as minInclusive can have a value of type anySimpleType, we just read
+ // the string here and store it for later intepretation
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
+ if (string->hasError()) {
+ attributeContentError("value", "minInclusive", value, BuiltinTypes::xsAnySimpleType);
+ return facet;
+ } else {
+ facet->setValue(string);
+ }
+
+ validateIdAttribute("minInclusive");
+
+ TagValidationHandler tagValidator(XsdTagScope::MinInclusiveFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseMaxExclusiveFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxExclusive, this);
+
+ validateElement(XsdTagScope::MaxExclusiveFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::MaximumExclusive);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "maxExclusive", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ // as maxExclusive can have a value of type anySimpleType, we just read
+ // the string here and store it for later intepretation
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
+ if (string->hasError()) {
+ attributeContentError("value", "maxExclusive", value, BuiltinTypes::xsAnySimpleType);
+ return facet;
+ } else {
+ facet->setValue(string);
+ }
+
+ validateIdAttribute("maxExclusive");
+
+ TagValidationHandler tagValidator(XsdTagScope::MaxExclusiveFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseMaxInclusiveFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxInclusive, this);
+
+ validateElement(XsdTagScope::MaxInclusiveFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::MaximumInclusive);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "maxInclusive", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ // as maxInclusive can have a value of type anySimpleType, we just read
+ // the string here and store it for later intepretation
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
+ if (string->hasError()) {
+ attributeContentError("value", "maxInclusive", value, BuiltinTypes::xsAnySimpleType);
+ return facet;
+ } else {
+ facet->setValue(string);
+ }
+
+ validateIdAttribute("maxInclusive");
+
+ TagValidationHandler tagValidator(XsdTagScope::MaxInclusiveFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseTotalDigitsFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::TotalDigits, this);
+
+ validateElement(XsdTagScope::TotalDigitsFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::TotalDigits);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "totalDigits", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedInteger<TypePositiveInteger>::Ptr integer = DerivedInteger<TypePositiveInteger>::fromLexical(m_namePool, value);
+ if (integer->hasError()) {
+ attributeContentError("value", "totalDigits", value, BuiltinTypes::xsPositiveInteger);
+ return facet;
+ } else {
+ facet->setValue(integer);
+ }
+
+ validateIdAttribute("totalDigits");
+
+ TagValidationHandler tagValidator(XsdTagScope::TotalDigitsFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseFractionDigitsFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::FractionDigits, this);
+
+ validateElement(XsdTagScope::FractionDigitsFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::FractionDigits);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "fractionDigits", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
+ if (integer->hasError()) {
+ attributeContentError("value", "fractionDigits", value, BuiltinTypes::xsNonNegativeInteger);
+ return facet;
+ } else {
+ facet->setValue(integer);
+ }
+
+ validateIdAttribute("fractionDigits");
+
+ TagValidationHandler tagValidator(XsdTagScope::FractionDigitsFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseLengthFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Length, this);
+
+ validateElement(XsdTagScope::LengthFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::Length);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "length", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
+ if (integer->hasError()) {
+ attributeContentError("value", "length", value, BuiltinTypes::xsNonNegativeInteger);
+ return facet;
+ } else {
+ facet->setValue(integer);
+ }
+
+ validateIdAttribute("length");
+
+ TagValidationHandler tagValidator(XsdTagScope::LengthFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseMinLengthFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinLength, this);
+
+ validateElement(XsdTagScope::MinLengthFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::MinimumLength);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "minLength", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
+ if (integer->hasError()) {
+ attributeContentError("value", "minLength", value, BuiltinTypes::xsNonNegativeInteger);
+ return facet;
+ } else {
+ facet->setValue(integer);
+ }
+
+ validateIdAttribute("minLength");
+
+ TagValidationHandler tagValidator(XsdTagScope::MinLengthFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseMaxLengthFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxLength, this);
+
+ validateElement(XsdTagScope::MaxLengthFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::MaximumLength);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "maxLength", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
+ if (integer->hasError()) {
+ attributeContentError("value", "maxLength", value, BuiltinTypes::xsNonNegativeInteger);
+ return facet;
+ } else {
+ facet->setValue(integer);
+ }
+
+ validateIdAttribute("maxLength");
+
+ TagValidationHandler tagValidator(XsdTagScope::MaxLengthFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseEnumerationFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Enumeration, this);
+
+ validateElement(XsdTagScope::EnumerationFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::Enumeration);
+
+ // parse attributes
+ facet->setFixed(false); // not defined in schema, but can't hurt
+
+ const QString value = readAttribute(QString::fromLatin1("value"));
+
+ // as enumeration can have a value of type anySimpleType, we just read
+ // the string here and store it for later intepretation
+ DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
+ if (string->hasError()) {
+ attributeContentError("value", "enumeration", value);
+ return facet;
+ } else {
+ AtomicValue::List multiValue;
+ multiValue << string;
+ facet->setMultiValue(multiValue);
+ }
+ m_schemaResolver->addEnumerationFacetValue(string, m_namespaceSupport);
+
+ validateIdAttribute("enumeration");
+
+ TagValidationHandler tagValidator(XsdTagScope::EnumerationFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseWhiteSpaceFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::WhiteSpace, this);
+
+ validateElement(XsdTagScope::WhiteSpaceFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::WhiteSpace);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ const Boolean::Ptr fixed = Boolean::fromLexical(value);
+ if (fixed->hasError()) {
+ attributeContentError("fixed", "whiteSpace", value, BuiltinTypes::xsBoolean);
+ return facet;
+ }
+
+ facet->setFixed(fixed->as<Boolean>()->value());
+ } else {
+ facet->setFixed(false); // the default value
+ }
+
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ if (value != XsdSchemaToken::toString(XsdSchemaToken::Collapse) &&
+ value != XsdSchemaToken::toString(XsdSchemaToken::Preserve) &&
+ value != XsdSchemaToken::toString(XsdSchemaToken::Replace)) {
+ attributeContentError("value", "whiteSpace", value);
+ return facet;
+ } else {
+ DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
+ if (string->hasError()) {
+ attributeContentError("value", "whiteSpace", value);
+ return facet;
+ } else {
+ facet->setValue(string);
+ }
+ }
+
+ validateIdAttribute("whiteSpace");
+
+ TagValidationHandler tagValidator(XsdTagScope::WhiteSpaceFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parsePatternFacet()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Pattern, this);
+
+ validateElement(XsdTagScope::PatternFacet);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::Pattern);
+
+ // parse attributes
+
+ // as pattern can have a value of type anySimpleType, we just read
+ // the string here and store it for later intepretation
+ const QString value = readAttribute(QString::fromLatin1("value"));
+ DerivedString<TypeString>::Ptr string = DerivedString<TypeString>::fromLexical(m_namePool, value);
+ if (string->hasError()) {
+ attributeContentError("value", "pattern", value);
+ return facet;
+ } else {
+ AtomicValue::List multiValue;
+ multiValue << string;
+ facet->setMultiValue(multiValue);
+ }
+
+ validateIdAttribute("pattern");
+
+ TagValidationHandler tagValidator(XsdTagScope::PatternFacet, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ facet->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return facet;
+}
+
+XsdFacet::Ptr XsdSchemaParser::parseAssertionFacet()
+{
+ // this is just a wrapper function around the parseAssertion() method
+
+ const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assertion, XsdTagScope::Assertion);
+
+ const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet());
+ facet->setType(XsdFacet::Assertion);
+ facet->setAssertions(XsdAssertion::List() << assertion);
+
+ return facet;
+}
+
+XsdComplexType::Ptr XsdSchemaParser::parseGlobalComplexType()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this);
+
+ validateElement(XsdTagScope::GlobalComplexType);
+
+ bool hasTypeSpecified = false;
+ bool hasComplexContent = false;
+
+ const XsdComplexType::Ptr complexType(new XsdComplexType());
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("abstract"))) {
+ const QString abstract = readAttribute(QString::fromLatin1("abstract"));
+
+ const Boolean::Ptr value = Boolean::fromLexical(abstract);
+ if (value->hasError()) {
+ attributeContentError("abstract", "complexType", abstract, BuiltinTypes::xsBoolean);
+ return complexType;
+ }
+
+ complexType->setIsAbstract(value->as<Boolean>()->value());
+ } else {
+ complexType->setIsAbstract(false); // default value
+ }
+
+ complexType->setProhibitedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint, "complexType"));
+ complexType->setDerivationConstraints(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "complexType"));
+
+ const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("complexType"));
+ complexType->setName(objectName);
+
+ bool effectiveMixed = false;
+ if (hasAttribute(QString::fromLatin1("mixed"))) {
+ const QString mixed = readAttribute(QString::fromLatin1("mixed"));
+
+ const Boolean::Ptr value = Boolean::fromLexical(mixed);
+ if (value->hasError()) {
+ attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean);
+ return complexType;
+ }
+
+ effectiveMixed = value->as<Boolean>()->value();
+ }
+
+ validateIdAttribute("complexType");
+
+ TagValidationHandler tagValidator(XsdTagScope::GlobalComplexType, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ complexType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleContent, token, namespaceToken)) {
+ if (effectiveMixed) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("complexType"))
+ .arg(formatElement("simpleContent"))
+ .arg(formatAttribute("mixed")));
+ return complexType;
+ }
+
+ parseSimpleContent(complexType);
+ hasTypeSpecified = true;
+ } else if (isSchemaTag(XsdSchemaToken::ComplexContent, token, namespaceToken)) {
+ bool mixed;
+ parseComplexContent(complexType, &mixed);
+ hasTypeSpecified = true;
+
+ effectiveMixed = (effectiveMixed || mixed);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
+ const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
+ complexType->contentType()->setOpenContent(openContent);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseReferredGroup(particle);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
+ complexType->addAttributeUse(attributeUse);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
+ complexType->addAttributeUse(attributeUse);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
+ const XsdWildcard::Ptr wildcard = parseAnyAttribute();
+ complexType->setAttributeWildcard(wildcard);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
+ const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
+ complexType->addAssertion(assertion);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ if (!hasTypeSpecified) {
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ }
+
+ if (hasComplexContent == true) {
+ resolveComplexContentType(complexType, effectiveMixed);
+ }
+
+ return complexType;
+}
+
+XsdComplexType::Ptr XsdSchemaParser::parseLocalComplexType()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this);
+
+ validateElement(XsdTagScope::LocalComplexType);
+
+ bool hasTypeSpecified = false;
+ bool hasComplexContent = true;
+
+ const XsdComplexType::Ptr complexType(new XsdComplexType());
+ complexType->setName(m_parserContext->createAnonymousName(m_targetNamespace));
+
+ // parse attributes
+ bool effectiveMixed = false;
+ if (hasAttribute(QString::fromLatin1("mixed"))) {
+ const QString mixed = readAttribute(QString::fromLatin1("mixed"));
+
+ const Boolean::Ptr value = Boolean::fromLexical(mixed);
+ if (value->hasError()) {
+ attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean);
+ return complexType;
+ }
+
+ effectiveMixed = value->as<Boolean>()->value();
+ }
+
+ validateIdAttribute("complexType");
+
+ TagValidationHandler tagValidator(XsdTagScope::LocalComplexType, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ complexType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleContent, token, namespaceToken)) {
+ parseSimpleContent(complexType);
+ hasTypeSpecified = true;
+ } else if (isSchemaTag(XsdSchemaToken::ComplexContent, token, namespaceToken)) {
+ bool mixed;
+ parseComplexContent(complexType, &mixed);
+ hasTypeSpecified = true;
+
+ effectiveMixed = (effectiveMixed || mixed);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
+ const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
+ complexType->contentType()->setOpenContent(openContent);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseReferredGroup(particle);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
+ complexType->addAttributeUse(attributeUse);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
+ complexType->addAttributeUse(attributeUse);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
+ const XsdWildcard::Ptr wildcard = parseAnyAttribute();
+ complexType->setAttributeWildcard(wildcard);
+
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
+ const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
+ complexType->addAssertion(assertion);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ if (!hasTypeSpecified) {
+ complexType->setWxsSuperType(BuiltinTypes::xsAnyType);
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ hasComplexContent = true;
+ }
+
+ if (hasComplexContent == true) {
+ resolveComplexContentType(complexType, effectiveMixed);
+ }
+
+ return complexType;
+}
+
+void XsdSchemaParser::resolveComplexContentType(const XsdComplexType::Ptr &complexType, bool effectiveMixed)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctcc.common
+
+ // 1
+ // the effectiveMixed contains the effective mixed value
+
+ // 2
+ bool hasEmptyContent = false;
+ if (!complexType->contentType()->particle()) {
+ hasEmptyContent = true; // 2.1.1
+ } else {
+ if (complexType->contentType()->particle()->term()->isModelGroup()) {
+ const XsdModelGroup::Ptr group = complexType->contentType()->particle()->term();
+ if (group->compositor() == XsdModelGroup::SequenceCompositor || group->compositor() == XsdModelGroup::AllCompositor) {
+ if (group->particles().isEmpty())
+ hasEmptyContent = true; // 2.1.2
+ } else if (group->compositor() == XsdModelGroup::ChoiceCompositor) {
+ if ((complexType->contentType()->particle()->minimumOccurs() == 0) && group->particles().isEmpty())
+ hasEmptyContent = true; // 2.1.3
+ }
+
+ if ((complexType->contentType()->particle()->maximumOccursUnbounded() == false) && (complexType->contentType()->particle()->maximumOccurs() == 0))
+ hasEmptyContent = true; // 2.1.4
+ }
+ }
+
+ const XsdParticle::Ptr explicitContent = (hasEmptyContent ? XsdParticle::Ptr() : complexType->contentType()->particle());
+
+ // do all the other work (3, 4, 5 and 6) in the resolver, as they need access to the base type object
+ m_schemaResolver->addComplexContentType(complexType, explicitContent, effectiveMixed);
+}
+
+void XsdSchemaParser::parseSimpleContent(const XsdComplexType::Ptr &complexType)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleContent, this);
+
+ validateElement(XsdTagScope::SimpleContent);
+
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::Simple);
+
+ // parse attributes
+ validateIdAttribute("simpleContent");
+
+ TagValidationHandler tagValidator(XsdTagScope::SimpleContent, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ complexType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
+ parseSimpleContentRestriction(complexType);
+ } else if (isSchemaTag(XsdSchemaToken::Extension, token, namespaceToken)) {
+ parseSimpleContentExtension(complexType);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+}
+
+void XsdSchemaParser::parseSimpleContentRestriction(const XsdComplexType::Ptr &complexType)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
+
+ validateElement(XsdTagScope::SimpleContentRestriction);
+
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+
+ // parse attributes
+ const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "restriction");
+ QXmlName typeName;
+ convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+
+ validateIdAttribute("restriction");
+
+ XsdFacet::Hash facets;
+ QList<XsdFacet::Ptr> patternFacets;
+ QList<XsdFacet::Ptr> enumerationFacets;
+ QList<XsdFacet::Ptr> assertionFacets;
+
+ TagValidationHandler tagValidator(XsdTagScope::SimpleContentRestriction, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ complexType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ const XsdSimpleType::Ptr type = parseLocalSimpleType();
+ type->setContext(complexType); //TODO: investigate what the schema spec really wants here?!?
+ complexType->contentType()->setSimpleType(type);
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+ } else if (isSchemaTag(XsdSchemaToken::MinExclusive, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMinExclusiveFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::MinInclusive, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMinInclusiveFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::MaxExclusive, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMaxExclusiveFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::MaxInclusive, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMaxInclusiveFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::TotalDigits, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseTotalDigitsFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::FractionDigits, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseFractionDigitsFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::Length, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseLengthFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::MinLength, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMinLengthFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::MaxLength, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseMaxLengthFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::Enumeration, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseEnumerationFacet();
+ enumerationFacets.append(facet);
+ } else if (isSchemaTag(XsdSchemaToken::WhiteSpace, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseWhiteSpaceFacet();
+ addFacet(facet, facets, complexType);
+ } else if (isSchemaTag(XsdSchemaToken::Pattern, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parsePatternFacet();
+ patternFacets.append(facet);
+ } else if (isSchemaTag(XsdSchemaToken::Assertion, token, namespaceToken)) {
+ const XsdFacet::Ptr facet = parseAssertionFacet();
+ assertionFacets.append(facet);
+ } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
+ complexType->addAttributeUse(attributeUse);
+ } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
+ complexType->addAttributeUse(attributeUse);
+ } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
+ const XsdWildcard::Ptr wildcard = parseAnyAttribute();
+ complexType->setAttributeWildcard(wildcard);
+ } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
+ const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
+ complexType->addAssertion(assertion);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ // merge all pattern facets into one multi value facet
+ if (!patternFacets.isEmpty()) {
+ const XsdFacet::Ptr patternFacet(new XsdFacet());
+ patternFacet->setType(XsdFacet::Pattern);
+
+ AtomicValue::List multiValue;
+ for (int i = 0; i < patternFacets.count(); ++i)
+ multiValue << patternFacets.at(i)->multiValue();
+
+ patternFacet->setMultiValue(multiValue);
+ addFacet(patternFacet, facets, complexType);
+ }
+
+ // merge all enumeration facets into one multi value facet
+ if (!enumerationFacets.isEmpty()) {
+ const XsdFacet::Ptr enumerationFacet(new XsdFacet());
+ enumerationFacet->setType(XsdFacet::Enumeration);
+
+ AtomicValue::List multiValue;
+ for (int i = 0; i < enumerationFacets.count(); ++i)
+ multiValue << enumerationFacets.at(i)->multiValue();
+
+ enumerationFacet->setMultiValue(multiValue);
+ addFacet(enumerationFacet, facets, complexType);
+ }
+
+ // merge all assertion facets into one facet
+ if (!assertionFacets.isEmpty()) {
+ const XsdFacet::Ptr assertionFacet(new XsdFacet());
+ assertionFacet->setType(XsdFacet::Assertion);
+
+ XsdAssertion::List assertions;
+ for (int i = 0; i < assertionFacets.count(); ++i)
+ assertions << assertionFacets.at(i)->assertions();
+
+ assertionFacet->setAssertions(assertions);
+ addFacet(assertionFacet, facets, complexType);
+ }
+
+ m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation(), facets); // add to resolver
+}
+
+void XsdSchemaParser::parseSimpleContentExtension(const XsdComplexType::Ptr &complexType)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this);
+
+ validateElement(XsdTagScope::SimpleContentExtension);
+
+ complexType->setDerivationMethod(XsdComplexType::DerivationExtension);
+
+ // parse attributes
+ const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "extension");
+ QXmlName typeName;
+ convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver
+
+ validateIdAttribute("extension");
+
+ TagValidationHandler tagValidator(XsdTagScope::SimpleContentExtension, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ complexType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
+ complexType->addAttributeUse(attributeUse);
+ } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
+ complexType->addAttributeUse(attributeUse);
+ } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
+ const XsdWildcard::Ptr wildcard = parseAnyAttribute();
+ complexType->setAttributeWildcard(wildcard);
+ } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
+ const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
+ complexType->addAssertion(assertion);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+}
+
+void XsdSchemaParser::parseComplexContent(const XsdComplexType::Ptr &complexType, bool *mixed)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexContent, this);
+
+ validateElement(XsdTagScope::ComplexContent);
+
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly);
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("mixed"))) {
+ const QString mixedStr = readAttribute(QString::fromLatin1("mixed"));
+
+ const Boolean::Ptr value = Boolean::fromLexical(mixedStr);
+ if (value->hasError()) {
+ attributeContentError("mixed", "complexType", mixedStr, BuiltinTypes::xsBoolean);
+ return;
+ }
+
+ *mixed = value->as<Boolean>()->value();
+ } else {
+ *mixed = false;
+ }
+
+ validateIdAttribute("complexContent");
+
+ TagValidationHandler tagValidator(XsdTagScope::ComplexContent, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ complexType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) {
+ parseComplexContentRestriction(complexType);
+ } else if (isSchemaTag(XsdSchemaToken::Extension, token, namespaceToken)) {
+ parseComplexContentExtension(complexType);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+}
+
+void XsdSchemaParser::parseComplexContentRestriction(const XsdComplexType::Ptr &complexType)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this);
+
+ validateElement(XsdTagScope::ComplexContentRestriction);
+
+ complexType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+
+ // parse attributes
+ const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "restriction");
+ QXmlName typeName;
+ convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver
+
+ validateIdAttribute("restriction");
+
+ TagValidationHandler tagValidator(XsdTagScope::ComplexContentRestriction, this, m_namePool);
+
+ bool hasContent = false;
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ complexType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
+ const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
+ complexType->contentType()->setOpenContent(openContent);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseReferredGroup(particle);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
+ complexType->addAttributeUse(attributeUse);
+ } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
+ complexType->addAttributeUse(attributeUse);
+ } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
+ const XsdWildcard::Ptr wildcard = parseAnyAttribute();
+ complexType->setAttributeWildcard(wildcard);
+ } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
+ const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
+ complexType->addAssertion(assertion);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ if (!hasContent)
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty);
+
+ tagValidator.finalize();
+}
+
+void XsdSchemaParser::parseComplexContentExtension(const XsdComplexType::Ptr &complexType)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this);
+
+ validateElement(XsdTagScope::ComplexContentExtension);
+
+ complexType->setDerivationMethod(XsdComplexType::DerivationExtension);
+
+ // parse attributes
+ const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "extension");
+ QXmlName typeName;
+ convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver
+
+ validateIdAttribute("extension");
+
+ TagValidationHandler tagValidator(XsdTagScope::ComplexContentExtension, this, m_namePool);
+
+ bool hasContent = false;
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ complexType->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) {
+ const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent();
+ complexType->contentType()->setOpenContent(openContent);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseReferredGroup(particle);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalAll(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalChoice(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalSequence(particle, complexType);
+ particle->setTerm(term);
+ complexType->contentType()->setParticle(particle);
+ hasContent = true;
+ } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType);
+ complexType->addAttributeUse(attributeUse);
+ } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
+ complexType->addAttributeUse(attributeUse);
+ } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
+ const XsdWildcard::Ptr wildcard = parseAnyAttribute();
+ complexType->setAttributeWildcard(wildcard);
+ } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) {
+ const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert);
+ complexType->addAssertion(assertion);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ if (!hasContent)
+ complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty);
+
+ tagValidator.finalize();
+}
+
+
+XsdAssertion::Ptr XsdSchemaParser::parseAssertion(const XsdSchemaToken::NodeName &nodeName, const XsdTagScope::Type &tag)
+{
+ const ElementNamespaceHandler namespaceHandler(nodeName, this);
+
+ validateElement(tag);
+
+ const XsdAssertion::Ptr assertion(new XsdAssertion());
+
+ // parse attributes
+
+ const XsdXPathExpression::Ptr expression = readXPathExpression("assertion");
+ assertion->setTest(expression);
+
+ const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "assertion");
+ expression->setExpression(test);
+
+ validateIdAttribute("assertion");
+
+ TagValidationHandler tagValidator(tag, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ assertion->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return assertion;
+}
+
+XsdComplexType::OpenContent::Ptr XsdSchemaParser::parseOpenContent()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::OpenContent, this);
+
+ validateElement(XsdTagScope::OpenContent);
+
+ const XsdComplexType::OpenContent::Ptr openContent(new XsdComplexType::OpenContent());
+
+ if (hasAttribute(QString::fromLatin1("mode"))) {
+ const QString mode = readAttribute(QString::fromLatin1("mode"));
+
+ if (mode == QString::fromLatin1("none")) {
+ m_defaultOpenContent->setMode(XsdComplexType::OpenContent::None);
+ } else if (mode == QString::fromLatin1("interleave")) {
+ m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave);
+ } else if (mode == QString::fromLatin1("suffix")) {
+ m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Suffix);
+ } else {
+ attributeContentError("mode", "openContent", mode);
+ return openContent;
+ }
+ } else {
+ openContent->setMode(XsdComplexType::OpenContent::Interleave);
+ }
+
+ validateIdAttribute("openContent");
+
+ TagValidationHandler tagValidator(XsdTagScope::OpenContent, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ openContent->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
+ const XsdParticle::Ptr particle;
+ const XsdWildcard::Ptr wildcard = parseAny(particle);
+ openContent->setWildcard(wildcard);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return openContent;
+}
+
+XsdModelGroup::Ptr XsdSchemaParser::parseNamedGroup()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this);
+
+ validateElement(XsdTagScope::NamedGroup);
+
+ const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
+ XsdModelGroup::Ptr group;
+
+ QXmlName objectName;
+ if (hasAttribute(QString::fromLatin1("name"))) {
+ objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("group"));
+ }
+
+ validateIdAttribute("group");
+
+ TagValidationHandler tagValidator(XsdTagScope::NamedGroup, this, m_namePool);
+
+ XsdAnnotation::Ptr annotation;
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ annotation = parseAnnotation();
+ } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) {
+ group = parseAll(modelGroup);
+ } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
+ group = parseChoice(modelGroup);
+ } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
+ group = parseSequence(modelGroup);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ group->setName(objectName);
+
+ if (annotation)
+ group->addAnnotation(annotation);
+
+ return group;
+}
+
+XsdTerm::Ptr XsdSchemaParser::parseReferredGroup(const XsdParticle::Ptr &particle)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this);
+
+ validateElement(XsdTagScope::ReferredGroup);
+
+ const XsdReference::Ptr reference(new XsdReference());
+ reference->setType(XsdReference::ModelGroup);
+ reference->setSourceLocation(currentSourceLocation());
+
+ // parse attributes
+ if (!parseMinMaxConstraint(particle, "group")) {
+ return reference;
+ }
+
+ const QString value = readQNameAttribute(QString::fromLatin1("ref"), "group");
+ QXmlName referenceName;
+ convertName(value, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
+ reference->setReferenceName(referenceName);
+
+ validateIdAttribute("group");
+
+ TagValidationHandler tagValidator(XsdTagScope::ReferredGroup, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ reference->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return reference;
+}
+
+XsdModelGroup::Ptr XsdSchemaParser::parseAll(const NamedSchemaComponent::Ptr &parent)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this);
+
+ validateElement(XsdTagScope::All);
+
+ const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
+ modelGroup->setCompositor(XsdModelGroup::AllCompositor);
+
+ validateIdAttribute("all");
+
+ TagValidationHandler tagValidator(XsdTagScope::All, this, m_namePool);
+
+ XsdParticle::List particles;
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ modelGroup->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalElement(particle, parent);
+ particle->setTerm(term);
+
+ if (particle->maximumOccursUnbounded() || particle->maximumOccurs() > 1) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must be %3 or %4")
+ .arg(formatAttribute("maxOccurs"))
+ .arg(formatElement("all"))
+ .arg(formatData("0"))
+ .arg(formatData("1")));
+ return modelGroup;
+ }
+
+ particles.append(particle);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ modelGroup->setParticles(particles);
+
+ tagValidator.finalize();
+
+ return modelGroup;
+}
+
+XsdModelGroup::Ptr XsdSchemaParser::parseLocalAll(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this);
+
+ validateElement(XsdTagScope::LocalAll);
+
+ const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
+ modelGroup->setCompositor(XsdModelGroup::AllCompositor);
+
+ // parse attributes
+ if (!parseMinMaxConstraint(particle, "all")) {
+ return modelGroup;
+ }
+ if (particle->maximumOccursUnbounded() || particle->maximumOccurs() != 1) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3")
+ .arg(formatAttribute("maxOccurs"))
+ .arg(formatElement("all"))
+ .arg(formatData("1")));
+ return modelGroup;
+ }
+ if (particle->minimumOccurs() != 0 && particle->minimumOccurs() != 1) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4")
+ .arg(formatAttribute("minOccurs"))
+ .arg(formatElement("all"))
+ .arg(formatData("0"))
+ .arg(formatData("1")));
+ return modelGroup;
+ }
+
+ validateIdAttribute("all");
+
+ TagValidationHandler tagValidator(XsdTagScope::LocalAll, this, m_namePool);
+
+ XsdParticle::List particles;
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ modelGroup->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalElement(particle, parent);
+ particle->setTerm(term);
+
+ if (particle->maximumOccursUnbounded() || particle->maximumOccurs() > 1) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4")
+ .arg(formatAttribute("maxOccurs"))
+ .arg(formatElement("all"))
+ .arg(formatData("0"))
+ .arg(formatData("1")));
+ return modelGroup;
+ }
+
+ particles.append(particle);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ modelGroup->setParticles(particles);
+
+ tagValidator.finalize();
+
+ return modelGroup;
+}
+
+XsdModelGroup::Ptr XsdSchemaParser::parseChoice(const NamedSchemaComponent::Ptr &parent)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this);
+
+ validateElement(XsdTagScope::Choice);
+
+ const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
+ modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor);
+
+ validateIdAttribute("choice");
+
+ XsdParticle::List particles;
+
+ TagValidationHandler tagValidator(XsdTagScope::Choice, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ modelGroup->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalElement(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseReferredGroup(particle);
+ m_schemaResolver->addAllGroupCheck(term);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseAny(particle);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ modelGroup->setParticles(particles);
+
+ tagValidator.finalize();
+
+ return modelGroup;
+}
+
+XsdModelGroup::Ptr XsdSchemaParser::parseLocalChoice(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this);
+
+ validateElement(XsdTagScope::LocalChoice);
+
+ const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
+ modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor);
+
+ // parse attributes
+ if (!parseMinMaxConstraint(particle, "choice")) {
+ return modelGroup;
+ }
+
+ validateIdAttribute("choice");
+
+ XsdParticle::List particles;
+
+ TagValidationHandler tagValidator(XsdTagScope::LocalChoice, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ modelGroup->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalElement(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseReferredGroup(particle);
+ m_schemaResolver->addAllGroupCheck(term);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseAny(particle);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ modelGroup->setParticles(particles);
+
+ tagValidator.finalize();
+
+ return modelGroup;
+}
+
+XsdModelGroup::Ptr XsdSchemaParser::parseSequence(const NamedSchemaComponent::Ptr &parent)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this);
+
+ validateElement(XsdTagScope::Sequence);
+
+ const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
+ modelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
+
+ validateIdAttribute("sequence");
+
+ XsdParticle::List particles;
+
+ TagValidationHandler tagValidator(XsdTagScope::Sequence, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ modelGroup->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalElement(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseReferredGroup(particle);
+ m_schemaResolver->addAllGroupCheck(term);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseAny(particle);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ modelGroup->setParticles(particles);
+
+ tagValidator.finalize();
+
+ return modelGroup;
+}
+
+XsdModelGroup::Ptr XsdSchemaParser::parseLocalSequence(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this);
+
+ validateElement(XsdTagScope::LocalSequence);
+
+ const XsdModelGroup::Ptr modelGroup(new XsdModelGroup());
+ modelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
+
+ // parse attributes
+ if (!parseMinMaxConstraint(particle, "sequence")) {
+ return modelGroup;
+ }
+
+ validateIdAttribute("sequence");
+
+ XsdParticle::List particles;
+
+ TagValidationHandler tagValidator(XsdTagScope::LocalSequence, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ modelGroup->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalElement(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseReferredGroup(particle);
+ m_schemaResolver->addAllGroupCheck(term);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalChoice(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseLocalSequence(particle, parent);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ const XsdTerm::Ptr term = parseAny(particle);
+ particle->setTerm(term);
+ particles.append(particle);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ modelGroup->setParticles(particles);
+
+ tagValidator.finalize();
+
+ return modelGroup;
+}
+
+XsdAttribute::Ptr XsdSchemaParser::parseGlobalAttribute()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this);
+
+ validateElement(XsdTagScope::GlobalAttribute);
+
+ const XsdAttribute::Ptr attribute(new XsdAttribute());
+ attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
+ attribute->scope()->setVariety(XsdAttribute::Scope::Global);
+
+ if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("attribute"))
+ .arg(formatAttribute("default"))
+ .arg(formatAttribute("fixed")));
+ return attribute;
+ }
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("default"))) {
+ const QString value = readAttribute(QString::fromLatin1("default"));
+ attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
+ attribute->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Default);
+ attribute->valueConstraint()->setValue(value);
+ } else if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
+ attribute->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Fixed);
+ attribute->valueConstraint()->setValue(value);
+ }
+
+ const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("attribute"));
+ if ((objectName.namespaceURI() == StandardNamespaces::xsi) &&
+ (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("type")) &&
+ (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("nil")) &&
+ (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("schemaLocation")) &&
+ (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) {
+
+ error(QtXmlPatterns::tr("content of %1 attribute of %2 element must not be from namespace %3")
+ .arg(formatAttribute("name"))
+ .arg(formatElement("attribute"))
+ .arg(formatURI(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"))));
+ return attribute;
+ }
+ if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3")
+ .arg(formatAttribute("name"))
+ .arg(formatElement("attribute"))
+ .arg(formatData("xmlns")));
+ return attribute;
+ }
+ attribute->setName(objectName);
+
+ bool hasTypeAttribute = false;
+ bool hasTypeSpecified = false;
+
+ if (hasAttribute(QString::fromLatin1("type"))) {
+ hasTypeAttribute = true;
+
+ const QString type = readQNameAttribute(QString::fromLatin1("type"), "attribute");
+ QXmlName typeName;
+ convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ m_schemaResolver->addAttributeType(attribute, typeName, currentSourceLocation()); // add to resolver
+ hasTypeSpecified = true;
+ }
+
+ validateIdAttribute("attribute");
+
+ TagValidationHandler tagValidator(XsdTagScope::GlobalAttribute, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ attribute->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ if (hasTypeAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("attribute"))
+ .arg(formatElement("simpleType"))
+ .arg(formatAttribute("type")));
+ break;
+ }
+
+ const XsdSimpleType::Ptr type = parseLocalSimpleType();
+ type->setContext(attribute);
+ attribute->setType(type);
+ hasTypeSpecified = true;
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ if (!hasTypeSpecified) {
+ attribute->setType(BuiltinTypes::xsAnySimpleType); // default value
+ return attribute;
+ }
+
+ tagValidator.finalize();
+
+ return attribute;
+}
+
+XsdAttributeUse::Ptr XsdSchemaParser::parseLocalAttribute(const NamedSchemaComponent::Ptr &parent)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this);
+
+ validateElement(XsdTagScope::LocalAttribute);
+
+ bool hasRefAttribute = false;
+ bool hasTypeAttribute = false;
+ bool hasTypeSpecified = false;
+
+ XsdAttributeUse::Ptr attributeUse;
+ if (hasAttribute(QString::fromLatin1("ref"))) {
+ const XsdAttributeReference::Ptr reference = XsdAttributeReference::Ptr(new XsdAttributeReference());
+ reference->setType(XsdAttributeReference::AttributeUse);
+ reference->setSourceLocation(currentSourceLocation());
+
+ attributeUse = reference;
+ hasRefAttribute = true;
+ } else {
+ attributeUse = XsdAttributeUse::Ptr(new XsdAttributeUse());
+ }
+
+ if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("attribute"))
+ .arg(formatAttribute("default"))
+ .arg(formatAttribute("fixed")));
+ return attributeUse;
+ }
+
+ if (hasRefAttribute) {
+ if (hasAttribute(QString::fromLatin1("form"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("attribute"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("form")));
+ return attributeUse;
+ }
+ if (hasAttribute(QString::fromLatin1("name"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("attribute"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("name")));
+ return attributeUse;
+ }
+ if (hasAttribute(QString::fromLatin1("type"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("attribute"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("type")));
+ return attributeUse;
+ }
+ }
+
+ // parse attributes
+
+ // default, fixed and use are handled by both, attribute use and attribute reference
+ if (hasAttribute(QString::fromLatin1("default"))) {
+ const QString value = readAttribute(QString::fromLatin1("default"));
+ attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint()));
+ attributeUse->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Default);
+ attributeUse->valueConstraint()->setValue(value);
+ } else if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint()));
+ attributeUse->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Fixed);
+ attributeUse->valueConstraint()->setValue(value);
+ }
+
+ if (hasAttribute(QString::fromLatin1("use"))) {
+ const QString value = readAttribute(QString::fromLatin1("use"));
+ if (value != QString::fromLatin1("optional") &&
+ value != QString::fromLatin1("prohibited") &&
+ value != QString::fromLatin1("required")) {
+ attributeContentError("use", "attribute", value);
+ return attributeUse;
+ }
+
+ if (value == QString::fromLatin1("optional"))
+ attributeUse->setUseType(XsdAttributeUse::OptionalUse);
+ else if (value == QString::fromLatin1("prohibited"))
+ attributeUse->setUseType(XsdAttributeUse::ProhibitedUse);
+ else if (value == QString::fromLatin1("required"))
+ attributeUse->setUseType(XsdAttributeUse::RequiredUse);
+
+ if (attributeUse->valueConstraint() && attributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Default && value != QString::fromLatin1("optional")) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must have the value %3 because the %4 attribute is set")
+ .arg(formatAttribute("use"))
+ .arg(formatElement("attribute"))
+ .arg(formatData("optional"))
+ .arg(formatElement("default")));
+ return attributeUse;
+ }
+ }
+
+ const XsdAttribute::Ptr attribute(new XsdAttribute());
+
+ attributeUse->setAttribute(attribute);
+ m_componentLocationHash.insert(attribute, currentSourceLocation());
+
+ attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope()));
+ attribute->scope()->setVariety(XsdAttribute::Scope::Local);
+ attribute->scope()->setParent(parent);
+
+ // now make a difference between attribute reference and attribute use
+ if (hasRefAttribute) {
+ const QString reference = readQNameAttribute(QString::fromLatin1("ref"), "attribute");
+ QXmlName referenceName;
+ convertName(reference, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
+
+ const XsdAttributeReference::Ptr attributeReference = attributeUse;
+ attributeReference->setReferenceName(referenceName);
+ } else {
+ if (hasAttribute(QString::fromLatin1("name"))) {
+ const QString attributeName = readNameAttribute("attribute");
+
+ QXmlName objectName;
+ if (hasAttribute(QString::fromLatin1("form"))) {
+ const QString value = readAttribute(QString::fromLatin1("form"));
+ if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
+ attributeContentError("form", "attribute", value);
+ return attributeUse;
+ }
+
+ if (value == QString::fromLatin1("qualified")) {
+ objectName = m_namePool->allocateQName(m_targetNamespace, attributeName);
+ } else {
+ objectName = m_namePool->allocateQName(QString(), attributeName);
+ }
+ } else {
+ if (m_attributeFormDefault == QString::fromLatin1("qualified")) {
+ objectName = m_namePool->allocateQName(m_targetNamespace, attributeName);
+ } else {
+ objectName = m_namePool->allocateQName(QString(), attributeName);
+ }
+ }
+
+ if ((objectName.namespaceURI() == StandardNamespaces::xsi) &&
+ (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("type")) &&
+ (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("nil")) &&
+ (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("schemaLocation")) &&
+ (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) {
+
+ error(QtXmlPatterns::tr("content of %1 attribute of %2 element must not be from namespace %3")
+ .arg(formatAttribute("name"))
+ .arg(formatElement("attribute"))
+ .arg(formatURI(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"))));
+ return attributeUse;
+ }
+ if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3")
+ .arg(formatAttribute("name"))
+ .arg(formatElement("attribute"))
+ .arg(formatData("xmlns")));
+ return attributeUse;
+ }
+
+ attribute->setName(objectName);
+ }
+
+ if (hasAttribute(QString::fromLatin1("type"))) {
+ hasTypeAttribute = true;
+
+ const QString type = readQNameAttribute(QString::fromLatin1("type"), "attribute");
+ QXmlName typeName;
+ convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ m_schemaResolver->addAttributeType(attribute, typeName, currentSourceLocation()); // add to resolver
+ hasTypeSpecified = true;
+ }
+
+ if (attributeUse->valueConstraint()) {
+ //TODO: check whether assigning the value constraint of the attribute use to the attribute is correct
+ if (!attribute->valueConstraint())
+ attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint()));
+
+ attribute->valueConstraint()->setVariety((XsdAttribute::ValueConstraint::Variety)attributeUse->valueConstraint()->variety());
+ attribute->valueConstraint()->setValue(attributeUse->valueConstraint()->value());
+ attribute->valueConstraint()->setLexicalForm(attributeUse->valueConstraint()->lexicalForm());
+ }
+ }
+
+ validateIdAttribute("attribute");
+
+ TagValidationHandler tagValidator(XsdTagScope::LocalAttribute, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ attribute->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ if (hasTypeAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("attribute"))
+ .arg(formatElement("simpleType"))
+ .arg(formatAttribute("type")));
+ break;
+ }
+ if (hasRefAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("attribute"))
+ .arg(formatElement("simpleType"))
+ .arg(formatAttribute("ref")));
+ break;
+ }
+
+ const XsdSimpleType::Ptr type = parseLocalSimpleType();
+ type->setContext(attribute);
+ attribute->setType(type);
+ hasTypeSpecified = true;
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ if (!hasTypeSpecified) {
+ attribute->setType(BuiltinTypes::xsAnySimpleType); // default value
+ }
+
+ tagValidator.finalize();
+
+ return attributeUse;
+}
+
+XsdAttributeGroup::Ptr XsdSchemaParser::parseNamedAttributeGroup()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this);
+
+ validateElement(XsdTagScope::NamedAttributeGroup);
+
+ const XsdAttributeGroup::Ptr attributeGroup(new XsdAttributeGroup());
+
+ // parse attributes
+ const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("attributeGroup"));
+ attributeGroup->setName(objectName);
+
+ validateIdAttribute("attributeGroup");
+
+ TagValidationHandler tagValidator(XsdTagScope::NamedAttributeGroup, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ attributeGroup->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(attributeGroup);
+
+ if (attributeUse->useType() == XsdAttributeUse::ProhibitedUse) {
+ warning(QtXmlPatterns::tr("specifying use='prohibited' inside an attribute group has no effect"));
+ } else {
+ attributeGroup->addAttributeUse(attributeUse);
+ }
+ } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) {
+ const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup();
+ attributeGroup->addAttributeUse(attributeUse);
+ } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) {
+ const XsdWildcard::Ptr wildcard = parseAnyAttribute();
+ attributeGroup->setWildcard(wildcard);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return attributeGroup;
+}
+
+XsdAttributeUse::Ptr XsdSchemaParser::parseReferredAttributeGroup()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this);
+
+ validateElement(XsdTagScope::ReferredAttributeGroup);
+
+ const XsdAttributeReference::Ptr attributeReference(new XsdAttributeReference());
+ attributeReference->setType(XsdAttributeReference::AttributeGroup);
+ attributeReference->setSourceLocation(currentSourceLocation());
+
+ // parse attributes
+ const QString reference = readQNameAttribute(QString::fromLatin1("ref"), "attributeGroup");
+ QXmlName referenceName;
+ convertName(reference, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
+ attributeReference->setReferenceName(referenceName);
+
+ validateIdAttribute("attributeGroup");
+
+ TagValidationHandler tagValidator(XsdTagScope::ReferredAttributeGroup, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ attributeReference->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return attributeReference;
+}
+
+XsdElement::Ptr XsdSchemaParser::parseGlobalElement()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this);
+
+ validateElement(XsdTagScope::GlobalElement);
+
+ const XsdElement::Ptr element(new XsdElement());
+ element->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope()));
+ element->scope()->setVariety(XsdElement::Scope::Global);
+
+ bool hasTypeAttribute = false;
+ bool hasTypeSpecified = false;
+ bool hasSubstitutionGroup = false;
+
+ // parse attributes
+ const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("element"));
+ element->setName(objectName);
+
+ if (hasAttribute(QString::fromLatin1("abstract"))) {
+ const QString abstract = readAttribute(QString::fromLatin1("abstract"));
+
+ const Boolean::Ptr value = Boolean::fromLexical(abstract);
+ if (value->hasError()) {
+ attributeContentError("abstract", "element", abstract, BuiltinTypes::xsBoolean);
+ return element;
+ }
+
+ element->setIsAbstract(value->as<Boolean>()->value());
+ } else {
+ element->setIsAbstract(false); // the default value
+ }
+
+ if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("default"))
+ .arg(formatAttribute("fixed")));
+ return element;
+ }
+
+ if (hasAttribute(QString::fromLatin1("default"))) {
+ const QString value = readAttribute(QString::fromLatin1("default"));
+ element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
+ element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default);
+ element->valueConstraint()->setValue(value);
+ } else if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
+ element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed);
+ element->valueConstraint()->setValue(value);
+ }
+
+ element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element"));
+ element->setSubstitutionGroupExclusions(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "element"));
+
+ if (hasAttribute(QString::fromLatin1("nillable"))) {
+ const QString nillable = readAttribute(QString::fromLatin1("nillable"));
+
+ const Boolean::Ptr value = Boolean::fromLexical(nillable);
+ if (value->hasError()) {
+ attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean);
+ return element;
+ }
+
+ element->setIsNillable(value->as<Boolean>()->value());
+ } else {
+ element->setIsNillable(false); // the default value
+ }
+
+ if (hasAttribute(QString::fromLatin1("type"))) {
+ const QString type = readQNameAttribute(QString::fromLatin1("type"), "element");
+ QXmlName typeName;
+ convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ m_schemaResolver->addElementType(element, typeName, currentSourceLocation()); // add to resolver
+
+ hasTypeAttribute = true;
+ hasTypeSpecified = true;
+ }
+
+ if (hasAttribute(QString::fromLatin1("substitutionGroup"))) {
+ QList<QXmlName> elementNames;
+
+ const QString value = readAttribute(QString::fromLatin1("substitutionGroup"));
+ const QStringList substitutionGroups = value.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ if (substitutionGroups.isEmpty()) {
+ attributeContentError("substitutionGroup", "element", value, BuiltinTypes::xsQName);
+ return element;
+ }
+
+ for (int i = 0; i < substitutionGroups.count(); ++i) {
+ const QString value = substitutionGroups.at(i).simplified();
+ if (!XPathHelper::isQName(value)) {
+ attributeContentError("substitutionGroup", "element", value, BuiltinTypes::xsQName);
+ return element;
+ }
+
+ QXmlName elementName;
+ convertName(value, NamespaceSupport::ElementName, elementName); // translate qualified name into QXmlName
+ elementNames.append(elementName);
+ }
+
+ m_schemaResolver->addSubstitutionGroupAffiliation(element, elementNames, currentSourceLocation()); // add to resolver
+
+ hasSubstitutionGroup = true;
+ }
+
+ validateIdAttribute("element");
+
+ XsdAlternative::List alternatives;
+
+ TagValidationHandler tagValidator(XsdTagScope::GlobalElement, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ element->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ if (hasTypeAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("simpleType"))
+ .arg(formatAttribute("type")));
+ return element;
+ }
+
+ const XsdSimpleType::Ptr type = parseLocalSimpleType();
+ type->setContext(element);
+ element->setType(type);
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+
+ hasTypeSpecified = true;
+ } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
+ if (hasTypeAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("complexType"))
+ .arg(formatAttribute("type")));
+ return element;
+ }
+
+ const XsdComplexType::Ptr type = parseLocalComplexType();
+ type->setContext(element);
+ element->setType(type);
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+
+ hasTypeSpecified = true;
+ } else if (isSchemaTag(XsdSchemaToken::Alternative, token, namespaceToken)) {
+ const XsdAlternative::Ptr alternative = parseAlternative();
+ alternatives.append(alternative);
+ } else if (isSchemaTag(XsdSchemaToken::Unique, token, namespaceToken)) {
+ const XsdIdentityConstraint::Ptr constraint = parseUnique();
+ element->addIdentityConstraint(constraint);
+ } else if (isSchemaTag(XsdSchemaToken::Key, token, namespaceToken)) {
+ const XsdIdentityConstraint::Ptr constraint = parseKey();
+ element->addIdentityConstraint(constraint);
+ } else if (isSchemaTag(XsdSchemaToken::Keyref, token, namespaceToken)) {
+ const XsdIdentityConstraint::Ptr constraint = parseKeyRef(element);
+ element->addIdentityConstraint(constraint);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ if (!hasTypeSpecified) {
+ if (hasSubstitutionGroup)
+ m_schemaResolver->addSubstitutionGroupType(element);
+ else
+ element->setType(BuiltinTypes::xsAnyType);
+ }
+
+ if (!alternatives.isEmpty()) {
+ element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
+
+ for (int i = 0; i < alternatives.count(); ++i) {
+ if (alternatives.at(i)->test())
+ element->typeTable()->addAlternative(alternatives.at(i));
+
+ if (i == (alternatives.count() - 1)) { // the final one
+ if (!alternatives.at(i)->test()) {
+ element->typeTable()->setDefaultTypeDefinition(alternatives.at(i));
+ } else {
+ const XsdAlternative::Ptr alternative(new XsdAlternative());
+ if (element->type())
+ alternative->setType(element->type());
+ else
+ m_schemaResolver->addAlternativeType(alternative, element); // add to resolver
+
+ element->typeTable()->setDefaultTypeDefinition(alternative);
+ }
+ }
+ }
+ }
+
+ return element;
+}
+
+XsdTerm::Ptr XsdSchemaParser::parseLocalElement(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this);
+
+ validateElement(XsdTagScope::LocalElement);
+
+ bool hasRefAttribute = false;
+ bool hasTypeAttribute = false;
+ bool hasTypeSpecified = false;
+
+ XsdTerm::Ptr term;
+ XsdElement::Ptr element;
+ if (hasAttribute(QString::fromLatin1("ref"))) {
+ term = XsdReference::Ptr(new XsdReference());
+ hasRefAttribute = true;
+ } else {
+ term = XsdElement::Ptr(new XsdElement());
+ element = term;
+ }
+
+ if (hasRefAttribute) {
+ if (hasAttribute(QString::fromLatin1("name"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("name")));
+ return term;
+ } else if (hasAttribute(QString::fromLatin1("block"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("block")));
+ return term;
+ } else if (hasAttribute(QString::fromLatin1("nillable"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("nillable")));
+ return term;
+ } else if (hasAttribute(QString::fromLatin1("default"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("default")));
+ return term;
+ } else if (hasAttribute(QString::fromLatin1("fixed"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("fixed")));
+ return term;
+ } else if (hasAttribute(QString::fromLatin1("form"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("form")));
+ return term;
+ } else if (hasAttribute(QString::fromLatin1("type"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("ref"))
+ .arg(formatAttribute("type")));
+ return term;
+ }
+ }
+
+ // parse attributes
+ if (!parseMinMaxConstraint(particle, "element")) {
+ return element;
+ }
+
+ if (!hasAttribute(QString::fromLatin1("name")) && !hasAttribute(QString::fromLatin1("ref"))) {
+ error(QtXmlPatterns::tr("%1 element must have either %2 or %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("name"))
+ .arg(formatAttribute("ref")));
+ return element;
+ }
+
+ if (hasRefAttribute) {
+ const QString ref = readQNameAttribute(QString::fromLatin1("ref"), "element");
+ QXmlName referenceName;
+ convertName(ref, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
+
+ const XsdReference::Ptr reference = term;
+ reference->setReferenceName(referenceName);
+ reference->setType(XsdReference::Element);
+ reference->setSourceLocation(currentSourceLocation());
+ } else {
+ element->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope()));
+ element->scope()->setVariety(XsdElement::Scope::Local);
+ element->scope()->setParent(parent);
+
+ if (hasAttribute(QString::fromLatin1("name"))) {
+ const QString elementName = readNameAttribute("element");
+
+ QXmlName objectName;
+ if (hasAttribute(QString::fromLatin1("form"))) {
+ const QString value = readAttribute(QString::fromLatin1("form"));
+ if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) {
+ attributeContentError("form", "element", value);
+ return element;
+ }
+
+ if (value == QString::fromLatin1("qualified")) {
+ objectName = m_namePool->allocateQName(m_targetNamespace, elementName);
+ } else {
+ objectName = m_namePool->allocateQName(QString(), elementName);
+ }
+ } else {
+ if (m_elementFormDefault == QString::fromLatin1("qualified")) {
+ objectName = m_namePool->allocateQName(m_targetNamespace, elementName);
+ } else {
+ objectName = m_namePool->allocateQName(QString(), elementName);
+ }
+ }
+
+ element->setName(objectName);
+ }
+
+ if (hasAttribute(QString::fromLatin1("nillable"))) {
+ const QString nillable = readAttribute(QString::fromLatin1("nillable"));
+
+ const Boolean::Ptr value = Boolean::fromLexical(nillable);
+ if (value->hasError()) {
+ attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean);
+ return term;
+ }
+
+ element->setIsNillable(value->as<Boolean>()->value());
+ } else {
+ element->setIsNillable(false); // the default value
+ }
+
+ if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) {
+ error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together")
+ .arg(formatElement("element"))
+ .arg(formatAttribute("default"))
+ .arg(formatAttribute("fixed")));
+ return element;
+ }
+
+ if (hasAttribute(QString::fromLatin1("default"))) {
+ const QString value = readAttribute(QString::fromLatin1("default"));
+ element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
+ element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default);
+ element->valueConstraint()->setValue(value);
+ } else if (hasAttribute(QString::fromLatin1("fixed"))) {
+ const QString value = readAttribute(QString::fromLatin1("fixed"));
+ element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint()));
+ element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed);
+ element->valueConstraint()->setValue(value);
+ }
+
+ if (hasAttribute(QString::fromLatin1("type"))) {
+ const QString type = readQNameAttribute(QString::fromLatin1("type"), "element");
+ QXmlName typeName;
+ convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ m_schemaResolver->addElementType(element, typeName, currentSourceLocation()); // add to resolver
+
+ hasTypeAttribute = true;
+ hasTypeSpecified = true;
+ }
+
+ element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element"));
+ }
+
+ validateIdAttribute("element");
+
+ XsdAlternative::List alternatives;
+
+ TagValidationHandler tagValidator(XsdTagScope::LocalElement, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ element->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ if (hasRefAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("simpleType"))
+ .arg(formatAttribute("ref")));
+ return term;
+ } else if (hasTypeAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("simpleType"))
+ .arg(formatAttribute("type")));
+ return term;
+ }
+
+ const XsdSimpleType::Ptr type = parseLocalSimpleType();
+ type->setContext(element);
+ element->setType(type);
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+
+ hasTypeSpecified = true;
+ } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
+ if (hasRefAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("complexType"))
+ .arg(formatAttribute("ref")));
+ return term;
+ } else if (hasTypeAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("complexType"))
+ .arg(formatAttribute("type")));
+ return term;
+ }
+
+ const XsdComplexType::Ptr type = parseLocalComplexType();
+ type->setContext(element);
+ element->setType(type);
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+
+ hasTypeSpecified = true;
+ } else if (isSchemaTag(XsdSchemaToken::Alternative, token, namespaceToken)) {
+ if (hasRefAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("alternative"))
+ .arg(formatAttribute("ref")));
+ return term;
+ }
+
+ const XsdAlternative::Ptr alternative = parseAlternative();
+ alternatives.append(alternative);
+ } else if (isSchemaTag(XsdSchemaToken::Unique, token, namespaceToken)) {
+ if (hasRefAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("unique"))
+ .arg(formatAttribute("ref")));
+ return term;
+ }
+
+ const XsdIdentityConstraint::Ptr constraint = parseUnique();
+ element->addIdentityConstraint(constraint);
+ } else if (isSchemaTag(XsdSchemaToken::Key, token, namespaceToken)) {
+ if (hasRefAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("key"))
+ .arg(formatAttribute("ref")));
+ return term;
+ }
+
+ const XsdIdentityConstraint::Ptr constraint = parseKey();
+ element->addIdentityConstraint(constraint);
+ } else if (isSchemaTag(XsdSchemaToken::Keyref, token, namespaceToken)) {
+ if (hasRefAttribute) {
+ error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute")
+ .arg(formatElement("element"))
+ .arg(formatElement("keyref"))
+ .arg(formatAttribute("ref")));
+ return term;
+ }
+
+ const XsdIdentityConstraint::Ptr constraint = parseKeyRef(element);
+ element->addIdentityConstraint(constraint);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ if (!hasTypeSpecified && !hasRefAttribute)
+ element->setType(BuiltinTypes::xsAnyType);
+
+ if (!hasRefAttribute && !alternatives.isEmpty()) {
+ element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable()));
+
+ for (int i = 0; i < alternatives.count(); ++i) {
+ if (alternatives.at(i)->test())
+ element->typeTable()->addAlternative(alternatives.at(i));
+
+ if (i == (alternatives.count() - 1)) { // the final one
+ if (!alternatives.at(i)->test()) {
+ element->typeTable()->setDefaultTypeDefinition(alternatives.at(i));
+ } else {
+ const XsdAlternative::Ptr alternative(new XsdAlternative());
+ if (element->type())
+ alternative->setType(element->type());
+ else
+ m_schemaResolver->addAlternativeType(alternative, element); // add to resolver
+
+ element->typeTable()->setDefaultTypeDefinition(alternative);
+ }
+ }
+ }
+ }
+
+ return term;
+}
+
+XsdIdentityConstraint::Ptr XsdSchemaParser::parseUnique()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Unique, this);
+
+ validateElement(XsdTagScope::Unique);
+
+ const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
+ constraint->setCategory(XsdIdentityConstraint::Unique);
+
+ // parse attributes
+ const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("unique"));
+ constraint->setName(objectName);
+
+ validateIdAttribute("unique");
+
+ TagValidationHandler tagValidator(XsdTagScope::Unique, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ constraint->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) {
+ parseSelector(constraint);
+ } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) {
+ parseField(constraint);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ // add constraint to schema for further checking
+ addIdentityConstraint(constraint);
+
+ tagValidator.finalize();
+
+ return constraint;
+}
+
+XsdIdentityConstraint::Ptr XsdSchemaParser::parseKey()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Key, this);
+
+ validateElement(XsdTagScope::Key);
+
+ const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
+ constraint->setCategory(XsdIdentityConstraint::Key);
+
+ // parse attributes
+ const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("key"));
+ constraint->setName(objectName);
+
+ validateIdAttribute("key");
+
+ TagValidationHandler tagValidator(XsdTagScope::Key, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ constraint->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) {
+ parseSelector(constraint);
+ } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) {
+ parseField(constraint);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ // add constraint to schema for further checking
+ addIdentityConstraint(constraint);
+
+ tagValidator.finalize();
+
+ return constraint;
+}
+
+XsdIdentityConstraint::Ptr XsdSchemaParser::parseKeyRef(const XsdElement::Ptr &element)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Keyref, this);
+
+ validateElement(XsdTagScope::KeyRef);
+
+ const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint());
+ constraint->setCategory(XsdIdentityConstraint::KeyReference);
+
+ // parse attributes
+ const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("keyref"));
+ constraint->setName(objectName);
+
+ const QString refer = readQNameAttribute(QString::fromLatin1("refer"), "keyref");
+ QXmlName referenceName;
+ convertName(refer, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName
+ m_schemaResolver->addKeyReference(element, constraint, referenceName, currentSourceLocation()); // add to resolver
+
+ validateIdAttribute("keyref");
+
+ TagValidationHandler tagValidator(XsdTagScope::KeyRef, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ constraint->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) {
+ parseSelector(constraint);
+ } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) {
+ parseField(constraint);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ // add constraint to schema for further checking
+ addIdentityConstraint(constraint);
+
+ tagValidator.finalize();
+
+ return constraint;
+}
+
+void XsdSchemaParser::parseSelector(const XsdIdentityConstraint::Ptr &ptr)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Selector, this);
+
+ validateElement(XsdTagScope::Selector);
+
+ // parse attributes
+ const XsdXPathExpression::Ptr expression = readXPathExpression("selector");
+
+ const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathSelector, "selector");
+ expression->setExpression(xpath);
+
+ ptr->setSelector(expression);
+
+ validateIdAttribute("selector");
+
+ TagValidationHandler tagValidator(XsdTagScope::Selector, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ expression->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+}
+
+void XsdSchemaParser::parseField(const XsdIdentityConstraint::Ptr &ptr)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Field, this);
+
+ validateElement(XsdTagScope::Field);
+
+ // parse attributes
+ const XsdXPathExpression::Ptr expression = readXPathExpression("field");
+
+ const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathField, "field");
+ expression->setExpression(xpath);
+
+ ptr->addField(expression);
+
+ validateIdAttribute("field");
+
+ TagValidationHandler tagValidator(XsdTagScope::Field, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ expression->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+}
+
+XsdAlternative::Ptr XsdSchemaParser::parseAlternative()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Alternative, this);
+
+ validateElement(XsdTagScope::Alternative);
+
+ const XsdAlternative::Ptr alternative(new XsdAlternative());
+
+ bool hasTypeSpecified = false;
+
+ if (hasAttribute(QString::fromLatin1("test"))) {
+ const XsdXPathExpression::Ptr expression = readXPathExpression("alternative");
+
+ const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "alternative");
+ expression->setExpression(test);
+
+ alternative->setTest(expression);
+ }
+
+ if (hasAttribute(QString::fromLatin1("type"))) {
+ const QString type = readQNameAttribute(QString::fromLatin1("type"), "alternative");
+ QXmlName typeName;
+ convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName
+ m_schemaResolver->addAlternativeType(alternative, typeName, currentSourceLocation()); // add to resolver
+
+ hasTypeSpecified = true;
+ }
+
+ validateIdAttribute("alternative");
+
+ TagValidationHandler tagValidator(XsdTagScope::Alternative, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ alternative->addAnnotation(annotation);
+ } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) {
+ const XsdSimpleType::Ptr type = parseLocalSimpleType();
+ alternative->setType(type);
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+
+ hasTypeSpecified = true;
+ } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) {
+ const XsdComplexType::Ptr type = parseLocalComplexType();
+ alternative->setType(type);
+
+ // add it to list of anonymous types as well
+ addAnonymousType(type);
+
+ hasTypeSpecified = true;
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ if (!hasTypeSpecified) {
+ error(QtXmlPatterns::tr("%1 element must have either %2 attribute or %3 or %4 as child element")
+ .arg(formatElement("alternative"))
+ .arg(formatAttribute("type"))
+ .arg(formatElement("simpleType"))
+ .arg(formatElement("complexType")));
+ return alternative;
+ }
+
+ return alternative;
+}
+
+XsdNotation::Ptr XsdSchemaParser::parseNotation()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Notation, this);
+
+ validateElement(XsdTagScope::Notation);
+
+ const XsdNotation::Ptr notation(new XsdNotation());
+
+ // parse attributes
+ const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("notation"));
+ notation->setName(objectName);
+
+ bool hasOptionalAttribute = false;
+
+ if (hasAttribute(QString::fromLatin1("public"))) {
+ const QString value = readAttribute(QString::fromLatin1("public"));
+ if (!value.isEmpty()) {
+ const DerivedString<TypeToken>::Ptr publicId = DerivedString<TypeToken>::fromLexical(m_namePool, value);
+ if (publicId->hasError()) {
+ attributeContentError("public", "notation", value, BuiltinTypes::xsToken);
+ return notation;
+ }
+ notation->setPublicId(publicId);
+ }
+
+ hasOptionalAttribute = true;
+ }
+
+ if (hasAttribute(QString::fromLatin1("system"))) {
+ const QString value = readAttribute(QString::fromLatin1("system"));
+ if (!isValidUri(value)) {
+ attributeContentError("system", "notation", value, BuiltinTypes::xsAnyURI);
+ return notation;
+ }
+
+ if (!value.isEmpty()) {
+ const AnyURI::Ptr systemId = AnyURI::fromLexical(value);
+ notation->setSystemId(systemId);
+ }
+
+ hasOptionalAttribute = true;
+ }
+
+ if (!hasOptionalAttribute) {
+ error(QtXmlPatterns::tr("%1 element requires either %2 or %3 attribute")
+ .arg(formatElement("notation"))
+ .arg(formatAttribute("public"))
+ .arg(formatAttribute("system")));
+ return notation;
+ }
+
+ validateIdAttribute("notation");
+
+ TagValidationHandler tagValidator(XsdTagScope::Notation, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isCharacters() || isEntityReference()) {
+ if (!text().toString().trimmed().isEmpty()) {
+ error(QtXmlPatterns::tr("text or entity references not allowed inside %1 element").arg(formatElement("notation")));
+ return notation;
+ }
+ }
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ notation->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return notation;
+}
+
+XsdWildcard::Ptr XsdSchemaParser::parseAny(const XsdParticle::Ptr &particle)
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Any, this);
+
+ validateElement(XsdTagScope::Any);
+
+ const XsdWildcard::Ptr wildcard(new XsdWildcard());
+
+ // parse attributes
+ if (!parseMinMaxConstraint(particle, "any")) {
+ return wildcard;
+ }
+
+ if (hasAttribute(QString::fromLatin1("namespace"))) {
+ const QSet<QString> values = readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
+ if ((values.contains(QString::fromLatin1("##any")) || values.contains(QString::fromLatin1("##other"))) && values.count() != 1) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs")
+ .arg(formatAttribute("namespace"))
+ .arg(formatElement("any"))
+ .arg(formatData("##any"))
+ .arg(formatData("##other")));
+ return wildcard;
+ }
+
+ if (values.contains(QString::fromLatin1("##any"))) {
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ } else if (values.contains(QString::fromLatin1("##other"))) {
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
+ if (!m_targetNamespace.isEmpty())
+ wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << m_targetNamespace);
+ else
+ wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
+ } else {
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
+ QStringList newValues = values.toList();
+
+ // replace the ##targetNamespace entry
+ for (int i = 0; i < newValues.count(); ++i) {
+ if (newValues.at(i) == QString::fromLatin1("##targetNamespace")) {
+ if (!m_targetNamespace.isEmpty())
+ newValues[i] = m_targetNamespace;
+ else
+ newValues[i] = XsdWildcard::absentNamespace();
+ } else if (newValues.at(i) == QString::fromLatin1("##local")) {
+ newValues[i] = XsdWildcard::absentNamespace();
+ }
+ }
+
+ // check for invalid URIs
+ for (int i = 0; i < newValues.count(); ++i) {
+ const QString stringValue = newValues.at(i);
+ if (stringValue == XsdWildcard::absentNamespace())
+ continue;
+
+ if (!isValidUri(stringValue)) {
+ attributeContentError("namespace", "any", stringValue, BuiltinTypes::xsAnyURI);
+ return wildcard;
+ }
+ }
+
+ wildcard->namespaceConstraint()->setNamespaces(newValues.toSet());
+ }
+ } else {
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ }
+
+ if (hasAttribute(QString::fromLatin1("processContents"))) {
+ const QString value = readAttribute(QString::fromLatin1("processContents"));
+ if (value != QString::fromLatin1("lax") &&
+ value != QString::fromLatin1("skip") &&
+ value != QString::fromLatin1("strict")) {
+ attributeContentError("processContents", "any", value);
+ return wildcard;
+ }
+
+ if (value == QString::fromLatin1("lax")) {
+ wildcard->setProcessContents(XsdWildcard::Lax);
+ } else if (value == QString::fromLatin1("skip")) {
+ wildcard->setProcessContents(XsdWildcard::Skip);
+ } else if (value == QString::fromLatin1("strict")) {
+ wildcard->setProcessContents(XsdWildcard::Strict);
+ }
+ } else {
+ wildcard->setProcessContents(XsdWildcard::Strict);
+ }
+
+ validateIdAttribute("any");
+
+ TagValidationHandler tagValidator(XsdTagScope::Any, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ wildcard->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return wildcard;
+}
+
+XsdWildcard::Ptr XsdSchemaParser::parseAnyAttribute()
+{
+ const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AnyAttribute, this);
+
+ validateElement(XsdTagScope::AnyAttribute);
+
+ const XsdWildcard::Ptr wildcard(new XsdWildcard());
+
+ // parse attributes
+ if (hasAttribute(QString::fromLatin1("namespace"))) {
+ const QSet<QString> values = readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
+ if ((values.contains(QString::fromLatin1("##any")) || values.contains(QString::fromLatin1("##other"))) && values.count() != 1) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs")
+ .arg(formatAttribute("namespace"))
+ .arg(formatElement("anyAttribute"))
+ .arg(formatData("##any"))
+ .arg(formatData("##other")));
+ return wildcard;
+ }
+
+ if (values.contains(QString::fromLatin1("##any"))) {
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ } else if (values.contains(QString::fromLatin1("##other"))) {
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not);
+ if (!m_targetNamespace.isEmpty())
+ wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << m_targetNamespace);
+ else
+ wildcard->namespaceConstraint()->setNamespaces(QSet<QString>() << XsdWildcard::absentNamespace());
+ } else {
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration);
+ QStringList newValues = values.toList();
+
+ // replace the ##targetNamespace entry
+ for (int i = 0; i < newValues.count(); ++i) {
+ if (newValues.at(i) == QString::fromLatin1("##targetNamespace")) {
+ if (!m_targetNamespace.isEmpty())
+ newValues[i] = m_targetNamespace;
+ else
+ newValues[i] = XsdWildcard::absentNamespace();
+ } else if (newValues.at(i) == QString::fromLatin1("##local")) {
+ newValues[i] = XsdWildcard::absentNamespace();
+ }
+ }
+
+ // check for invalid URIs
+ for (int i = 0; i < newValues.count(); ++i) {
+ const QString stringValue = newValues.at(i);
+ if (stringValue == XsdWildcard::absentNamespace())
+ continue;
+
+ if (!isValidUri(stringValue)) {
+ attributeContentError("namespace", "anyAttribute", stringValue, BuiltinTypes::xsAnyURI);
+ return wildcard;
+ }
+ }
+
+ wildcard->namespaceConstraint()->setNamespaces(newValues.toSet());
+ }
+ } else {
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ }
+
+ if (hasAttribute(QString::fromLatin1("processContents"))) {
+ const QString value = readAttribute(QString::fromLatin1("processContents"));
+ if (value != QString::fromLatin1("lax") &&
+ value != QString::fromLatin1("skip") &&
+ value != QString::fromLatin1("strict")) {
+ attributeContentError("processContents", "anyAttribute", value);
+ return wildcard;
+ }
+
+ if (value == QString::fromLatin1("lax")) {
+ wildcard->setProcessContents(XsdWildcard::Lax);
+ } else if (value == QString::fromLatin1("skip")) {
+ wildcard->setProcessContents(XsdWildcard::Skip);
+ } else if (value == QString::fromLatin1("strict")) {
+ wildcard->setProcessContents(XsdWildcard::Strict);
+ }
+ } else {
+ wildcard->setProcessContents(XsdWildcard::Strict);
+ }
+
+ validateIdAttribute("anyAttribute");
+
+ TagValidationHandler tagValidator(XsdTagScope::AnyAttribute, this, m_namePool);
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement()) {
+ const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name());
+ const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri());
+
+ tagValidator.validate(token);
+
+ if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) {
+ const XsdAnnotation::Ptr annotation = parseAnnotation();
+ wildcard->addAnnotation(annotation);
+ } else {
+ parseUnknown();
+ }
+ }
+ }
+
+ tagValidator.finalize();
+
+ return wildcard;
+}
+
+
+void XsdSchemaParser::parseUnknownDocumentation()
+{
+ Q_ASSERT(isStartElement());
+ m_namespaceSupport.pushContext();
+ m_namespaceSupport.setPrefixes(namespaceDeclarations());
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement())
+ parseUnknownDocumentation();
+ }
+
+ m_namespaceSupport.popContext();
+}
+
+void XsdSchemaParser::parseUnknown()
+{
+ Q_ASSERT(isStartElement());
+ m_namespaceSupport.pushContext();
+ m_namespaceSupport.setPrefixes(namespaceDeclarations());
+
+ error(QtXmlPatterns::tr("%1 element is not allowed in this context").arg(formatElement(name().toString())));
+
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ break;
+
+ if (isStartElement())
+ parseUnknown();
+ }
+
+ m_namespaceSupport.popContext();
+}
+
+bool XsdSchemaParser::parseMinMaxConstraint(const XsdParticle::Ptr &particle, const char *elementName)
+{
+ if (hasAttribute(QString::fromLatin1("minOccurs"))) {
+ const QString value = readAttribute(QString::fromLatin1("minOccurs"));
+
+ DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
+ if (integer->hasError()) {
+ attributeContentError("minOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger);
+ return false;
+ } else {
+ particle->setMinimumOccurs(integer->as< DerivedInteger<TypeNonNegativeInteger> >()->storedValue());
+ }
+ } else {
+ particle->setMinimumOccurs(1);
+ }
+
+ if (hasAttribute(QString::fromLatin1("maxOccurs"))) {
+ const QString value = readAttribute(QString::fromLatin1("maxOccurs"));
+
+ if (value == QString::fromLatin1("unbounded")) {
+ particle->setMaximumOccursUnbounded(true);
+ } else {
+ particle->setMaximumOccursUnbounded(false);
+ DerivedInteger<TypeNonNegativeInteger>::Ptr integer = DerivedInteger<TypeNonNegativeInteger>::fromLexical(m_namePool, value);
+ if (integer->hasError()) {
+ attributeContentError("maxOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger);
+ return false;
+ } else {
+ particle->setMaximumOccurs(integer->as< DerivedInteger<TypeNonNegativeInteger> >()->storedValue());
+ }
+ }
+ } else {
+ particle->setMaximumOccursUnbounded(false);
+ particle->setMaximumOccurs(1);
+ }
+
+ if (!particle->maximumOccursUnbounded()) {
+ if (particle->maximumOccurs() < particle->minimumOccurs()) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element has larger value than %3 attribute")
+ .arg(formatAttribute("minOccurs"))
+ .arg(formatElement(elementName))
+ .arg(formatAttribute("maxOccurs")));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+QSourceLocation XsdSchemaParser::currentSourceLocation() const
+{
+ QSourceLocation location;
+ location.setLine(lineNumber());
+ location.setColumn(columnNumber());
+ location.setUri(m_documentURI);
+
+ return location;
+}
+
+void XsdSchemaParser::convertName(const QString &qualifiedName, NamespaceSupport::NameType type, QXmlName &name)
+{
+ bool result = m_namespaceSupport.processName(qualifiedName, type, name);
+ if (!result) {
+ error(QtXmlPatterns::tr("prefix of qualified name %1 is not defined").arg(formatKeyword(qualifiedName)));
+ }
+}
+
+QString XsdSchemaParser::readNameAttribute(const char *elementName)
+{
+ const QString value = readAttribute(QString::fromLatin1("name")).simplified();
+ if (!QXmlUtils::isNCName(value)) {
+ attributeContentError("name", elementName, value, BuiltinTypes::xsNCName);
+ return QString();
+ } else {
+ return value;
+ }
+}
+
+QString XsdSchemaParser::readQNameAttribute(const QString &typeAttribute, const char *elementName)
+{
+ const QString value = readAttribute(typeAttribute).simplified();
+ if (!XPathHelper::isQName(value)) {
+ attributeContentError(typeAttribute.toLatin1(), elementName, value, BuiltinTypes::xsQName);
+ return QString();
+ } else {
+ return value;
+ }
+}
+
+QString XsdSchemaParser::readNamespaceAttribute(const QString &attributeName, const char *elementName)
+{
+ const QString value = readAttribute(attributeName);
+ if (value.isEmpty()) {
+ attributeContentError(attributeName.toLatin1(), elementName, value, BuiltinTypes::xsAnyURI);
+ return QString();
+ }
+
+ return value;
+}
+
+SchemaType::DerivationConstraints XsdSchemaParser::readDerivationConstraintAttribute(const SchemaType::DerivationConstraints &allowedConstraints, const char *elementName)
+{
+ // first convert the flags into strings for easier comparision
+ QSet<QString> allowedContent;
+ if (allowedConstraints & SchemaType::RestrictionConstraint)
+ allowedContent.insert(QString::fromLatin1("restriction"));
+ if (allowedConstraints & SchemaType::ExtensionConstraint)
+ allowedContent.insert(QString::fromLatin1("extension"));
+ if (allowedConstraints & SchemaType::ListConstraint)
+ allowedContent.insert(QString::fromLatin1("list"));
+ if (allowedConstraints & SchemaType::UnionConstraint)
+ allowedContent.insert(QString::fromLatin1("union"));
+
+ // read content from the attribute if available, otherwise use the default definitions from the schema tag
+ QString content;
+ if (hasAttribute(QString::fromLatin1("final"))) {
+ content = readAttribute(QString::fromLatin1("final"));
+
+ // split string into list to validate the content of the attribute
+ const QStringList values = content.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < values.count(); i++) {
+ const QString value = values.at(i);
+ if (!allowedContent.contains(value) && (value != QString::fromLatin1("#all"))) {
+ attributeContentError("final", elementName, value);
+ return SchemaType::DerivationConstraints();
+ }
+
+ if ((value == QString::fromLatin1("#all")) && values.count() != 1) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values")
+ .arg(formatAttribute("final"))
+ .arg(formatElement(elementName))
+ .arg(formatData("#all")));
+ return SchemaType::DerivationConstraints();
+ }
+ }
+ } else {
+ // content of the default value has been validated in parseSchema already
+ content = m_finalDefault;
+ }
+
+ QSet<QString> contentSet = content.split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
+
+ // if the '#all' tag is defined, we return all allowed values
+ if (contentSet.contains(QString::fromLatin1("#all"))) {
+ return allowedConstraints;
+ } else { // return the values from content set that intersects with the allowed values
+ contentSet.intersect(allowedContent);
+
+ SchemaType::DerivationConstraints constraints;
+
+ if (contentSet.contains(QString::fromLatin1("restriction")))
+ constraints |= SchemaType::RestrictionConstraint;
+ if (contentSet.contains(QString::fromLatin1("extension")))
+ constraints |= SchemaType::ExtensionConstraint;
+ if (contentSet.contains(QString::fromLatin1("list")))
+ constraints |= SchemaType::ListConstraint;
+ if (contentSet.contains(QString::fromLatin1("union")))
+ constraints |= SchemaType::UnionConstraint;
+
+ return constraints;
+ }
+}
+
+NamedSchemaComponent::BlockingConstraints XsdSchemaParser::readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints &allowedConstraints, const char *elementName)
+{
+ // first convert the flags into strings for easier comparision
+ QSet<QString> allowedContent;
+ if (allowedConstraints & NamedSchemaComponent::RestrictionConstraint)
+ allowedContent.insert(QString::fromLatin1("restriction"));
+ if (allowedConstraints & NamedSchemaComponent::ExtensionConstraint)
+ allowedContent.insert(QString::fromLatin1("extension"));
+ if (allowedConstraints & NamedSchemaComponent::SubstitutionConstraint)
+ allowedContent.insert(QString::fromLatin1("substitution"));
+
+ // read content from the attribute if available, otherwise use the default definitions from the schema tag
+ QString content;
+ if (hasAttribute(QString::fromLatin1("block"))) {
+ content = readAttribute(QString::fromLatin1("block"));
+
+ // split string into list to validate the content of the attribute
+ const QStringList values = content.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < values.count(); i++) {
+ const QString value = values.at(i);
+ if (!allowedContent.contains(value) && (value != QString::fromLatin1("#all"))) {
+ attributeContentError("block", elementName, value);
+ return NamedSchemaComponent::BlockingConstraints();
+ }
+
+ if ((value == QString::fromLatin1("#all")) && values.count() != 1) {
+ error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values")
+ .arg(formatAttribute("block"))
+ .arg(formatElement(elementName))
+ .arg(formatData("#all")));
+ return NamedSchemaComponent::BlockingConstraints();
+ }
+ }
+ } else {
+ // content of the default value has been validated in parseSchema already
+ content = m_blockDefault;
+ }
+
+ QSet<QString> contentSet = content.split(QLatin1Char(' '), QString::SkipEmptyParts).toSet();
+
+ // if the '#all' tag is defined, we return all allowed values
+ if (contentSet.contains(QString::fromLatin1("#all"))) {
+ return allowedConstraints;
+ } else { // return the values from content set that intersects with the allowed values
+ contentSet.intersect(allowedContent);
+
+ NamedSchemaComponent::BlockingConstraints constraints;
+
+ if (contentSet.contains(QString::fromLatin1("restriction")))
+ constraints |= NamedSchemaComponent::RestrictionConstraint;
+ if (contentSet.contains(QString::fromLatin1("extension")))
+ constraints |= NamedSchemaComponent::ExtensionConstraint;
+ if (contentSet.contains(QString::fromLatin1("substitution")))
+ constraints |= NamedSchemaComponent::SubstitutionConstraint;
+
+ return constraints;
+ }
+}
+
+XsdXPathExpression::Ptr XsdSchemaParser::readXPathExpression(const char *elementName)
+{
+ const XsdXPathExpression::Ptr expression(new XsdXPathExpression());
+
+ const QList<QXmlName> namespaceBindings = m_namespaceSupport.namespaceBindings();
+ QXmlName emptyName;
+ for (int i = 0; i < namespaceBindings.count(); ++i) {
+ if (namespaceBindings.at(i).prefix() == StandardPrefixes::empty)
+ emptyName = namespaceBindings.at(i);
+ }
+
+ expression->setNamespaceBindings(namespaceBindings);
+
+ QString xpathDefaultNamespace;
+ if (hasAttribute(QString::fromLatin1("xpathDefaultNamespace"))) {
+ xpathDefaultNamespace = readAttribute(QString::fromLatin1("xpathDefaultNamespace"));
+ if (xpathDefaultNamespace != QString::fromLatin1("##defaultNamespace") &&
+ xpathDefaultNamespace != QString::fromLatin1("##targetNamespace") &&
+ xpathDefaultNamespace != QString::fromLatin1("##local")) {
+ if (!isValidUri(xpathDefaultNamespace)) {
+ attributeContentError("xpathDefaultNamespace", elementName, xpathDefaultNamespace, BuiltinTypes::xsAnyURI);
+ return expression;
+ }
+ }
+ } else {
+ xpathDefaultNamespace = m_xpathDefaultNamespace;
+ }
+
+ AnyURI::Ptr namespaceURI;
+ if (xpathDefaultNamespace == QString::fromLatin1("##defaultNamespace")) {
+ if (!emptyName.isNull())
+ namespaceURI = AnyURI::fromLexical(m_namePool->stringForNamespace(emptyName.namespaceURI()));
+ } else if (xpathDefaultNamespace == QString::fromLatin1("##targetNamespace")) {
+ if (!m_targetNamespace.isEmpty())
+ namespaceURI = AnyURI::fromLexical(m_targetNamespace);
+ } else if (xpathDefaultNamespace == QString::fromLatin1("##local")) {
+ // it is absent
+ } else {
+ namespaceURI = AnyURI::fromLexical(xpathDefaultNamespace);
+ }
+ if (namespaceURI) {
+ if (namespaceURI->hasError()) {
+ attributeContentError("xpathDefaultNamespace", elementName, xpathDefaultNamespace, BuiltinTypes::xsAnyURI);
+ return expression;
+ }
+
+ expression->setDefaultNamespace(namespaceURI);
+ }
+
+ //TODO: read the base uri if qmaintaining reader support it
+
+ return expression;
+}
+
+QString XsdSchemaParser::readXPathAttribute(const QString &attributeName, XPathType type, const char *elementName)
+{
+ const QString value = readAttribute(attributeName);
+ if (value.isEmpty() || value.startsWith(QLatin1Char('/'))) {
+ attributeContentError(attributeName.toLatin1(), elementName, value);
+ return QString();
+ }
+
+ QXmlNamePool namePool(m_namePool.data());
+
+ QXmlQuery::QueryLanguage language;
+ switch (type) {
+ case XPath20: language = QXmlQuery::XPath20; break;
+ case XPathSelector: language = QXmlQuery::XmlSchema11IdentityConstraintSelector; break;
+ case XPathField: language = QXmlQuery::XmlSchema11IdentityConstraintField; break;
+ };
+
+ QXmlQuery query(language, namePool);
+ QXmlQueryPrivate *queryPrivate = query.d;
+
+ const QList<QXmlName> namespaceBindings = m_namespaceSupport.namespaceBindings();
+ for (int i = 0; i < namespaceBindings.count(); ++i) {
+ if (!namespaceBindings.at(i).prefix() == StandardPrefixes::empty)
+ queryPrivate->addAdditionalNamespaceBinding(namespaceBindings.at(i));
+ }
+
+ query.setQuery(value, m_documentURI);
+ if (!query.isValid()) {
+ attributeContentError(attributeName.toLatin1(), elementName, value);
+ return QString();
+ }
+
+ return value;
+}
+
+void XsdSchemaParser::validateIdAttribute(const char *elementName)
+{
+ if (hasAttribute(QString::fromLatin1("id"))) {
+ const QString value = readAttribute(QString::fromLatin1("id"));
+ DerivedString<TypeID>::Ptr id = DerivedString<TypeID>::fromLexical(m_namePool, value);
+ if (id->hasError()) {
+ attributeContentError("id", elementName, value, BuiltinTypes::xsID);
+ } else {
+ if (m_idCache->hasId(value)) {
+ error(QtXmlPatterns::tr("component with id %1 has been defined previously").arg(formatData(value)));
+ } else {
+ m_idCache->addId(value);
+ }
+ }
+ }
+}
+
+bool XsdSchemaParser::isSchemaTag(XsdSchemaToken::NodeName tag, XsdSchemaToken::NodeName token, XsdSchemaToken::NodeName namespaceToken) const
+{
+ return ((tag == token) && (namespaceToken == XsdSchemaToken::XML_NS_SCHEMA_URI));
+}
+
+void XsdSchemaParser::addElement(const XsdElement::Ptr &element)
+{
+ const QXmlName objectName = element->name(m_namePool);
+ if (m_schema->element(objectName)) {
+ error(QtXmlPatterns::tr("element %1 already defined").arg(formatElement(m_namePool->displayName(objectName))));
+ } else {
+ m_schema->addElement(element);
+ m_componentLocationHash.insert(element, currentSourceLocation());
+ }
+}
+
+void XsdSchemaParser::addAttribute(const XsdAttribute::Ptr &attribute)
+{
+ const QXmlName objectName = attribute->name(m_namePool);
+ if (m_schema->attribute(objectName)) {
+ error(QtXmlPatterns::tr("attribute %1 already defined").arg(formatAttribute(m_namePool->displayName(objectName))));
+ } else {
+ m_schema->addAttribute(attribute);
+ m_componentLocationHash.insert(attribute, currentSourceLocation());
+ }
+}
+
+void XsdSchemaParser::addType(const SchemaType::Ptr &type)
+{
+ // we don't import redefinitions of builtin types, that just causes problems
+ if (m_builtinTypeNames.contains(type->name(m_namePool)))
+ return;
+
+ const QXmlName objectName = type->name(m_namePool);
+ if (m_schema->type(objectName)) {
+ error(QtXmlPatterns::tr("type %1 already defined").arg(formatType(m_namePool, objectName)));
+ } else {
+ m_schema->addType(type);
+ if (type->isSimpleType())
+ m_componentLocationHash.insert(XsdSimpleType::Ptr(type), currentSourceLocation());
+ else
+ m_componentLocationHash.insert(XsdComplexType::Ptr(type), currentSourceLocation());
+ }
+}
+
+void XsdSchemaParser::addAnonymousType(const SchemaType::Ptr &type)
+{
+ m_schema->addAnonymousType(type);
+ if (type->isSimpleType())
+ m_componentLocationHash.insert(XsdSimpleType::Ptr(type), currentSourceLocation());
+ else
+ m_componentLocationHash.insert(XsdComplexType::Ptr(type), currentSourceLocation());
+}
+
+void XsdSchemaParser::addAttributeGroup(const XsdAttributeGroup::Ptr &group)
+{
+ const QXmlName objectName = group->name(m_namePool);
+ if (m_schema->attributeGroup(objectName)) {
+ error(QtXmlPatterns::tr("attribute group %1 already defined").arg(formatKeyword(m_namePool, objectName)));
+ } else {
+ m_schema->addAttributeGroup(group);
+ m_componentLocationHash.insert(group, currentSourceLocation());
+ }
+}
+
+void XsdSchemaParser::addElementGroup(const XsdModelGroup::Ptr &group)
+{
+ const QXmlName objectName = group->name(m_namePool);
+ if (m_schema->elementGroup(objectName)) {
+ error(QtXmlPatterns::tr("element group %1 already defined").arg(formatKeyword(m_namePool, objectName)));
+ } else {
+ m_schema->addElementGroup(group);
+ m_componentLocationHash.insert(group, currentSourceLocation());
+ }
+}
+
+void XsdSchemaParser::addNotation(const XsdNotation::Ptr &notation)
+{
+ const QXmlName objectName = notation->name(m_namePool);
+ if (m_schema->notation(objectName)) {
+ error(QtXmlPatterns::tr("notation %1 already defined").arg(formatKeyword(m_namePool, objectName)));
+ } else {
+ m_schema->addNotation(notation);
+ m_componentLocationHash.insert(notation, currentSourceLocation());
+ }
+}
+
+void XsdSchemaParser::addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint)
+{
+ const QXmlName objectName = constraint->name(m_namePool);
+ if (m_schema->identityConstraint(objectName)) {
+ error(QtXmlPatterns::tr("identity constraint %1 already defined").arg(formatKeyword(m_namePool, objectName)));
+ } else {
+ m_schema->addIdentityConstraint(constraint);
+ m_componentLocationHash.insert(constraint, currentSourceLocation());
+ }
+}
+
+void XsdSchemaParser::addFacet(const XsdFacet::Ptr &facet, XsdFacet::Hash &facets, const SchemaType::Ptr &type)
+{
+ // @see http://www.w3.org/TR/xmlschema-2/#src-single-facet-value
+ if (facets.contains(facet->type())) {
+ error(QtXmlPatterns::tr("duplicated facets in simple type %1").arg(formatType(m_namePool, type)));
+ return;
+ }
+
+ facets.insert(facet->type(), facet);
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemaparser_p.h b/src/xmlpatterns/schema/qxsdschemaparser_p.h
new file mode 100644
index 0000000000..960fb863f5
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemaparser_p.h
@@ -0,0 +1,691 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchemaParser_H
+#define Patternist_XsdSchemaParser_H
+
+#include "qnamespacesupport_p.h"
+#include "qxsdalternative_p.h"
+#include "qxsdattribute_p.h"
+#include "qxsdattributegroup_p.h"
+#include "qxsdattributeterm_p.h"
+#include "qxsdcomplextype_p.h"
+#include "qxsdelement_p.h"
+#include "qxsdidcache_p.h"
+#include "qxsdmodelgroup_p.h"
+#include "qxsdnotation_p.h"
+#include "qxsdsimpletype_p.h"
+#include "qxsdschemacontext_p.h"
+#include "qxsdschemaparsercontext_p.h"
+#include "qxsdstatemachine_p.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QSet>
+#include <QtCore/QUrl>
+#include <QtXml/QXmlStreamReader>
+#include <QtXmlPatterns/QXmlNamePool>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Implements the parsing of XML schema file.
+ *
+ * This class parses a XML schema in XML presentation from an QIODevice
+ * and returns object representation as XsdSchema.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSchemaParser : public MaintainingReader<XsdSchemaToken, XsdTagScope::Type>
+ {
+ friend class ElementNamespaceHandler;
+ friend class TagValidationHandler;
+
+ public:
+ enum ParserType
+ {
+ TopLevelParser,
+ IncludeParser,
+ ImportParser,
+ RedefineParser
+ };
+
+ /**
+ * Creates a new schema parser object.
+ */
+ XsdSchemaParser(const XsdSchemaContext::Ptr &context, const XsdSchemaParserContext::Ptr &parserContext, QIODevice *device);
+
+ /**
+ * Parses the XML schema file.
+ *
+ * @return @c true on success, @c false if the schema is somehow invalid.
+ */
+ bool parse(ParserType parserType = TopLevelParser);
+
+ /**
+ * Describes a set of namespace URIs
+ */
+ typedef QSet<QUrl> NamespaceSet;
+
+ /**
+ * Sets which @p schemas have been included already, so the parser
+ * can detect circular includes.
+ */
+ void setIncludedSchemas(const NamespaceSet &schemas);
+
+ /**
+ * Sets which @p schemas have been imported already, so the parser
+ * can detect circular imports.
+ */
+ void setImportedSchemas(const NamespaceSet &schemas);
+
+ /**
+ * Sets which @p schemas have been redefined already, so the parser
+ * can detect circular redefines.
+ */
+ void setRedefinedSchemas(const NamespaceSet &schemas);
+
+ /**
+ * Sets the target namespace of the schema to parse.
+ */
+ void setTargetNamespace(const QString &targetNamespace);
+
+ /**
+ * Sets the document URI of the schema to parse.
+ */
+ void setDocumentURI(const QUrl &uri);
+
+ /**
+ * Returns the document URI of the schema to parse.
+ */
+ QUrl documentURI() const;
+
+ /**
+ * Reimplemented from MaintainingReader, always returns @c false.
+ */
+ bool isAnyAttributeAllowed() const;
+
+ private:
+ /**
+ * Used internally to report any kind of parsing error or
+ * schema inconsistency.
+ */
+ virtual void error(const QString &msg);
+
+ void attributeContentError(const char *attributeName, const char *elementName, const QString &value, const SchemaType::Ptr &type = SchemaType::Ptr());
+
+ /**
+ * Sets the target namespace of the schema to parse.
+ */
+ void setTargetNamespaceExtended(const QString &targetNamespace);
+
+ /**
+ * This method is called for parsing the top-level <em>schema</em> object.
+ */
+ void parseSchema(ParserType parserType);
+
+ /**
+ * This method is called for parsing any top-level <em>include</em> object.
+ */
+ void parseInclude();
+
+ /**
+ * This method is called for parsing any top-level <em>import</em> object.
+ */
+ void parseImport();
+
+ /**
+ * This method is called for parsing any top-level <em>redefine</em> object.
+ */
+ void parseRedefine();
+
+ /**
+ * This method is called for parsing any <em>annotation</em> object everywhere
+ * in the schema.
+ */
+ XsdAnnotation::Ptr parseAnnotation();
+
+ /**
+ * This method is called for parsing an <em>appinfo</em> object as child of
+ * an <em>annotation</em> object.
+ */
+ XsdApplicationInformation::Ptr parseAppInfo();
+
+ /**
+ * This method is called for parsing a <em>documentation</em> object as child of
+ * an <em>annotation</em> object.
+ */
+ XsdDocumentation::Ptr parseDocumentation();
+
+ /**
+ * This method is called for parsing a <em>defaultOpenContent</em> object.
+ */
+ void parseDefaultOpenContent();
+
+ /**
+ * This method is called for parsing any top-level <em>simpleType</em> object.
+ */
+ XsdSimpleType::Ptr parseGlobalSimpleType();
+
+ /**
+ * This method is called for parsing any <em>simpleType</em> object as descendant
+ * of an <em>element</em> or <em>complexType</em> object.
+ */
+ XsdSimpleType::Ptr parseLocalSimpleType();
+
+ /**
+ * This method is called for parsing a <em>restriction</em> object as child
+ * of a <em>simpleType</em> object.
+ */
+ void parseSimpleRestriction(const XsdSimpleType::Ptr &ptr);
+
+ /**
+ * This method is called for parsing a <em>list</em> object as child
+ * of a <em>simpleType</em> object.
+ */
+ void parseList(const XsdSimpleType::Ptr &ptr);
+
+ /**
+ * This method is called for parsing a <em>union</em> object as child
+ * of a <em>simpleType</em> object.
+ */
+ void parseUnion(const XsdSimpleType::Ptr &ptr);
+
+ /**
+ * This method is called for parsing a <em>minExclusive</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseMinExclusiveFacet();
+
+ /**
+ * This method is called for parsing a <em>minInclusive</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseMinInclusiveFacet();
+
+ /**
+ * This method is called for parsing a <em>maxExclusive</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseMaxExclusiveFacet();
+
+ /**
+ * This method is called for parsing a <em>maxInclusive</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseMaxInclusiveFacet();
+
+ /**
+ * This method is called for parsing a <em>totalDigits</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseTotalDigitsFacet();
+
+ /**
+ * This method is called for parsing a <em>fractionDigits</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseFractionDigitsFacet();
+
+ /**
+ * This method is called for parsing a <em>length</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseLengthFacet();
+
+ /**
+ * This method is called for parsing a <em>minLength</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseMinLengthFacet();
+
+ /**
+ * This method is called for parsing a <em>maxLength</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseMaxLengthFacet();
+
+ /**
+ * This method is called for parsing an <em>enumeration</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseEnumerationFacet();
+
+ /**
+ * This method is called for parsing a <em>whiteSpace</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseWhiteSpaceFacet();
+
+ /**
+ * This method is called for parsing a <em>pattern</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parsePatternFacet();
+
+ /**
+ * This method is called for parsing an <em>assertion</em> object as child
+ * of a <em>restriction</em> object.
+ */
+ XsdFacet::Ptr parseAssertionFacet();
+
+ /**
+ * This method is called for parsing any top-level <em>complexType</em> object.
+ */
+ XsdComplexType::Ptr parseGlobalComplexType();
+
+ /**
+ * This method is called for parsing any <em>complexType</em> object as descendant
+ * of an <em>element</em> object.
+ */
+ XsdComplexType::Ptr parseLocalComplexType();
+
+ /**
+ * This method resolves the content type of the @p complexType for the given
+ * @p effectiveMixed value.
+ */
+ void resolveComplexContentType(const XsdComplexType::Ptr &complexType, bool effectiveMixed);
+
+ /**
+ * This method is called for parsing a <em>simpleContent</em> object as child
+ * of a <em>complexType</em> object.
+ */
+ void parseSimpleContent(const XsdComplexType::Ptr &complexType);
+
+ /**
+ * This method is called for parsing a <em>restriction</em> object as child
+ * of a <em>simpleContent</em> object.
+ */
+ void parseSimpleContentRestriction(const XsdComplexType::Ptr &complexType);
+
+ /**
+ * This method is called for parsing an <em>extension</em> object as child
+ * of a <em>simpleContent</em> object.
+ */
+ void parseSimpleContentExtension(const XsdComplexType::Ptr &complexType);
+
+ /**
+ * This method is called for parsing a <em>complexContent</em> object as child
+ * of a <em>complexType</em> object.
+ *
+ * @param complexType The complex type the complex content belongs to.
+ * @param mixed The output parameter for the mixed value.
+ */
+ void parseComplexContent(const XsdComplexType::Ptr &complexType, bool *mixed);
+
+ /**
+ * This method is called for parsing a <em>restriction</em> object as child
+ * of a <em>complexContent</em> object.
+ */
+ void parseComplexContentRestriction(const XsdComplexType::Ptr &complexType);
+
+ /**
+ * This method is called for parsing an <em>extension</em> object as child
+ * of a <em>complexContent</em> object.
+ */
+ void parseComplexContentExtension(const XsdComplexType::Ptr &complexType);
+
+ /**
+ * This method is called for parsing an <em>assert</em> object as child
+ * of a <em>complexType</em> or parsing a <em>assertion</em> facet object as
+ * child of a <em>simpleType</em>.
+ *
+ * @param nodeName Either XsdSchemaToken::Assert or XsdSchemaToken::Assertion.
+ * @param tag Either XsdTagScope::Assert or XsdTagScope::Assertion.
+ */
+ XsdAssertion::Ptr parseAssertion(const XsdSchemaToken::NodeName &nodeName, const XsdTagScope::Type &tag);
+
+ /**
+ * This method is called for parsing an <em>openContent</em> object.
+ */
+ XsdComplexType::OpenContent::Ptr parseOpenContent();
+
+ /**
+ * This method is called for parsing a top-level <em>group</em> object.
+ */
+ XsdModelGroup::Ptr parseNamedGroup();
+
+ /**
+ * This method is called for parsing a non-top-level <em>group</em> object
+ * that contains a <em>ref</em> attribute.
+ */
+ XsdTerm::Ptr parseReferredGroup(const XsdParticle::Ptr &particle);
+
+ /**
+ * This method is called for parsing an <em>all</em> object as child
+ * of a top-level <em>group</em> object.
+ *
+ * @param parent The schema component the <em>all</em> object is part of.
+ */
+ XsdModelGroup::Ptr parseAll(const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * This method is called for parsing an <em>all</em> object as descendant
+ * of a <em>complexType</em> object.
+ *
+ * @param particle The particle the <em>all</em> object belongs to.
+ * @param parent The schema component the <em>all</em> object is part of.
+ */
+ XsdModelGroup::Ptr parseLocalAll(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * This method is called for parsing a <em>choice</em> object as child
+ * of a top-level <em>group</em> object.
+ *
+ * @param parent The schema component the <em>choice</em> object is part of.
+ */
+ XsdModelGroup::Ptr parseChoice(const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * This method is called for parsing a <em>choice</em> object as descendant
+ * of a <em>complexType</em> object or a <em>choice</em> object.
+ *
+ * @param particle The particle the <em>choice</em> object belongs to.
+ * @param parent The schema component the <em>choice</em> object is part of.
+ */
+ XsdModelGroup::Ptr parseLocalChoice(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * This method is called for parsing a <em>sequence</em> object as child
+ * of a top-level <em>group</em> object.
+ *
+ * @param parent The schema component the <em>sequence</em> object is part of.
+ */
+ XsdModelGroup::Ptr parseSequence(const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * This method is called for parsing a <em>sequence</em> object as descendant
+ * of a <em>complexType</em> object or a <em>sequence</em> object.
+ *
+ * @param particle The particle the <em>sequence</em> object belongs to.
+ * @param parent The schema component the <em>sequence</em> object is part of.
+ */
+ XsdModelGroup::Ptr parseLocalSequence(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * A helper method that parses the minOccurs and maxOccurs constraints for
+ * the given @p particle that has the given @p tagName.
+ */
+ bool parseMinMaxConstraint(const XsdParticle::Ptr &particle, const char* tagName);
+
+ /**
+ * This method is called for parsing any top-level <em>attribute</em> object.
+ */
+ XsdAttribute::Ptr parseGlobalAttribute();
+
+ /**
+ * This method is called for parsing any non-top-level <em>attribute</em> object as a
+ * descendant of a <em>complexType</em> object or an <em>attributeGroup</em> object.
+ *
+ * @param parent The parent component the <em>attribute</em> object is part of.
+ */
+ XsdAttributeUse::Ptr parseLocalAttribute(const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * This method is called for parsing a top-level <em>attributeGroup</em> object.
+ */
+ XsdAttributeGroup::Ptr parseNamedAttributeGroup();
+
+ /**
+ * This method is called for parsing a non-top-level <em>attributeGroup</em> object
+ * that contains a <em>ref</em> attribute.
+ */
+ XsdAttributeUse::Ptr parseReferredAttributeGroup();
+
+ /**
+ * This method is called for parsing any top-level <em>element</em> object.
+ */
+ XsdElement::Ptr parseGlobalElement();
+
+ /**
+ * This method is called for parsing any non-top-level <em>element</em> object as a
+ * descendant of a <em>complexType</em> object or a <em>group</em> object.
+ *
+ * @param particle The particle the <em>element</em> object belongs to.
+ * @param parent The parent component the <em>element</em> object is part of.
+ */
+ XsdTerm::Ptr parseLocalElement(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent);
+
+ /**
+ * This method is called for parsing a <em>unique</em> object as child of an <em>element</em> object.
+ */
+ XsdIdentityConstraint::Ptr parseUnique();
+
+ /**
+ * This method is called for parsing a <em>key</em> object as child of an <em>element</em> object.
+ */
+ XsdIdentityConstraint::Ptr parseKey();
+
+ /**
+ * This method is called for parsing a <em>keyref</em> object as child of an <em>element</em> object.
+ */
+ XsdIdentityConstraint::Ptr parseKeyRef(const XsdElement::Ptr &element);
+
+ /**
+ * This method is called for parsing a <em>selector</em> object as child of an <em>unique</em> object,
+ * <em>key</em> object or <em>keyref</em> object,
+ *
+ * @param ptr The identity constraint it belongs to.
+ */
+ void parseSelector(const XsdIdentityConstraint::Ptr &ptr);
+
+ /**
+ * This method is called for parsing a <em>field</em> object as child of an <em>unique</em> object,
+ * <em>key</em> object or <em>keyref</em> object,
+ *
+ * @param ptr The identity constraint it belongs to.
+ */
+ void parseField(const XsdIdentityConstraint::Ptr &ptr);
+
+ /**
+ * This method is called for parsing an <em>alternative</em> object inside an <em>element</em> object.
+ */
+ XsdAlternative::Ptr parseAlternative();
+
+ /**
+ * This method is called for parsing a top-level <em>notation</em> object.
+ */
+ XsdNotation::Ptr parseNotation();
+
+ /**
+ * This method is called for parsing an <em>any</em> object somewhere in
+ * the schema.
+ *
+ * @param particle The particle the <em>any</em> object belongs to.
+ */
+ XsdWildcard::Ptr parseAny(const XsdParticle::Ptr &particle);
+
+ /**
+ * This method is called for parsing an <em>anyAttribute</em> object somewhere in
+ * the schema.
+ */
+ XsdWildcard::Ptr parseAnyAttribute();
+
+ /**
+ * This method is called for parsing unknown object as descendant of the <em>annotation</em> object.
+ */
+ void parseUnknownDocumentation();
+
+ /**
+ * This method is called for parsing unknown object in the schema.
+ */
+ void parseUnknown();
+
+ /**
+ * Returnes an source location for the current position.
+ */
+ QSourceLocation currentSourceLocation() const;
+
+ /**
+ * Converts a @p qualified name into a QXmlName @p name and does some error handling.
+ */
+ void convertName(const QString &qualified, NamespaceSupport::NameType type, QXmlName &name);
+
+ /**
+ * A helper method that reads in a 'name' attribute and checks it for syntactic errors.
+ */
+ inline QString readNameAttribute(const char *elementName);
+
+ /**
+ * A helper method that reads in an attribute that contains an QName and
+ * checks it for syntactic errors.
+ */
+ inline QString readQNameAttribute(const QString &typeAttribute, const char *elementName);
+
+ /**
+ * A helper method that reads in a namespace attribute and checks for syntactic errors.
+ */
+ inline QString readNamespaceAttribute(const QString &attributeName, const char *elementName);
+
+ /**
+ * A helper method that reads the final attribute and does correct handling of schema default definitions.
+ */
+ inline SchemaType::DerivationConstraints readDerivationConstraintAttribute(const SchemaType::DerivationConstraints &allowedConstraints, const char *elementName);
+
+ /**
+ * A helper method that reads the block attribute and does correct handling of schema default definitions.
+ */
+ inline NamedSchemaComponent::BlockingConstraints readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints &allowedConstraints, const char *elementName);
+
+ /**
+ * A helper method that reads all components for a xpath expression for the current scope.
+ */
+ XsdXPathExpression::Ptr readXPathExpression(const char *elementName);
+
+ /**
+ * Describes the type of XPath that is allowed by the readXPathAttribute method.
+ */
+ enum XPathType {
+ XPath20,
+ XPathSelector,
+ XPathField
+ };
+
+ /**
+ * A helper method that reads an attribute that represents a xpath query and does basic
+ * validation.
+ */
+ QString readXPathAttribute(const QString &attributeName, XPathType type, const char *elementName);
+
+ /**
+ * A helper method that reads in an "id" attribute, checks it for syntactic errors
+ * and tests whether a component with the same id has already been parsed.
+ */
+ inline void validateIdAttribute(const char *elementName);
+
+ /**
+ * Adds an @p element to the schema and checks for duplicated entries.
+ */
+ void addElement(const XsdElement::Ptr &element);
+
+ /**
+ * Adds an @p attribute to the schema and checks for duplicated entries.
+ */
+ void addAttribute(const XsdAttribute::Ptr &attribute);
+
+ /**
+ * Adds a @p type to the schema and checks for duplicated entries.
+ */
+ void addType(const SchemaType::Ptr &type);
+
+ /**
+ * Adds an anonymous @p type to the schema and checks for duplicated entries.
+ */
+ void addAnonymousType(const SchemaType::Ptr &type);
+
+ /**
+ * Adds an attribute @p group to the schema and checks for duplicated entries.
+ */
+ void addAttributeGroup(const XsdAttributeGroup::Ptr &group);
+
+ /**
+ * Adds an element @p group to the schema and checks for duplicated entries.
+ */
+ void addElementGroup(const XsdModelGroup::Ptr &group);
+
+ /**
+ * Adds a @p notation to the schema and checks for duplicated entries.
+ */
+ void addNotation(const XsdNotation::Ptr &notation);
+
+ /**
+ * Adds an identity @p constraint to the schema and checks for duplicated entries.
+ */
+ void addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint);
+
+ /**
+ * Adds the @p facet to the list of @p facets for @p type and checks for duplicates.
+ */
+ void addFacet(const XsdFacet::Ptr &facet, XsdFacet::Hash &facets, const SchemaType::Ptr &type);
+
+ /**
+ * Sets up the state machines for validating the right occurrence of xml elements.
+ */
+ void setupStateMachines();
+
+ /**
+ * Sets up a list of names of known builtin types.
+ */
+ void setupBuiltinTypeNames();
+
+ /**
+ * Checks whether the given @p tag is equal to the given @p token and
+ * the given @p namespaceToken is the XML Schema namespace.
+ */
+ inline bool isSchemaTag(XsdSchemaToken::NodeName tag, XsdSchemaToken::NodeName token, XsdSchemaToken::NodeName namespaceToken) const;
+
+ XsdSchemaContext::Ptr m_context;
+ XsdSchemaParserContext::Ptr m_parserContext;
+ NamePool::Ptr m_namePool;
+ NamespaceSupport m_namespaceSupport;
+ XsdSchemaResolver::Ptr m_schemaResolver;
+ XsdSchema::Ptr m_schema;
+
+ QString m_targetNamespace;
+ QString m_attributeFormDefault;
+ QString m_elementFormDefault;
+ QString m_blockDefault;
+ QString m_finalDefault;
+ QString m_xpathDefaultNamespace;
+ QXmlName m_defaultAttributes;
+ XsdComplexType::OpenContent::Ptr m_defaultOpenContent;
+ bool m_defaultOpenContentAppliesToEmpty;
+
+ NamespaceSet m_includedSchemas;
+ NamespaceSet m_importedSchemas;
+ NamespaceSet m_redefinedSchemas;
+ QUrl m_documentURI;
+ XsdIdCache::Ptr m_idCache;
+ QHash<XsdTagScope::Type, XsdStateMachine<XsdSchemaToken::NodeName> > m_stateMachines;
+ ComponentLocationHash m_componentLocationHash;
+ QSet<QXmlName> m_builtinTypeNames;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschemaparser_setup.cpp b/src/xmlpatterns/schema/qxsdschemaparser_setup.cpp
new file mode 100644
index 0000000000..167af7ab12
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemaparser_setup.cpp
@@ -0,0 +1,1070 @@
+
+#include "qxsdschemaparser_p.h"
+
+#include "qbuiltintypes_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+/**
+ * @page using_dfa_for_schema Using DFA for validation of correct XML tag occurrence
+ *
+ * This page describes how to use DFAs for validating that the XML child tags of an
+ * XML parent tag occur in the right order.
+ *
+ * To validate the occurence of XML tags one need a regular expression that describes
+ * which tags can appear how often in what context. For example the regular expression
+ * of the global <em>attribute</em> tag in XML Schema is (annotation?, simpleType?).
+ * That means the <em>attribute</em> tag can contain an <em>annotation</em> tag followed
+ * by a <em>simpleType</em> tag, or just one <em>simpleType</em> tag and even no child
+ * tag at all.
+ * So the regular expression describes some kind of language and all the various occurrences
+ * of the child tags can be seen as words of that language.
+ * We can create a DFA now, that accepts all words (and only these words) of that language
+ * and whenever we want to check if a sequence of child tags belongs to the language,
+ * we test if the sequence passes the DFA successfully.
+ *
+ * The following example shows how to create the DFA for the regular expression method
+ * above.
+ *
+ * \dotfile GlobalAttribute_diagram.dot
+ *
+ * At first we need a start state (1), that's the state the DFA is before it
+ * starts running. As our regular expression allows that there are no child tags, the
+ * start state is an end state as well (marked by the double circle).
+ * Now we fetch the first token from the XML file (let's assume it is an <em>annotation</em> tag)
+ * and check if there is an edge labled with the tag name leaving the current state of the DFA.
+ * If there is no such edge, the input doesn't fullfill the rules of the regular expression,
+ * so we throw an error. Otherwise we follow that edge and the DFA is set to the new state (2) the
+ * edge points to. Now we fetch the next token from the XML file and do the previous steps again.
+ * If there is no further input from the XML file, we check whether the DFA is in an end state and
+ * throw an error if not.
+ *
+ * So the algorithm for checking is quite simple, the whole logic is encoded in the DFA and creating
+ * one for a regular expression is sometimes not easy, however the ones for XML Schema are straight
+ * forward.
+ *
+ * <h2>Legend:</h2>
+ * \dotfile legend.dot
+ * <br>
+ *
+ * <h2>DFA for <em>all</em> tag</h2>
+ * \dotfile All_diagram.dot
+ * <br>
+ * <h2>DFA for <em>alternative</em> tag</h2>
+ * \dotfile Alternative_diagram.dot
+ * <br>
+ * <h2>DFA for <em>annotation</em> tag</h2>
+ * \dotfile Annotation_diagram.dot
+ * <br>
+ * <h2>DFA for <em>anyAttribute</em> tag</h2>
+ * \dotfile AnyAttribute_diagram.dot
+ * <br>
+ * <h2>DFA for <em>any</em> tag</h2>
+ * \dotfile Any_diagram.dot
+ * <br>
+ * <h2>DFA for <em>assert</em> tag</h2>
+ * \dotfile Assert_diagram.dot
+ * <br>
+ * <h2>DFA for <em>choice</em> tag</h2>
+ * \dotfile Choice_diagram.dot
+ * <br>
+ * <h2>DFA for <em>complexContent</em> tag</h2>
+ * \dotfile ComplexContent_diagram.dot
+ * <br>
+ * <h2>DFA for <em>extension</em> tag inside a <em>complexContent</em> tag</h2>
+ * \dotfile ComplexContentExtension_diagram.dot
+ * <br>
+ * <h2>DFA for <em>restriction</em> tag inside a <em>complexContent</em> tag</h2>
+ * \dotfile ComplexContentRestriction_diagram.dot
+ * <br>
+ * <h2>DFA for <em>defaultOpenContent</em> tag</h2>
+ * \dotfile DefaultOpenContent_diagram.dot
+ * <br>
+ * <h2>DFA for <em>enumeration</em> tag</h2>
+ * \dotfile EnumerationFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>field</em> tag</h2>
+ * \dotfile Field_diagram.dot
+ * <br>
+ * <h2>DFA for <em>fractionDigits</em> tag</h2>
+ * \dotfile FractionDigitsFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>attribute</em> tag</h2>
+ * \dotfile GlobalAttribute_diagram.dot
+ * <br>
+ * <h2>DFA for <em>complexType</em> tag</h2>
+ * \dotfile GlobalComplexType_diagram.dot
+ * <br>
+ * <h2>DFA for <em>element</em> tag</h2>
+ * \dotfile GlobalElement_diagram.dot
+ * <br>
+ * <h2>DFA for <em>simpleType</em> tag</h2>
+ * \dotfile GlobalSimpleType_diagram.dot
+ * <br>
+ * <h2>DFA for <em>import</em> tag</h2>
+ * \dotfile Import_diagram.dot
+ * <br>
+ * <h2>DFA for <em>include</em> tag</h2>
+ * \dotfile Include_diagram.dot
+ * <br>
+ * <h2>DFA for <em>key</em> tag</h2>
+ * \dotfile Key_diagram.dot
+ * <br>
+ * <h2>DFA for <em>keyref</em> tag</h2>
+ * \dotfile KeyRef_diagram.dot
+ * <br>
+ * <h2>DFA for <em>length</em> tag</h2>
+ * \dotfile LengthFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>list</em> tag</h2>
+ * \dotfile List_diagram.dot
+ * <br>
+ * <h2>DFA for <em>all</em> tag</h2>
+ * \dotfile LocalAll_diagram.dot
+ * <br>
+ * <h2>DFA for <em>attribute</em> tag</h2>
+ * \dotfile LocalAttribute_diagram.dot
+ * <br>
+ * <h2>DFA for <em>choice</em> tag</h2>
+ * \dotfile LocalChoice_diagram.dot
+ * <br>
+ * <h2>DFA for <em>complexType</em> tag</h2>
+ * \dotfile LocalComplexType_diagram.dot
+ * <br>
+ * <h2>DFA for <em>element</em> tag</h2>
+ * \dotfile LocalElement_diagram.dot
+ * <br>
+ * <h2>DFA for <em>sequence</em> tag</h2>
+ * \dotfile LocalSequence_diagram.dot
+ * <br>
+ * <h2>DFA for <em>simpleType</em> tag that </h2>
+ * \dotfile LocalSimpleType_diagram.dot
+ * <br>
+ * <h2>DFA for <em>maxExclusive</em> tag</h2>
+ * \dotfile MaxExclusiveFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>maxInclusive</em> tag</h2>
+ * \dotfile MaxInclusiveFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>maxLength</em> tag</h2>
+ * \dotfile MaxLengthFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>minExclusive</em> tag</h2>
+ * \dotfile MinExclusiveFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>minInclusive</em> tag</h2>
+ * \dotfile MinInclusiveFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>minLength</em> tag</h2>
+ * \dotfile MinLengthFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>attributeGroup</em> tag without <em>ref</em> attribute</h2>
+ * \dotfile NamedAttributeGroup_diagram.dot
+ * <br>
+ * <h2>DFA for <em>group</em> tag without <em>ref</em> attribute</h2>
+ * \dotfile NamedGroup_diagram.dot
+ * <br>
+ * <h2>DFA for <em>notation</em> tag</h2>
+ * \dotfile Notation_diagram.dot
+ * <br>
+ * <h2>DFA for <em>override</em> tag</h2>
+ * \dotfile Override_diagram.dot
+ * <br>
+ * <h2>DFA for <em>pattern</em> tag</h2>
+ * \dotfile PatternFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>redefine</em> tag</h2>
+ * \dotfile Redefine_diagram.dot
+ * <br>
+ * <h2>DFA for <em>attributeGroup</em> tag with <em>ref</em> attribute</h2>
+ * \dotfile ReferredAttributeGroup_diagram.dot
+ * <br>
+ * <h2>DFA for <em>group</em> tag with <em>ref</em> attribute</h2>
+ * \dotfile ReferredGroup_diagram.dot
+ * <br>
+ * <h2>DFA for <em>schema</em> tag</h2>
+ * \dotfile Schema_diagram.dot
+ * <br>
+ * <h2>DFA for <em>selector</em> tag</h2>
+ * \dotfile Selector_diagram.dot
+ * <br>
+ * <h2>DFA for <em>sequence</em> tag</h2>
+ * \dotfile Sequence_diagram.dot
+ * <br>
+ * <h2>DFA for <em>simpleContent</em> tag</h2>
+ * \dotfile SimpleContent_diagram.dot
+ * <br>
+ * <h2>DFA for <em>extension</em> tag inside a <em>simpleContent</em> tag</h2>
+ * \dotfile SimpleContentExtension_diagram.dot
+ * <br>
+ * <h2>DFA for <em>restriction</em> tag inside a <em>simpleContent</em> tag</h2>
+ * \dotfile SimpleContentRestriction_diagram.dot
+ * <br>
+ * <h2>DFA for <em>restriction</em> tag inside a <em>simpleType</em> tag</h2>
+ * \dotfile SimpleRestriction_diagram.dot
+ * <br>
+ * <h2>DFA for <em>totalDigits</em> tag</h2>
+ * \dotfile TotalDigitsFacet_diagram.dot
+ * <br>
+ * <h2>DFA for <em>union</em> tag</h2>
+ * \dotfile Union_diagram.dot
+ * <br>
+ * <h2>DFA for <em>unique</em> tag</h2>
+ * \dotfile Unique_diagram.dot
+ * <br>
+ * <h2>DFA for <em>whiteSpace</em> tag</h2>
+ * \dotfile WhiteSpaceFacet_diagram.dot
+ */
+
+void XsdSchemaParser::setupStateMachines()
+{
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, simpleType?) : attribute
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s2);
+
+ m_stateMachines.insert(XsdTagScope::GlobalAttribute, machine);
+ m_stateMachines.insert(XsdTagScope::LocalAttribute, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, ((simpleType | complexType)?, alternative*, (unique | key | keyref)*)) : element
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s3 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s4 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(startState, XsdSchemaToken::ComplexType, s2);
+ machine.addTransition(startState, XsdSchemaToken::Alternative, s3);
+ machine.addTransition(startState, XsdSchemaToken::Unique, s4);
+ machine.addTransition(startState, XsdSchemaToken::Key, s4);
+ machine.addTransition(startState, XsdSchemaToken::Keyref, s4);
+
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(s1, XsdSchemaToken::ComplexType, s2);
+ machine.addTransition(s1, XsdSchemaToken::Alternative, s3);
+ machine.addTransition(s1, XsdSchemaToken::Unique, s4);
+ machine.addTransition(s1, XsdSchemaToken::Key, s4);
+ machine.addTransition(s1, XsdSchemaToken::Keyref, s4);
+
+ machine.addTransition(s2, XsdSchemaToken::Alternative, s3);
+ machine.addTransition(s2, XsdSchemaToken::Unique, s4);
+ machine.addTransition(s2, XsdSchemaToken::Key, s4);
+ machine.addTransition(s2, XsdSchemaToken::Keyref, s4);
+
+ machine.addTransition(s3, XsdSchemaToken::Alternative, s3);
+ machine.addTransition(s3, XsdSchemaToken::Unique, s4);
+ machine.addTransition(s3, XsdSchemaToken::Key, s4);
+ machine.addTransition(s3, XsdSchemaToken::Keyref, s4);
+
+ machine.addTransition(s4, XsdSchemaToken::Unique, s4);
+ machine.addTransition(s4, XsdSchemaToken::Key, s4);
+ machine.addTransition(s4, XsdSchemaToken::Keyref, s4);
+
+ m_stateMachines.insert(XsdTagScope::GlobalElement, machine);
+ m_stateMachines.insert(XsdTagScope::LocalElement, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (simpleContent | complexContent | (openContent?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?), assert*))) : complexType
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s3 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s4 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s5 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s6 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s7 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleContent, s2);
+ machine.addTransition(startState, XsdSchemaToken::ComplexContent, s2);
+ machine.addTransition(startState, XsdSchemaToken::OpenContent, s3);
+ machine.addTransition(startState, XsdSchemaToken::Group, s4);
+ machine.addTransition(startState, XsdSchemaToken::All, s4);
+ machine.addTransition(startState, XsdSchemaToken::Choice, s4);
+ machine.addTransition(startState, XsdSchemaToken::Sequence, s4);
+ machine.addTransition(startState, XsdSchemaToken::Attribute, s5);
+ machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s5);
+ machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s6);
+ machine.addTransition(startState, XsdSchemaToken::Assert, s7);
+
+ machine.addTransition(s1, XsdSchemaToken::SimpleContent, s2);
+ machine.addTransition(s1, XsdSchemaToken::ComplexContent, s2);
+ machine.addTransition(s1, XsdSchemaToken::OpenContent, s3);
+ machine.addTransition(s1, XsdSchemaToken::Group, s4);
+ machine.addTransition(s1, XsdSchemaToken::All, s4);
+ machine.addTransition(s1, XsdSchemaToken::Choice, s4);
+ machine.addTransition(s1, XsdSchemaToken::Sequence, s4);
+ machine.addTransition(s1, XsdSchemaToken::Attribute, s5);
+ machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s5);
+ machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s6);
+ machine.addTransition(s1, XsdSchemaToken::Assert, s7);
+
+ machine.addTransition(s3, XsdSchemaToken::Group, s4);
+ machine.addTransition(s3, XsdSchemaToken::All, s4);
+ machine.addTransition(s3, XsdSchemaToken::Choice, s4);
+ machine.addTransition(s3, XsdSchemaToken::Sequence, s4);
+ machine.addTransition(s3, XsdSchemaToken::Attribute, s5);
+ machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s5);
+ machine.addTransition(s3, XsdSchemaToken::AnyAttribute, s6);
+ machine.addTransition(s3, XsdSchemaToken::Assert, s7);
+
+ machine.addTransition(s4, XsdSchemaToken::Attribute, s5);
+ machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s5);
+ machine.addTransition(s4, XsdSchemaToken::AnyAttribute, s6);
+ machine.addTransition(s4, XsdSchemaToken::Assert, s7);
+
+ machine.addTransition(s5, XsdSchemaToken::Attribute, s5);
+ machine.addTransition(s5, XsdSchemaToken::AttributeGroup, s5);
+ machine.addTransition(s5, XsdSchemaToken::AnyAttribute, s6);
+ machine.addTransition(s5, XsdSchemaToken::Assert, s7);
+
+ machine.addTransition(s6, XsdSchemaToken::Assert, s7);
+
+ machine.addTransition(s7, XsdSchemaToken::Assert, s7);
+
+ m_stateMachines.insert(XsdTagScope::GlobalComplexType, machine);
+ m_stateMachines.insert(XsdTagScope::LocalComplexType, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (restriction | extension)) : simpleContent/complexContent
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::InternalState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::Restriction, s2);
+ machine.addTransition(startState, XsdSchemaToken::Extension, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::Restriction, s2);
+ machine.addTransition(s1, XsdSchemaToken::Extension, s2);
+
+ m_stateMachines.insert(XsdTagScope::SimpleContent, machine);
+ m_stateMachines.insert(XsdTagScope::ComplexContent, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern | assertion)*)?, ((attribute | attributeGroup)*, anyAttribute?), assert*) : simpleContent restriction
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s3 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s4 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s5 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s6 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(startState, XsdSchemaToken::MinExclusive, s3);
+ machine.addTransition(startState, XsdSchemaToken::MinInclusive, s3);
+ machine.addTransition(startState, XsdSchemaToken::MaxExclusive, s3);
+ machine.addTransition(startState, XsdSchemaToken::MaxInclusive, s3);
+ machine.addTransition(startState, XsdSchemaToken::TotalDigits, s3);
+ machine.addTransition(startState, XsdSchemaToken::FractionDigits, s3);
+ machine.addTransition(startState, XsdSchemaToken::Length, s3);
+ machine.addTransition(startState, XsdSchemaToken::MinLength, s3);
+ machine.addTransition(startState, XsdSchemaToken::MaxLength, s3);
+ machine.addTransition(startState, XsdSchemaToken::Enumeration, s3);
+ machine.addTransition(startState, XsdSchemaToken::WhiteSpace, s3);
+ machine.addTransition(startState, XsdSchemaToken::Pattern, s3);
+ machine.addTransition(startState, XsdSchemaToken::Assertion, s3);
+ machine.addTransition(startState, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(startState, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(s1, XsdSchemaToken::MinExclusive, s3);
+ machine.addTransition(s1, XsdSchemaToken::MinInclusive, s3);
+ machine.addTransition(s1, XsdSchemaToken::MaxExclusive, s3);
+ machine.addTransition(s1, XsdSchemaToken::MaxInclusive, s3);
+ machine.addTransition(s1, XsdSchemaToken::TotalDigits, s3);
+ machine.addTransition(s1, XsdSchemaToken::FractionDigits, s3);
+ machine.addTransition(s1, XsdSchemaToken::Length, s3);
+ machine.addTransition(s1, XsdSchemaToken::MinLength, s3);
+ machine.addTransition(s1, XsdSchemaToken::MaxLength, s3);
+ machine.addTransition(s1, XsdSchemaToken::Enumeration, s3);
+ machine.addTransition(s1, XsdSchemaToken::WhiteSpace, s3);
+ machine.addTransition(s1, XsdSchemaToken::Pattern, s3);
+ machine.addTransition(s1, XsdSchemaToken::Assertion, s3);
+ machine.addTransition(s1, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(s1, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s2, XsdSchemaToken::MinExclusive, s3);
+ machine.addTransition(s2, XsdSchemaToken::MinInclusive, s3);
+ machine.addTransition(s2, XsdSchemaToken::MaxExclusive, s3);
+ machine.addTransition(s2, XsdSchemaToken::MaxInclusive, s3);
+ machine.addTransition(s2, XsdSchemaToken::TotalDigits, s3);
+ machine.addTransition(s2, XsdSchemaToken::FractionDigits, s3);
+ machine.addTransition(s2, XsdSchemaToken::Length, s3);
+ machine.addTransition(s2, XsdSchemaToken::MinLength, s3);
+ machine.addTransition(s2, XsdSchemaToken::MaxLength, s3);
+ machine.addTransition(s2, XsdSchemaToken::Enumeration, s3);
+ machine.addTransition(s2, XsdSchemaToken::WhiteSpace, s3);
+ machine.addTransition(s2, XsdSchemaToken::Pattern, s3);
+ machine.addTransition(s2, XsdSchemaToken::Assertion, s3);
+ machine.addTransition(s2, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(s2, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s3, XsdSchemaToken::MinExclusive, s3);
+ machine.addTransition(s3, XsdSchemaToken::MinInclusive, s3);
+ machine.addTransition(s3, XsdSchemaToken::MaxExclusive, s3);
+ machine.addTransition(s3, XsdSchemaToken::MaxInclusive, s3);
+ machine.addTransition(s3, XsdSchemaToken::TotalDigits, s3);
+ machine.addTransition(s3, XsdSchemaToken::FractionDigits, s3);
+ machine.addTransition(s3, XsdSchemaToken::Length, s3);
+ machine.addTransition(s3, XsdSchemaToken::MinLength, s3);
+ machine.addTransition(s3, XsdSchemaToken::MaxLength, s3);
+ machine.addTransition(s3, XsdSchemaToken::Enumeration, s3);
+ machine.addTransition(s3, XsdSchemaToken::WhiteSpace, s3);
+ machine.addTransition(s3, XsdSchemaToken::Pattern, s3);
+ machine.addTransition(s3, XsdSchemaToken::Assertion, s3);
+ machine.addTransition(s3, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s3, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(s3, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s4, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s4, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(s4, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s5, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s6, XsdSchemaToken::Assert, s6);
+
+ m_stateMachines.insert(XsdTagScope::SimpleContentRestriction, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, ((attribute | attributeGroup)*, anyAttribute?), assert*) : simple content extension
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s3 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s4 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::Attribute, s2);
+ machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s2);
+ machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s3);
+ machine.addTransition(startState, XsdSchemaToken::Assert, s4);
+
+ machine.addTransition(s1, XsdSchemaToken::Attribute, s2);
+ machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s2);
+ machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s3);
+ machine.addTransition(s1, XsdSchemaToken::Assert, s4);
+
+ machine.addTransition(s2, XsdSchemaToken::Attribute, s2);
+ machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s2);
+ machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s3);
+ machine.addTransition(s2, XsdSchemaToken::Assert, s4);
+
+ machine.addTransition(s3, XsdSchemaToken::Assert, s4);
+
+ machine.addTransition(s4, XsdSchemaToken::Assert, s4);
+
+ m_stateMachines.insert(XsdTagScope::SimpleContentExtension, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, openContent?, ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?), assert*)) : complex content restriction/complex content extension
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s3 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s4 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s5 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s6 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::OpenContent, s2);
+ machine.addTransition(startState, XsdSchemaToken::Group, s3);
+ machine.addTransition(startState, XsdSchemaToken::All, s3);
+ machine.addTransition(startState, XsdSchemaToken::Choice, s3);
+ machine.addTransition(startState, XsdSchemaToken::Sequence, s3);
+ machine.addTransition(startState, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(startState, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s1, XsdSchemaToken::OpenContent, s2);
+ machine.addTransition(s1, XsdSchemaToken::Group, s3);
+ machine.addTransition(s1, XsdSchemaToken::All, s3);
+ machine.addTransition(s1, XsdSchemaToken::Choice, s3);
+ machine.addTransition(s1, XsdSchemaToken::Sequence, s3);
+ machine.addTransition(s1, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(s1, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s2, XsdSchemaToken::Group, s3);
+ machine.addTransition(s2, XsdSchemaToken::All, s3);
+ machine.addTransition(s2, XsdSchemaToken::Choice, s3);
+ machine.addTransition(s2, XsdSchemaToken::Sequence, s3);
+ machine.addTransition(s2, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(s2, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s3, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s3, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(s3, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s4, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s4, XsdSchemaToken::AnyAttribute, s5);
+ machine.addTransition(s4, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s5, XsdSchemaToken::Assert, s6);
+
+ machine.addTransition(s6, XsdSchemaToken::Assert, s6);
+
+ m_stateMachines.insert(XsdTagScope::ComplexContentRestriction, machine);
+ m_stateMachines.insert(XsdTagScope::ComplexContentExtension, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, ((attribute | attributeGroup)*, anyAttribute?)) : named attribute group
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s3 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::Attribute, s2);
+ machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s2);
+ machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s3);
+
+ machine.addTransition(s1, XsdSchemaToken::Attribute, s2);
+ machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s2);
+ machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s3);
+
+ machine.addTransition(s2, XsdSchemaToken::Attribute, s2);
+ machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s2);
+ machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s3);
+
+ m_stateMachines.insert(XsdTagScope::NamedAttributeGroup, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (all | choice | sequence)?) : group
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::All, s2);
+ machine.addTransition(startState, XsdSchemaToken::Choice, s2);
+ machine.addTransition(startState, XsdSchemaToken::Sequence, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::All, s2);
+ machine.addTransition(s1, XsdSchemaToken::Choice, s2);
+ machine.addTransition(s1, XsdSchemaToken::Sequence, s2);
+
+ m_stateMachines.insert(XsdTagScope::NamedGroup, machine);
+ m_stateMachines.insert(XsdTagScope::ReferredGroup, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (element | any)*) : all
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::Element, s2);
+ machine.addTransition(startState, XsdSchemaToken::Any, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::Element, s2);
+ machine.addTransition(s1, XsdSchemaToken::Any, s2);
+
+ machine.addTransition(s2, XsdSchemaToken::Element, s2);
+ machine.addTransition(s2, XsdSchemaToken::Any, s2);
+
+ m_stateMachines.insert(XsdTagScope::All, machine);
+ m_stateMachines.insert(XsdTagScope::LocalAll, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (element | group | choice | sequence | any)*) : choice sequence
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::Element, s2);
+ machine.addTransition(startState, XsdSchemaToken::Group, s2);
+ machine.addTransition(startState, XsdSchemaToken::Choice, s2);
+ machine.addTransition(startState, XsdSchemaToken::Sequence, s2);
+ machine.addTransition(startState, XsdSchemaToken::Any, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::Element, s2);
+ machine.addTransition(s1, XsdSchemaToken::Group, s2);
+ machine.addTransition(s1, XsdSchemaToken::Choice, s2);
+ machine.addTransition(s1, XsdSchemaToken::Sequence, s2);
+ machine.addTransition(s1, XsdSchemaToken::Any, s2);
+
+ machine.addTransition(s2, XsdSchemaToken::Element, s2);
+ machine.addTransition(s2, XsdSchemaToken::Group, s2);
+ machine.addTransition(s2, XsdSchemaToken::Choice, s2);
+ machine.addTransition(s2, XsdSchemaToken::Sequence, s2);
+ machine.addTransition(s2, XsdSchemaToken::Any, s2);
+
+ m_stateMachines.insert(XsdTagScope::Choice, machine);
+ m_stateMachines.insert(XsdTagScope::LocalChoice, machine);
+ m_stateMachines.insert(XsdTagScope::Sequence, machine);
+ m_stateMachines.insert(XsdTagScope::LocalSequence, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?) : any/selector/field/notation/include/import/referred attribute group/anyAttribute/all facets/assert
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+
+ m_stateMachines.insert(XsdTagScope::Any, machine);
+ m_stateMachines.insert(XsdTagScope::Selector, machine);
+ m_stateMachines.insert(XsdTagScope::Field, machine);
+ m_stateMachines.insert(XsdTagScope::Notation, machine);
+ m_stateMachines.insert(XsdTagScope::Include, machine);
+ m_stateMachines.insert(XsdTagScope::Import, machine);
+ m_stateMachines.insert(XsdTagScope::ReferredAttributeGroup, machine);
+ m_stateMachines.insert(XsdTagScope::AnyAttribute, machine);
+ m_stateMachines.insert(XsdTagScope::MinExclusiveFacet, machine);
+ m_stateMachines.insert(XsdTagScope::MinInclusiveFacet, machine);
+ m_stateMachines.insert(XsdTagScope::MaxExclusiveFacet, machine);
+ m_stateMachines.insert(XsdTagScope::MaxInclusiveFacet, machine);
+ m_stateMachines.insert(XsdTagScope::TotalDigitsFacet, machine);
+ m_stateMachines.insert(XsdTagScope::FractionDigitsFacet, machine);
+ m_stateMachines.insert(XsdTagScope::LengthFacet, machine);
+ m_stateMachines.insert(XsdTagScope::MinLengthFacet, machine);
+ m_stateMachines.insert(XsdTagScope::MaxLengthFacet, machine);
+ m_stateMachines.insert(XsdTagScope::EnumerationFacet, machine);
+ m_stateMachines.insert(XsdTagScope::WhiteSpaceFacet, machine);
+ m_stateMachines.insert(XsdTagScope::PatternFacet, machine);
+ m_stateMachines.insert(XsdTagScope::Assert, machine);
+ m_stateMachines.insert(XsdTagScope::Assertion, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (selector, field+)) : unique/key/keyref
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::InternalState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::InternalState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s3 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::Selector, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::Selector, s2);
+ machine.addTransition(s2, XsdSchemaToken::Field, s3);
+ machine.addTransition(s3, XsdSchemaToken::Field, s3);
+
+ m_stateMachines.insert(XsdTagScope::Unique, machine);
+ m_stateMachines.insert(XsdTagScope::Key, machine);
+ m_stateMachines.insert(XsdTagScope::KeyRef, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (simpleType | complexType)?) : alternative
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(startState, XsdSchemaToken::ComplexType, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(s1, XsdSchemaToken::ComplexType, s2);
+
+ m_stateMachines.insert(XsdTagScope::Alternative, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (appinfo | documentation)* : annotation
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Appinfo, s1);
+ machine.addTransition(startState, XsdSchemaToken::Documentation, s1);
+
+ machine.addTransition(s1, XsdSchemaToken::Appinfo, s1);
+ machine.addTransition(s1, XsdSchemaToken::Documentation, s1);
+
+ m_stateMachines.insert(XsdTagScope::Annotation, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (restriction | list | union)) : simpleType
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::InternalState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::Restriction, s2);
+ machine.addTransition(startState, XsdSchemaToken::List, s2);
+ machine.addTransition(startState, XsdSchemaToken::Union, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::Restriction, s2);
+ machine.addTransition(s1, XsdSchemaToken::List, s2);
+ machine.addTransition(s1, XsdSchemaToken::Union, s2);
+
+ m_stateMachines.insert(XsdTagScope::GlobalSimpleType, machine);
+ m_stateMachines.insert(XsdTagScope::LocalSimpleType, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern | assertion)*)) : simple type restriction
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s3 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(startState, XsdSchemaToken::MinExclusive, s3);
+ machine.addTransition(startState, XsdSchemaToken::MinInclusive, s3);
+ machine.addTransition(startState, XsdSchemaToken::MaxExclusive, s3);
+ machine.addTransition(startState, XsdSchemaToken::MaxInclusive, s3);
+ machine.addTransition(startState, XsdSchemaToken::TotalDigits, s3);
+ machine.addTransition(startState, XsdSchemaToken::FractionDigits, s3);
+ machine.addTransition(startState, XsdSchemaToken::Length, s3);
+ machine.addTransition(startState, XsdSchemaToken::MinLength, s3);
+ machine.addTransition(startState, XsdSchemaToken::MaxLength, s3);
+ machine.addTransition(startState, XsdSchemaToken::Enumeration, s3);
+ machine.addTransition(startState, XsdSchemaToken::WhiteSpace, s3);
+ machine.addTransition(startState, XsdSchemaToken::Pattern, s3);
+ machine.addTransition(startState, XsdSchemaToken::Assertion, s3);
+
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(s1, XsdSchemaToken::MinExclusive, s3);
+ machine.addTransition(s1, XsdSchemaToken::MinInclusive, s3);
+ machine.addTransition(s1, XsdSchemaToken::MaxExclusive, s3);
+ machine.addTransition(s1, XsdSchemaToken::MaxInclusive, s3);
+ machine.addTransition(s1, XsdSchemaToken::TotalDigits, s3);
+ machine.addTransition(s1, XsdSchemaToken::FractionDigits, s3);
+ machine.addTransition(s1, XsdSchemaToken::Length, s3);
+ machine.addTransition(s1, XsdSchemaToken::MinLength, s3);
+ machine.addTransition(s1, XsdSchemaToken::MaxLength, s3);
+ machine.addTransition(s1, XsdSchemaToken::Enumeration, s3);
+ machine.addTransition(s1, XsdSchemaToken::WhiteSpace, s3);
+ machine.addTransition(s1, XsdSchemaToken::Pattern, s3);
+ machine.addTransition(s1, XsdSchemaToken::Assertion, s3);
+
+ machine.addTransition(s2, XsdSchemaToken::MinExclusive, s3);
+ machine.addTransition(s2, XsdSchemaToken::MinInclusive, s3);
+ machine.addTransition(s2, XsdSchemaToken::MaxExclusive, s3);
+ machine.addTransition(s2, XsdSchemaToken::MaxInclusive, s3);
+ machine.addTransition(s2, XsdSchemaToken::TotalDigits, s3);
+ machine.addTransition(s2, XsdSchemaToken::FractionDigits, s3);
+ machine.addTransition(s2, XsdSchemaToken::Length, s3);
+ machine.addTransition(s2, XsdSchemaToken::MinLength, s3);
+ machine.addTransition(s2, XsdSchemaToken::MaxLength, s3);
+ machine.addTransition(s2, XsdSchemaToken::Enumeration, s3);
+ machine.addTransition(s2, XsdSchemaToken::WhiteSpace, s3);
+ machine.addTransition(s2, XsdSchemaToken::Pattern, s3);
+ machine.addTransition(s2, XsdSchemaToken::Assertion, s3);
+
+ machine.addTransition(s3, XsdSchemaToken::MinExclusive, s3);
+ machine.addTransition(s3, XsdSchemaToken::MinInclusive, s3);
+ machine.addTransition(s3, XsdSchemaToken::MaxExclusive, s3);
+ machine.addTransition(s3, XsdSchemaToken::MaxInclusive, s3);
+ machine.addTransition(s3, XsdSchemaToken::TotalDigits, s3);
+ machine.addTransition(s3, XsdSchemaToken::FractionDigits, s3);
+ machine.addTransition(s3, XsdSchemaToken::Length, s3);
+ machine.addTransition(s3, XsdSchemaToken::MinLength, s3);
+ machine.addTransition(s3, XsdSchemaToken::MaxLength, s3);
+ machine.addTransition(s3, XsdSchemaToken::Enumeration, s3);
+ machine.addTransition(s3, XsdSchemaToken::WhiteSpace, s3);
+ machine.addTransition(s3, XsdSchemaToken::Pattern, s3);
+ machine.addTransition(s3, XsdSchemaToken::Assertion, s3);
+
+ m_stateMachines.insert(XsdTagScope::SimpleRestriction, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, simpleType?) : list
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s2);
+
+ m_stateMachines.insert(XsdTagScope::List, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, simpleType*) : union
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s2);
+ machine.addTransition(s2, XsdSchemaToken::SimpleType, s2);
+
+ m_stateMachines.insert(XsdTagScope::Union, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for ((include | import | redefine |i override | annotation)*, (defaultOpenContent, annotation*)?, (((simpleType | complexType | group | attributeGroup) | element | attribute | notation), annotation*)*) : schema
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s3 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s4 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s5 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Include, s1);
+ machine.addTransition(startState, XsdSchemaToken::Import, s1);
+ machine.addTransition(startState, XsdSchemaToken::Redefine, s1);
+ machine.addTransition(startState, XsdSchemaToken::Override, s1);
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::DefaultOpenContent, s2);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s4);
+ machine.addTransition(startState, XsdSchemaToken::ComplexType, s4);
+ machine.addTransition(startState, XsdSchemaToken::Group, s4);
+ machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(startState, XsdSchemaToken::Element, s4);
+ machine.addTransition(startState, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(startState, XsdSchemaToken::Notation, s4);
+
+ machine.addTransition(s1, XsdSchemaToken::Include, s1);
+ machine.addTransition(s1, XsdSchemaToken::Import, s1);
+ machine.addTransition(s1, XsdSchemaToken::Redefine, s1);
+ machine.addTransition(s1, XsdSchemaToken::Override, s1);
+ machine.addTransition(s1, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(s1, XsdSchemaToken::DefaultOpenContent, s2);
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s4);
+ machine.addTransition(s1, XsdSchemaToken::ComplexType, s4);
+ machine.addTransition(s1, XsdSchemaToken::Group, s4);
+ machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s1, XsdSchemaToken::Element, s4);
+ machine.addTransition(s1, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s1, XsdSchemaToken::Notation, s4);
+
+ machine.addTransition(s2, XsdSchemaToken::Annotation, s3);
+ machine.addTransition(s2, XsdSchemaToken::SimpleType, s4);
+ machine.addTransition(s2, XsdSchemaToken::ComplexType, s4);
+ machine.addTransition(s2, XsdSchemaToken::Group, s4);
+ machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s2, XsdSchemaToken::Element, s4);
+ machine.addTransition(s2, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s2, XsdSchemaToken::Notation, s4);
+
+ machine.addTransition(s3, XsdSchemaToken::SimpleType, s4);
+ machine.addTransition(s3, XsdSchemaToken::ComplexType, s4);
+ machine.addTransition(s3, XsdSchemaToken::Group, s4);
+ machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s3, XsdSchemaToken::Element, s4);
+ machine.addTransition(s3, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s3, XsdSchemaToken::Notation, s4);
+
+ machine.addTransition(s4, XsdSchemaToken::SimpleType, s4);
+ machine.addTransition(s4, XsdSchemaToken::ComplexType, s4);
+ machine.addTransition(s4, XsdSchemaToken::Group, s4);
+ machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s4, XsdSchemaToken::Element, s4);
+ machine.addTransition(s4, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s4, XsdSchemaToken::Notation, s4);
+ machine.addTransition(s4, XsdSchemaToken::Annotation, s5);
+
+ machine.addTransition(s5, XsdSchemaToken::SimpleType, s4);
+ machine.addTransition(s5, XsdSchemaToken::ComplexType, s4);
+ machine.addTransition(s5, XsdSchemaToken::Group, s4);
+ machine.addTransition(s5, XsdSchemaToken::AttributeGroup, s4);
+ machine.addTransition(s5, XsdSchemaToken::Element, s4);
+ machine.addTransition(s5, XsdSchemaToken::Attribute, s4);
+ machine.addTransition(s5, XsdSchemaToken::Notation, s4);
+ machine.addTransition(s5, XsdSchemaToken::Annotation, s5);
+
+ m_stateMachines.insert(XsdTagScope::Schema, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation?, any) : defaultOpenContent
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::InternalState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s2 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::Any, s2);
+
+ machine.addTransition(s1, XsdSchemaToken::Any, s2);
+
+ m_stateMachines.insert(XsdTagScope::DefaultOpenContent, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation | (simpleType | complexType | group | attributeGroup))* : redefine
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s1);
+ machine.addTransition(startState, XsdSchemaToken::ComplexType, s1);
+ machine.addTransition(startState, XsdSchemaToken::Group, s1);
+ machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s1);
+
+ machine.addTransition(s1, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s1);
+ machine.addTransition(s1, XsdSchemaToken::ComplexType, s1);
+ machine.addTransition(s1, XsdSchemaToken::Group, s1);
+ machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s1);
+
+ m_stateMachines.insert(XsdTagScope::Redefine, machine);
+ }
+
+ {
+ XsdStateMachine<XsdSchemaToken::NodeName> machine(m_namePool);
+
+ // setup state machine for (annotation | (simpleType | complexType | group | attributeGroup | element | attribute | notation))* : override
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId startState = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::StartEndState);
+ const XsdStateMachine<XsdSchemaToken::NodeName>::StateId s1 = machine.addState(XsdStateMachine<XsdSchemaToken::NodeName>::EndState);
+
+ machine.addTransition(startState, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(startState, XsdSchemaToken::SimpleType, s1);
+ machine.addTransition(startState, XsdSchemaToken::ComplexType, s1);
+ machine.addTransition(startState, XsdSchemaToken::Group, s1);
+ machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s1);
+ machine.addTransition(startState, XsdSchemaToken::Element, s1);
+ machine.addTransition(startState, XsdSchemaToken::Attribute, s1);
+ machine.addTransition(startState, XsdSchemaToken::Notation, s1);
+
+ machine.addTransition(s1, XsdSchemaToken::Annotation, s1);
+ machine.addTransition(s1, XsdSchemaToken::SimpleType, s1);
+ machine.addTransition(s1, XsdSchemaToken::ComplexType, s1);
+ machine.addTransition(s1, XsdSchemaToken::Group, s1);
+ machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s1);
+ machine.addTransition(s1, XsdSchemaToken::Element, s1);
+ machine.addTransition(s1, XsdSchemaToken::Attribute, s1);
+ machine.addTransition(s1, XsdSchemaToken::Notation, s1);
+
+ m_stateMachines.insert(XsdTagScope::Override, machine);
+ }
+}
+
+void XsdSchemaParser::setupBuiltinTypeNames()
+{
+ m_builtinTypeNames.reserve(48);
+
+ m_builtinTypeNames.insert(BuiltinTypes::xsAnyType->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsAnySimpleType->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsUntyped->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsAnyAtomicType->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsUntypedAtomic->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsDateTime->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsDate->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsTime->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsDuration->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsYearMonthDuration->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsDayTimeDuration->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsFloat->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsDouble->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsInteger->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsDecimal->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsNonPositiveInteger->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsNegativeInteger->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsLong->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsInt->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsShort->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsByte->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsNonNegativeInteger->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsUnsignedLong->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsUnsignedInt->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsUnsignedShort->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsUnsignedByte->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsPositiveInteger->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsGYearMonth->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsGYear->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsGMonthDay->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsGDay->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsGMonth->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsBoolean->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsBase64Binary->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsHexBinary->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsAnyURI->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsQName->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsString->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsNormalizedString->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsToken->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsLanguage->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsNMTOKEN->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsName->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsNCName->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsID->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsIDREF->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsENTITY->name(m_namePool));
+ m_builtinTypeNames.insert(BuiltinTypes::xsNOTATION->name(m_namePool));
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp b/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp
new file mode 100644
index 0000000000..896619ecd3
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp
@@ -0,0 +1,573 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdschemaparsercontext_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchemaParserContext::XsdSchemaParserContext(const NamePool::Ptr &namePool, const XsdSchemaContext::Ptr &context)
+ : m_namePool(namePool)
+ , m_schema(new XsdSchema(m_namePool))
+ , m_checker(new XsdSchemaChecker(context, this))
+ , m_resolver(new XsdSchemaResolver(context, this))
+ , m_elementDescriptions(setupElementDescriptions())
+{
+}
+
+NamePool::Ptr XsdSchemaParserContext::namePool() const
+{
+ return m_namePool;
+}
+
+XsdSchemaResolver::Ptr XsdSchemaParserContext::resolver() const
+{
+ return m_resolver;
+}
+
+XsdSchemaChecker::Ptr XsdSchemaParserContext::checker() const
+{
+ return m_checker;
+}
+
+XsdSchema::Ptr XsdSchemaParserContext::schema() const
+{
+ return m_schema;
+}
+
+ElementDescription<XsdSchemaToken, XsdTagScope::Type>::Hash XsdSchemaParserContext::elementDescriptions() const
+{
+ return m_elementDescriptions;
+}
+
+QXmlName XsdSchemaParserContext::createAnonymousName(const QString &targetNamespace) const
+{
+ m_anonymousNameCounter.ref();
+
+ const QString name = QString::fromLatin1("__AnonymousClass_%1").arg((int)m_anonymousNameCounter);
+
+ return m_namePool->allocateQName(targetNamespace, name);
+}
+
+ElementDescription<XsdSchemaToken, XsdTagScope::Type>::Hash XsdSchemaParserContext::setupElementDescriptions()
+{
+ enum
+ {
+ ReservedForElements = 60
+ };
+
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type>::Hash elementDescriptions;
+ elementDescriptions.reserve(ReservedForElements);
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Schema];
+ description.optionalAttributes.reserve(10);
+ //description.tagToken = XsdSchemaToken::Schema;
+ description.optionalAttributes.insert(XsdSchemaToken::AttributeFormDefault);
+ description.optionalAttributes.insert(XsdSchemaToken::BlockDefault);
+ description.optionalAttributes.insert(XsdSchemaToken::DefaultAttributes);
+ description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace);
+ description.optionalAttributes.insert(XsdSchemaToken::ElementFormDefault);
+ description.optionalAttributes.insert(XsdSchemaToken::FinalDefault);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::TargetNamespace);
+ description.optionalAttributes.insert(XsdSchemaToken::Version);
+ description.optionalAttributes.insert(XsdSchemaToken::XmlLanguage);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Include];
+ //description.tagToken = XsdSchemaToken::Include;
+ description.requiredAttributes.insert(XsdSchemaToken::SchemaLocation);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Import];
+ //description.tagToken = XsdSchemaToken::Import;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::Namespace);
+ description.optionalAttributes.insert(XsdSchemaToken::SchemaLocation);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Redefine];
+ //description.tagToken = XsdSchemaToken::Redefine;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::SchemaLocation);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Override];
+ //description.tagToken = XsdSchemaToken::Override;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::SchemaLocation);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Annotation];
+ //description.tagToken = XsdSchemaToken::Annotation;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::AppInfo];
+ //description.tagToken = XsdSchemaToken::Appinfo;
+ description.optionalAttributes.insert(XsdSchemaToken::Source);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Documentation];
+ //description.tagToken = XsdSchemaToken::Documentation;
+ description.optionalAttributes.insert(XsdSchemaToken::Source);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::GlobalSimpleType];
+ //description.tagToken = XsdSchemaToken::SimpleType;
+ description.optionalAttributes.insert(XsdSchemaToken::Final);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::LocalSimpleType];
+ //description.tagToken = XsdSchemaToken::SimpleType;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::SimpleRestriction];
+ //description.tagToken = XsdSchemaToken::Restriction;
+ description.optionalAttributes.insert(XsdSchemaToken::Base);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::List];
+ //description.tagToken = XsdSchemaToken::List;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::ItemType);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Union];
+ //description.tagToken = XsdSchemaToken::Union;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::MemberTypes);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::MinExclusiveFacet];
+ //description.tagToken = XsdSchemaToken::MinExclusive;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::MinInclusiveFacet];
+ //description.tagToken = XsdSchemaToken::MinInclusive;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::MaxExclusiveFacet];
+ //description.tagToken = XsdSchemaToken::MaxExclusive;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::MaxInclusiveFacet];
+ //description.tagToken = XsdSchemaToken::MaxInclusive;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::TotalDigitsFacet];
+ //description.tagToken = XsdSchemaToken::TotalDigits;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::FractionDigitsFacet];
+ //description.tagToken = XsdSchemaToken::FractionDigits;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::LengthFacet];
+ //description.tagToken = XsdSchemaToken::Length;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::MinLengthFacet];
+ //description.tagToken = XsdSchemaToken::MinLength;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::MaxLengthFacet];
+ //description.tagToken = XsdSchemaToken::MaxLength;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::EnumerationFacet];
+ //description.tagToken = XsdSchemaToken::Enumeration;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::WhiteSpaceFacet];
+ //description.tagToken = XsdSchemaToken::WhiteSpace;
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::PatternFacet];
+ //description.tagToken = XsdSchemaToken::Pattern;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Value);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::GlobalComplexType];
+ description.optionalAttributes.reserve(7);
+ //description.tagToken = XsdSchemaToken::ComplexType;
+ description.optionalAttributes.insert(XsdSchemaToken::Abstract);
+ description.optionalAttributes.insert(XsdSchemaToken::Block);
+ description.optionalAttributes.insert(XsdSchemaToken::DefaultAttributesApply);
+ description.optionalAttributes.insert(XsdSchemaToken::Final);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::Mixed);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::LocalComplexType];
+ //description.tagToken = XsdSchemaToken::ComplexType;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::Mixed);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::SimpleContent];
+ //description.tagToken = XsdSchemaToken::SimpleContent;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::SimpleContentRestriction];
+ //description.tagToken = XsdSchemaToken::Restriction;
+ description.requiredAttributes.insert(XsdSchemaToken::Base);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::SimpleContentExtension];
+ //description.tagToken = XsdSchemaToken::Extension;
+ description.requiredAttributes.insert(XsdSchemaToken::Base);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::ComplexContent];
+ //description.tagToken = XsdSchemaToken::ComplexContent;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::Mixed);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::ComplexContentRestriction];
+ //description.tagToken = XsdSchemaToken::Restriction;
+ description.requiredAttributes.insert(XsdSchemaToken::Base);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::ComplexContentExtension];
+ //description.tagToken = XsdSchemaToken::Extension;
+ description.requiredAttributes.insert(XsdSchemaToken::Base);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::NamedGroup];
+ //description.tagToken = XsdSchemaToken::Group;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::ReferredGroup];
+ description.optionalAttributes.reserve(4);
+ //description.tagToken = XsdSchemaToken::Group;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs);
+ description.optionalAttributes.insert(XsdSchemaToken::MinOccurs);
+ description.requiredAttributes.insert(XsdSchemaToken::Ref);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::All];
+ //description.tagToken = XsdSchemaToken::All;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::LocalAll];
+ //description.tagToken = XsdSchemaToken::All;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs);
+ description.optionalAttributes.insert(XsdSchemaToken::MinOccurs);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Choice];
+ //description.tagToken = XsdSchemaToken::Choice;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::LocalChoice];
+ //description.tagToken = XsdSchemaToken::Choice;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs);
+ description.optionalAttributes.insert(XsdSchemaToken::MinOccurs);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Sequence];
+ //description.tagToken = XsdSchemaToken::Sequence;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::LocalSequence];
+ //description.tagToken = XsdSchemaToken::Sequence;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs);
+ description.optionalAttributes.insert(XsdSchemaToken::MinOccurs);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::GlobalAttribute];
+ description.optionalAttributes.reserve(5);
+ //description.tagToken = XsdSchemaToken::Attribute;
+ description.optionalAttributes.insert(XsdSchemaToken::Default);
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ description.optionalAttributes.insert(XsdSchemaToken::Type);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::LocalAttribute];
+ description.optionalAttributes.reserve(8);
+ //description.tagToken = XsdSchemaToken::Attribute;
+ description.optionalAttributes.insert(XsdSchemaToken::Default);
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Form);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::Name);
+ description.optionalAttributes.insert(XsdSchemaToken::Ref);
+ description.optionalAttributes.insert(XsdSchemaToken::Type);
+ description.optionalAttributes.insert(XsdSchemaToken::Use);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::NamedAttributeGroup];
+ //description.tagToken = XsdSchemaToken::AttributeGroup;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::ReferredAttributeGroup];
+ //description.tagToken = XsdSchemaToken::AttributeGroup;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Ref);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::LocalElement];
+ description.optionalAttributes.reserve(11);
+ //description.tagToken = XsdSchemaToken::Element;
+ description.optionalAttributes.insert(XsdSchemaToken::Block);
+ description.optionalAttributes.insert(XsdSchemaToken::Default);
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Form);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::MinOccurs);
+ description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs);
+ description.optionalAttributes.insert(XsdSchemaToken::Name);
+ description.optionalAttributes.insert(XsdSchemaToken::Nillable);
+ description.optionalAttributes.insert(XsdSchemaToken::Ref);
+ description.optionalAttributes.insert(XsdSchemaToken::Type);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::GlobalElement];
+ description.optionalAttributes.reserve(10);
+ //description.tagToken = XsdSchemaToken::Element;
+ description.optionalAttributes.insert(XsdSchemaToken::Abstract);
+ description.optionalAttributes.insert(XsdSchemaToken::Block);
+ description.optionalAttributes.insert(XsdSchemaToken::Default);
+ description.optionalAttributes.insert(XsdSchemaToken::Final);
+ description.optionalAttributes.insert(XsdSchemaToken::Fixed);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ description.optionalAttributes.insert(XsdSchemaToken::Nillable);
+ description.optionalAttributes.insert(XsdSchemaToken::SubstitutionGroup);
+ description.optionalAttributes.insert(XsdSchemaToken::Type);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Unique];
+ //description.tagToken = XsdSchemaToken::Unique;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Key];
+ //description.tagToken = XsdSchemaToken::Key;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::KeyRef];
+ //description.tagToken = XsdSchemaToken::Keyref;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ description.requiredAttributes.insert(XsdSchemaToken::Refer);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Selector];
+ //description.tagToken = XsdSchemaToken::Selector;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Xpath);
+ description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Field];
+ //description.tagToken = XsdSchemaToken::Field;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Xpath);
+ description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Notation];
+ description.optionalAttributes.reserve(4);
+ //description.tagToken = XsdSchemaToken::Notation;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Name);
+ description.optionalAttributes.insert(XsdSchemaToken::Public);
+ description.optionalAttributes.insert(XsdSchemaToken::System);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Any];
+ description.optionalAttributes.reserve(7);
+ //description.tagToken = XsdSchemaToken::Any;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs);
+ description.optionalAttributes.insert(XsdSchemaToken::MinOccurs);
+ description.optionalAttributes.insert(XsdSchemaToken::Namespace);
+ description.optionalAttributes.insert(XsdSchemaToken::NotNamespace);
+ description.optionalAttributes.insert(XsdSchemaToken::NotQName);
+ description.optionalAttributes.insert(XsdSchemaToken::ProcessContents);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::AnyAttribute];
+ description.optionalAttributes.reserve(5);
+ //description.tagToken = XsdSchemaToken::AnyAttribute;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::Namespace);
+ description.optionalAttributes.insert(XsdSchemaToken::NotNamespace);
+ description.optionalAttributes.insert(XsdSchemaToken::NotQName);
+ description.optionalAttributes.insert(XsdSchemaToken::ProcessContents);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Alternative];
+ //description.tagToken = XsdSchemaToken::Alternative;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::Test);
+ description.optionalAttributes.insert(XsdSchemaToken::Type);
+ description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::OpenContent];
+ //description.tagToken = XsdSchemaToken::OpenContent;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::Mode);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::DefaultOpenContent];
+ //description.tagToken = XsdSchemaToken::DefaultOpenContent;
+ description.optionalAttributes.insert(XsdSchemaToken::AppliesToEmpty);
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.optionalAttributes.insert(XsdSchemaToken::Mode);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Assert];
+ //description.tagToken = XsdSchemaToken::Assert;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Test);
+ description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace);
+ }
+
+ {
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type> &description = elementDescriptions[XsdTagScope::Assertion];
+ //description.tagToken = XsdSchemaToken::Assertion;
+ description.optionalAttributes.insert(XsdSchemaToken::Id);
+ description.requiredAttributes.insert(XsdSchemaToken::Test);
+ description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace);
+ }
+
+ Q_ASSERT_X(elementDescriptions.count() == ReservedForElements, Q_FUNC_INFO,
+ qPrintable(QString::fromLatin1("Expected is %1, actual is %2.").arg(ReservedForElements).arg(elementDescriptions.count())));
+
+ return elementDescriptions;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h b/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h
new file mode 100644
index 0000000000..616aff318d
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h
@@ -0,0 +1,201 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchemaParserContext_H
+#define Patternist_XsdSchemaParserContext_H
+
+#include "qmaintainingreader_p.h" // for definition of ElementDescription
+#include "qxsdschematoken_p.h"
+#include "qxsdschema_p.h"
+#include "qxsdschemachecker_p.h"
+#include "qxsdschemacontext_p.h"
+#include "qxsdschemaresolver_p.h"
+
+#include <QtCore/QSharedData>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A namespace class that contains identifiers for the different
+ * scopes a tag from the xml schema spec can appear in.
+ */
+ class XsdTagScope
+ {
+ public:
+ enum Type
+ {
+ Schema,
+ Include,
+ Import,
+ Redefine,
+ Annotation,
+ AppInfo,
+ Documentation,
+ GlobalSimpleType,
+ LocalSimpleType,
+ SimpleRestriction,
+ List,
+ Union,
+ MinExclusiveFacet,
+ MinInclusiveFacet,
+ MaxExclusiveFacet,
+ MaxInclusiveFacet,
+ TotalDigitsFacet,
+ FractionDigitsFacet,
+ LengthFacet,
+ MinLengthFacet,
+ MaxLengthFacet,
+ EnumerationFacet,
+ WhiteSpaceFacet,
+ PatternFacet,
+ GlobalComplexType,
+ LocalComplexType,
+ SimpleContent,
+ SimpleContentRestriction,
+ SimpleContentExtension,
+ ComplexContent,
+ ComplexContentRestriction,
+ ComplexContentExtension,
+ NamedGroup,
+ ReferredGroup,
+ All,
+ LocalAll,
+ Choice,
+ LocalChoice,
+ Sequence,
+ LocalSequence,
+ GlobalAttribute,
+ LocalAttribute,
+ NamedAttributeGroup,
+ ReferredAttributeGroup,
+ GlobalElement,
+ LocalElement,
+ Unique,
+ Key,
+ KeyRef,
+ Selector,
+ Field,
+ Notation,
+ Any,
+ AnyAttribute,
+ Alternative,
+ Assert,
+ Assertion,
+ OpenContent,
+ DefaultOpenContent,
+ Override
+ };
+ };
+
+ /**
+ * A hash that keeps the mapping between the single components that can appear
+ * in a schema document (e.g. elements, attributes, type definitions) and their
+ * source locations inside the document.
+ */
+ typedef QHash<NamedSchemaComponent::Ptr, QSourceLocation> ComponentLocationHash;
+
+ /**
+ * @short A context for schema parsing.
+ *
+ * This class provides a context for all components that are
+ * nedded for parsing and compiling the XML schema.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSchemaParserContext : public QSharedData
+ {
+ public:
+ /**
+ * A smart pointer wrapping XsdSchemaParserContext instances.
+ */
+ typedef QExplicitlySharedDataPointer<XsdSchemaParserContext> Ptr;
+
+ /**
+ * Creates a new schema parser context object.
+ *
+ * @param namePool The name pool where all names of the schema will be stored in.
+ * @param context The schema context to use for error reporting etc.
+ */
+ XsdSchemaParserContext(const NamePool::Ptr &namePool, const XsdSchemaContext::Ptr &context);
+
+ /**
+ * Returns the name pool of the schema parser context.
+ */
+ NamePool::Ptr namePool() const;
+
+ /**
+ * Returns the schema resolver of the schema context.
+ */
+ XsdSchemaResolver::Ptr resolver() const;
+
+ /**
+ * Returns the schema resolver of the schema context.
+ */
+ XsdSchemaChecker::Ptr checker() const;
+
+ /**
+ * Returns the schema object of the schema context.
+ */
+ XsdSchema::Ptr schema() const;
+
+ /**
+ * Returns the element descriptions for the schema parser.
+ *
+ * The element descriptions are a fast lookup table for
+ * verifying whether certain attributes are allowed for
+ * a given element type.
+ */
+ ElementDescription<XsdSchemaToken, XsdTagScope::Type>::Hash elementDescriptions() const;
+
+ /**
+ * Returns an unique name that is used by the schema parser
+ * for anonymous types.
+ *
+ * @param targetNamespace The namespace of the name.
+ */
+ QXmlName createAnonymousName(const QString &targetNamespace) const;
+
+ private:
+ /**
+ * Fills the element description hash with the required and prohibited
+ * attributes.
+ */
+ static ElementDescription<XsdSchemaToken, XsdTagScope::Type>::Hash setupElementDescriptions();
+
+ NamePool::Ptr m_namePool;
+ XsdSchema::Ptr m_schema;
+ XsdSchemaChecker::Ptr m_checker;
+ XsdSchemaResolver::Ptr m_resolver;
+ const ElementDescription<XsdSchemaToken, XsdTagScope::Type>::Hash m_elementDescriptions;
+ mutable QAtomicInt m_anonymousNameCounter;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschemaresolver.cpp b/src/xmlpatterns/schema/qxsdschemaresolver.cpp
new file mode 100644
index 0000000000..4c6910ffff
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemaresolver.cpp
@@ -0,0 +1,1706 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdschemaresolver_p.h"
+
+#include "qderivedinteger_p.h"
+#include "qderivedstring_p.h"
+#include "qqnamevalue_p.h"
+#include "qxsdattributereference_p.h"
+#include "qxsdparticlechecker_p.h"
+#include "qxsdreference_p.h"
+#include "qxsdschemacontext_p.h"
+#include "qxsdschemahelper_p.h"
+#include "qxsdschemaparsercontext_p.h"
+#include "qxsdschematypesfactory_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchemaResolver::XsdSchemaResolver(const QExplicitlySharedDataPointer<XsdSchemaContext> &context, const XsdSchemaParserContext *parserContext)
+ : m_context(context)
+ , m_checker(parserContext->checker())
+ , m_namePool(parserContext->namePool())
+ , m_schema(parserContext->schema())
+{
+ m_keyReferences.reserve(20);
+ m_simpleRestrictionBases.reserve(20);
+ m_simpleListTypes.reserve(20);
+ m_simpleUnionTypes.reserve(20);
+ m_elementTypes.reserve(20);
+ m_complexBaseTypes.reserve(20);
+ m_attributeTypes.reserve(20);
+ m_alternativeTypes.reserve(20);
+ m_alternativeTypeElements.reserve(20);
+ m_substitutionGroupAffiliations.reserve(20);
+
+ m_predefinedSchemaTypes = m_context->schemaTypeFactory()->types().values();
+}
+
+XsdSchemaResolver::~XsdSchemaResolver()
+{
+}
+
+void XsdSchemaResolver::resolve()
+{
+ m_checker->addComponentLocationHash(m_componentLocationHash);
+
+ // resolve the base types for all types
+ resolveSimpleRestrictionBaseTypes();
+ resolveComplexBaseTypes();
+
+ // do the basic checks which depend on having a base type available
+ m_checker->basicCheck();
+
+ // resolve further types that only map a type name to a type object
+ resolveSimpleListType();
+ resolveSimpleUnionTypes();
+ resolveElementTypes();
+ resolveAttributeTypes();
+ resolveAlternativeTypes();
+
+ // resolve objects that do not need information about inheritance
+ resolveKeyReferences();
+ resolveSubstitutionGroupAffiliations();
+
+ // resolve objects that do need information about inheritance
+ resolveSimpleRestrictions();
+ resolveSimpleContentComplexTypes();
+
+ // resolve objects which replace place holders
+ resolveTermReferences();
+ resolveAttributeTermReferences();
+
+ // resolve additional objects that do need information about inheritance
+ resolveAttributeInheritance();
+ resolveComplexContentComplexTypes();
+ resolveSubstitutionGroups();
+
+ resolveEnumerationFacetValues();
+
+ checkRedefinedGroups();
+ checkRedefinedAttributeGroups();
+
+ // check the constraining facets before we resolve them
+ m_checker->checkConstrainingFacets();
+
+ // add it again, as we may have added new components in the meantime
+ m_checker->addComponentLocationHash(m_componentLocationHash);
+
+ m_checker->check();
+}
+
+void XsdSchemaResolver::addKeyReference(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &keyRef, const QXmlName &reference, const QSourceLocation &location)
+{
+ KeyReference item;
+ item.element = element;
+ item.keyRef = keyRef;
+ item.reference = reference;
+ item.location = location;
+
+ m_keyReferences.append(item);
+}
+
+void XsdSchemaResolver::addSimpleRestrictionBase(const XsdSimpleType::Ptr &simpleType, const QXmlName &baseName, const QSourceLocation &location)
+{
+ SimpleRestrictionBase item;
+ item.simpleType = simpleType;
+ item.baseName = baseName;
+ item.location = location;
+
+ m_simpleRestrictionBases.append(item);
+}
+
+void XsdSchemaResolver::removeSimpleRestrictionBase(const XsdSimpleType::Ptr &type)
+{
+ for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) {
+ if (m_simpleRestrictionBases.at(i).simpleType == type) {
+ m_simpleRestrictionBases.remove(i);
+ break;
+ }
+ }
+}
+
+void XsdSchemaResolver::addSimpleListType(const XsdSimpleType::Ptr &simpleType, const QXmlName &typeName, const QSourceLocation &location)
+{
+ SimpleListType item;
+ item.simpleType = simpleType;
+ item.typeName = typeName;
+ item.location = location;
+
+ m_simpleListTypes.append(item);
+}
+
+void XsdSchemaResolver::addSimpleUnionTypes(const XsdSimpleType::Ptr &simpleType, const QList<QXmlName> &typeNames, const QSourceLocation &location)
+{
+ SimpleUnionType item;
+ item.simpleType = simpleType;
+ item.typeNames = typeNames;
+ item.location = location;
+
+ m_simpleUnionTypes.append(item);
+}
+
+void XsdSchemaResolver::addElementType(const XsdElement::Ptr &element, const QXmlName &typeName, const QSourceLocation &location)
+{
+ ElementType item;
+ item.element = element;
+ item.typeName = typeName;
+ item.location = location;
+
+ m_elementTypes.append(item);
+}
+
+void XsdSchemaResolver::addComplexBaseType(const XsdComplexType::Ptr &complexType, const QXmlName &baseName, const QSourceLocation &location, const XsdFacet::Hash &facets)
+{
+ ComplexBaseType item;
+ item.complexType = complexType;
+ item.baseName = baseName;
+ item.location = location;
+ item.facets = facets;
+
+ m_complexBaseTypes.append(item);
+}
+
+void XsdSchemaResolver::removeComplexBaseType(const XsdComplexType::Ptr &type)
+{
+ for (int i = 0; i < m_complexBaseTypes.count(); ++i) {
+ if (m_complexBaseTypes.at(i).complexType == type) {
+ m_complexBaseTypes.remove(i);
+ break;
+ }
+ }
+}
+
+void XsdSchemaResolver::addComplexContentType(const XsdComplexType::Ptr &complexType, const XsdParticle::Ptr &content, bool mixed)
+{
+ ComplexContentType item;
+ item.complexType = complexType;
+ item.explicitContent = content;
+ item.effectiveMixed = mixed;
+ m_complexContentTypes.append(item);
+}
+
+void XsdSchemaResolver::addAttributeType(const XsdAttribute::Ptr &attribute, const QXmlName &typeName, const QSourceLocation &location)
+{
+ AttributeType item;
+ item.attribute = attribute;
+ item.typeName = typeName;
+ item.location = location;
+
+ m_attributeTypes.append(item);
+}
+
+void XsdSchemaResolver::addAlternativeType(const XsdAlternative::Ptr &alternative, const QXmlName &typeName, const QSourceLocation &location)
+{
+ AlternativeType item;
+ item.alternative = alternative;
+ item.typeName = typeName;
+ item.location = location;
+
+ m_alternativeTypes.append(item);
+}
+
+void XsdSchemaResolver::addAlternativeType(const XsdAlternative::Ptr &alternative, const XsdElement::Ptr &element)
+{
+ AlternativeTypeElement item;
+ item.alternative = alternative;
+ item.element = element;
+
+ m_alternativeTypeElements.append(item);
+}
+
+void XsdSchemaResolver::addSubstitutionGroupAffiliation(const XsdElement::Ptr &element, const QList<QXmlName> &elementNames, const QSourceLocation &location)
+{
+ SubstitutionGroupAffiliation item;
+ item.element = element;
+ item.elementNames = elementNames;
+ item.location = location;
+
+ m_substitutionGroupAffiliations.append(item);
+}
+
+void XsdSchemaResolver::addSubstitutionGroupType(const XsdElement::Ptr &element)
+{
+ m_substitutionGroupTypes.append(element);
+}
+
+void XsdSchemaResolver::addComponentLocationHash(const ComponentLocationHash &hash)
+{
+ m_componentLocationHash.unite(hash);
+}
+
+void XsdSchemaResolver::addEnumerationFacetValue(const AtomicValue::Ptr &facetValue, const NamespaceSupport &namespaceSupport)
+{
+ m_enumerationFacetValues.insert(facetValue, namespaceSupport);
+}
+
+void XsdSchemaResolver::addRedefinedGroups(const XsdModelGroup::Ptr &redefinedGroup, const XsdModelGroup::Ptr &group)
+{
+ RedefinedGroups item;
+ item.redefinedGroup = redefinedGroup;
+ item.group = group;
+
+ m_redefinedGroups.append(item);
+}
+
+void XsdSchemaResolver::addRedefinedAttributeGroups(const XsdAttributeGroup::Ptr &redefinedGroup, const XsdAttributeGroup::Ptr &group)
+{
+ RedefinedAttributeGroups item;
+ item.redefinedGroup = redefinedGroup;
+ item.group = group;
+
+ m_redefinedAttributeGroups.append(item);
+}
+
+void XsdSchemaResolver::addAllGroupCheck(const XsdReference::Ptr &reference)
+{
+ m_allGroups.insert(reference);
+}
+
+void XsdSchemaResolver::copyDataTo(const XsdSchemaResolver::Ptr &other) const
+{
+ other->m_keyReferences << m_keyReferences;
+ other->m_simpleRestrictionBases << m_simpleRestrictionBases;
+ other->m_simpleListTypes << m_simpleListTypes;
+ other->m_simpleUnionTypes << m_simpleUnionTypes;
+ other->m_elementTypes << m_elementTypes;
+ other->m_complexBaseTypes << m_complexBaseTypes;
+ other->m_complexContentTypes << m_complexContentTypes;
+ other->m_attributeTypes << m_attributeTypes;
+ other->m_alternativeTypes << m_alternativeTypes;
+ other->m_alternativeTypeElements << m_alternativeTypeElements;
+ other->m_substitutionGroupAffiliations << m_substitutionGroupAffiliations;
+ other->m_substitutionGroupTypes << m_substitutionGroupTypes;
+}
+
+QXmlName XsdSchemaResolver::baseTypeNameOfType(const SchemaType::Ptr &type) const
+{
+ for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) {
+ if (m_simpleRestrictionBases.at(i).simpleType == type)
+ return m_simpleRestrictionBases.at(i).baseName;
+ }
+
+ for (int i = 0; i < m_complexBaseTypes.count(); ++i) {
+ if (m_complexBaseTypes.at(i).complexType == type)
+ return m_complexBaseTypes.at(i).baseName;
+ }
+
+ return QXmlName();
+}
+
+QXmlName XsdSchemaResolver::typeNameOfAttribute(const XsdAttribute::Ptr &attribute) const
+{
+ for (int i = 0; i < m_attributeTypes.count(); ++i) {
+ if (m_attributeTypes.at(i).attribute == attribute)
+ return m_attributeTypes.at(i).typeName;
+ }
+
+ return QXmlName();
+}
+
+void XsdSchemaResolver::setDefaultOpenContent(const XsdComplexType::OpenContent::Ptr &openContent, bool appliesToEmpty)
+{
+ m_defaultOpenContent = openContent;
+ m_defaultOpenContentAppliesToEmpty = appliesToEmpty;
+}
+
+void XsdSchemaResolver::resolveKeyReferences()
+{
+ for (int i = 0; i < m_keyReferences.count(); ++i) {
+ const KeyReference ref = m_keyReferences.at(i);
+
+ const XsdIdentityConstraint::Ptr constraint = m_schema->identityConstraint(ref.reference);
+ if (!constraint) {
+ m_context->error(QtXmlPatterns::tr("%1 references unknown %2 or %3 element %4")
+ .arg(formatKeyword(ref.keyRef->displayName(m_namePool)))
+ .arg(formatElement("key"))
+ .arg(formatElement("unique"))
+ .arg(formatKeyword(m_namePool, ref.reference)),
+ XsdSchemaContext::XSDError, ref.location);
+ return;
+ }
+
+ if (constraint->category() != XsdIdentityConstraint::Key && constraint->category() != XsdIdentityConstraint::Unique) { // only key and unique can be referenced
+ m_context->error(QtXmlPatterns::tr("%1 references identity constraint %2 that is no %3 or %4 element")
+ .arg(formatKeyword(ref.keyRef->displayName(m_namePool)))
+ .arg(formatKeyword(m_namePool, ref.reference))
+ .arg(formatElement("key"))
+ .arg(formatElement("unique")),
+ XsdSchemaContext::XSDError, ref.location);
+ return;
+ }
+
+ if (constraint->fields().count() != ref.keyRef->fields().count()) {
+ m_context->error(QtXmlPatterns::tr("%1 has a different number of fields from the identity constraint %2 that it references")
+ .arg(formatKeyword(ref.keyRef->displayName(m_namePool)))
+ .arg(formatKeyword(m_namePool, ref.reference)),
+ XsdSchemaContext::XSDError, ref.location);
+ return;
+ }
+
+ ref.keyRef->setReferencedKey(constraint);
+ }
+}
+
+void XsdSchemaResolver::resolveSimpleRestrictionBaseTypes()
+{
+ // iterate over all simple types that are derived by restriction
+ for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) {
+ const SimpleRestrictionBase item = m_simpleRestrictionBases.at(i);
+
+ // find the base type
+ SchemaType::Ptr type = m_schema->type(item.baseName);
+ if (!type) {
+ // maybe it's a basic type...
+ type = m_context->schemaTypeFactory()->createSchemaType(item.baseName);
+ if (!type) {
+ m_context->error(QtXmlPatterns::tr("base type %1 of %2 element cannot be resolved")
+ .arg(formatType(m_namePool, item.baseName))
+ .arg(formatElement("restriction")),
+ XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+ }
+
+ item.simpleType->setWxsSuperType(type);
+ }
+}
+
+void XsdSchemaResolver::resolveSimpleRestrictions()
+{
+ XsdSimpleType::List simpleTypes;
+
+ // first collect the global simple types
+ const SchemaType::List types = m_schema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ if (types.at(i)->isSimpleType() && (types.at(i)->derivationMethod() == SchemaType::DerivationRestriction))
+ simpleTypes.append(types.at(i));
+ }
+
+ // then collect all anonymous simple types
+ const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
+ for (int i = 0; i < anonymousTypes.count(); ++i) {
+ if (anonymousTypes.at(i)->isSimpleType() && (anonymousTypes.at(i)->derivationMethod() == SchemaType::DerivationRestriction))
+ simpleTypes.append(anonymousTypes.at(i));
+ }
+
+ QSet<XsdSimpleType::Ptr> visitedTypes;
+ for (int i = 0; i < simpleTypes.count(); ++i) {
+ resolveSimpleRestrictions(simpleTypes.at(i), visitedTypes);
+ }
+}
+
+void XsdSchemaResolver::resolveSimpleRestrictions(const XsdSimpleType::Ptr &simpleType, QSet<XsdSimpleType::Ptr> &visitedTypes)
+{
+ if (visitedTypes.contains(simpleType))
+ return;
+ else
+ visitedTypes.insert(simpleType);
+
+ if (simpleType->derivationMethod() != XsdSimpleType::DerivationRestriction)
+ return;
+
+ // as xs:NMTOKENS, xs:ENTITIES and xs:IDREFS are provided by our XsdSchemaTypesFactory, they are
+ // setup correctly already and shouldn't be handled here
+ if (m_predefinedSchemaTypes.contains(simpleType))
+ return;
+
+ const SchemaType::Ptr baseType = simpleType->wxsSuperType();
+ Q_ASSERT(baseType);
+
+ if (baseType->isDefinedBySchema())
+ resolveSimpleRestrictions(XsdSimpleType::Ptr(baseType), visitedTypes);
+
+ simpleType->setCategory(baseType->category());
+
+ if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
+ QSet<AnySimpleType::Ptr> visitedPrimitiveTypes;
+ const AnySimpleType::Ptr primitiveType = findPrimitiveType(baseType, visitedPrimitiveTypes);
+ simpleType->setPrimitiveType(primitiveType);
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
+ const XsdSimpleType::Ptr simpleBaseType = baseType;
+ simpleType->setItemType(simpleBaseType->itemType());
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
+ const XsdSimpleType::Ptr simpleBaseType = baseType;
+ simpleType->setMemberTypes(simpleBaseType->memberTypes());
+ }
+}
+
+void XsdSchemaResolver::resolveSimpleListType()
+{
+ // iterate over all simple types where the item type shall be resolved
+ for (int i = 0; i < m_simpleListTypes.count(); ++i) {
+ const SimpleListType item = m_simpleListTypes.at(i);
+
+ // try to resolve the name
+ SchemaType::Ptr type = m_schema->type(item.typeName);
+ if (!type) {
+ // maybe it's a basic type...
+ type = m_context->schemaTypeFactory()->createSchemaType(item.typeName);
+ if (!type) {
+ m_context->error(QtXmlPatterns::tr("item type %1 of %2 element cannot be resolved")
+ .arg(formatType(m_namePool, item.typeName))
+ .arg(formatElement("list")),
+ XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+ }
+
+ item.simpleType->setItemType(type);
+ }
+}
+
+void XsdSchemaResolver::resolveSimpleUnionTypes()
+{
+ // iterate over all simple types where the union member types shall be resolved
+ for (int i = 0; i < m_simpleUnionTypes.count(); ++i) {
+ const SimpleUnionType item = m_simpleUnionTypes.at(i);
+
+ AnySimpleType::List memberTypes;
+
+ // iterate over all union member type names
+ const QList<QXmlName> typeNames = item.typeNames;
+ for (int j = 0; j < typeNames.count(); ++j) {
+ const QXmlName typeName = typeNames.at(j);
+
+ // try to resolve the name
+ SchemaType::Ptr type = m_schema->type(typeName);
+ if (!type) {
+ // maybe it's a basic type...
+ type = m_context->schemaTypeFactory()->createSchemaType(typeName);
+ if (!type) {
+ m_context->error(QtXmlPatterns::tr("member type %1 of %2 element cannot be resolved")
+ .arg(formatType(m_namePool, typeName))
+ .arg(formatElement("union")),
+ XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+ }
+
+ memberTypes.append(type);
+ }
+
+ // append the types that have been defined as <simpleType> children
+ memberTypes << item.simpleType->memberTypes();
+
+ item.simpleType->setMemberTypes(memberTypes);
+ }
+}
+
+void XsdSchemaResolver::resolveElementTypes()
+{
+ for (int i = 0; i < m_elementTypes.count(); ++i) {
+ const ElementType item = m_elementTypes.at(i);
+
+ SchemaType::Ptr type = m_schema->type(item.typeName);
+ if (!type) {
+ // maybe it's a basic type...
+ type = m_context->schemaTypeFactory()->createSchemaType(item.typeName);
+ if (!type) {
+ m_context->error(QtXmlPatterns::tr("type %1 of %2 element cannot be resolved")
+ .arg(formatType(m_namePool, item.typeName))
+ .arg(formatElement("element")),
+ XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+ }
+
+ item.element->setType(type);
+ }
+}
+
+void XsdSchemaResolver::resolveComplexBaseTypes()
+{
+ for (int i = 0; i < m_complexBaseTypes.count(); ++i) {
+ const ComplexBaseType item = m_complexBaseTypes.at(i);
+
+ SchemaType::Ptr type = m_schema->type(item.baseName);
+ if (!type) {
+ // maybe it's a basic type...
+ type = m_context->schemaTypeFactory()->createSchemaType(item.baseName);
+ if (!type) {
+ m_context->error(QtXmlPatterns::tr("base type %1 of complex type cannot be resolved").arg(formatType(m_namePool, item.baseName)), XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+ }
+
+ if (item.complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
+ if (type->isComplexType() && type->isDefinedBySchema()) {
+ const XsdComplexType::Ptr baseType = type;
+ if (baseType->contentType()->variety() != XsdComplexType::ContentType::Simple) {
+ m_context->error(QtXmlPatterns::tr("%1 cannot have complex base type that has a %2")
+ .arg(formatElement("simpleContent"))
+ .arg(formatElement("complexContent")),
+ XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+ }
+ }
+
+ item.complexType->setWxsSuperType(type);
+ }
+}
+
+void XsdSchemaResolver::resolveSimpleContentComplexTypes()
+{
+ XsdComplexType::List complexTypes;
+
+ // first collect the global complex types
+ const SchemaType::List types = m_schema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema())
+ complexTypes.append(types.at(i));
+ }
+
+ // then collect all anonymous simple types
+ const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
+ for (int i = 0; i < anonymousTypes.count(); ++i) {
+ if (anonymousTypes.at(i)->isComplexType() && anonymousTypes.at(i)->isDefinedBySchema())
+ complexTypes.append(anonymousTypes.at(i));
+ }
+
+ QSet<XsdComplexType::Ptr> visitedTypes;
+ for (int i = 0; i < complexTypes.count(); ++i) {
+ if (XsdComplexType::Ptr(complexTypes.at(i))->contentType()->variety() == XsdComplexType::ContentType::Simple)
+ resolveSimpleContentComplexTypes(complexTypes.at(i), visitedTypes);
+ }
+}
+
+void XsdSchemaResolver::resolveSimpleContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes)
+{
+ if (visitedTypes.contains(complexType))
+ return;
+ else
+ visitedTypes.insert(complexType);
+
+ const SchemaType::Ptr baseType = complexType->wxsSuperType();
+
+ // at this point simple types have been resolved already, so we care about
+ // complex types here only
+
+ // http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctsc
+ // 1
+ if (baseType->isComplexType() && baseType->isDefinedBySchema()) {
+ const XsdComplexType::Ptr complexBaseType = baseType;
+
+ resolveSimpleContentComplexTypes(complexBaseType, visitedTypes);
+
+ if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
+ if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) {
+ if (complexType->contentType()->simpleType()) {
+ // 1.1 contains the content of the <simpleType> already
+ } else {
+ // 1.2
+ const XsdSimpleType::Ptr anonType(new XsdSimpleType());
+ anonType->setCategory(complexBaseType->contentType()->simpleType()->category());
+ anonType->setDerivationMethod(XsdSimpleType::DerivationRestriction);
+ anonType->setWxsSuperType(complexBaseType->contentType()->simpleType());
+ anonType->setFacets(complexTypeFacets(complexType));
+
+ QSet<AnySimpleType::Ptr> visitedPrimitiveTypes;
+ const AnySimpleType::Ptr primitiveType = findPrimitiveType(anonType->wxsSuperType(), visitedPrimitiveTypes);
+ anonType->setPrimitiveType(primitiveType);
+
+ complexType->contentType()->setSimpleType(anonType);
+
+ m_schema->addAnonymousType(anonType);
+ m_componentLocationHash.insert(anonType, m_componentLocationHash.value(complexType));
+ }
+ } else if (complexBaseType->derivationMethod() == XsdComplexType::DerivationExtension) { // 3
+ complexType->contentType()->setSimpleType(complexBaseType->contentType()->simpleType());
+ }
+ } else if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed &&
+ complexType->derivationMethod() == XsdComplexType::DerivationRestriction &&
+ XsdSchemaHelper::isParticleEmptiable(complexBaseType->contentType()->particle())) { // 2
+ // simple type was already set in parser
+
+ const XsdSimpleType::Ptr anonType(new XsdSimpleType());
+ anonType->setCategory(complexType->contentType()->simpleType()->category());
+ anonType->setDerivationMethod(XsdSimpleType::DerivationRestriction);
+ anonType->setWxsSuperType(complexType->contentType()->simpleType());
+ anonType->setFacets(complexTypeFacets(complexType));
+
+ QSet<AnySimpleType::Ptr> visitedPrimitiveTypes;
+ const AnySimpleType::Ptr primitiveType = findPrimitiveType(anonType->wxsSuperType(), visitedPrimitiveTypes);
+ anonType->setPrimitiveType(primitiveType);
+
+ complexType->contentType()->setSimpleType(anonType);
+
+ m_schema->addAnonymousType(anonType);
+ m_componentLocationHash.insert(anonType, m_componentLocationHash.value(complexType));
+ } else {
+ complexType->contentType()->setSimpleType(BuiltinTypes::xsAnySimpleType);
+ }
+ } else if (baseType->isSimpleType()) { // 4
+ complexType->contentType()->setSimpleType(baseType);
+ } else { // 5
+ complexType->contentType()->setSimpleType(BuiltinTypes::xsAnySimpleType);
+ }
+}
+
+void XsdSchemaResolver::resolveComplexContentComplexTypes()
+{
+ XsdComplexType::List complexTypes;
+
+ // first collect the global complex types
+ const SchemaType::List types = m_schema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema())
+ complexTypes.append(types.at(i));
+ }
+
+ // then collect all anonymous simple types
+ const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
+ for (int i = 0; i < anonymousTypes.count(); ++i) {
+ if (anonymousTypes.at(i)->isComplexType() && anonymousTypes.at(i)->isDefinedBySchema())
+ complexTypes.append(anonymousTypes.at(i));
+ }
+
+ QSet<XsdComplexType::Ptr> visitedTypes;
+ for (int i = 0; i < complexTypes.count(); ++i) {
+ if (XsdComplexType::Ptr(complexTypes.at(i))->contentType()->variety() != XsdComplexType::ContentType::Simple)
+ resolveComplexContentComplexTypes(complexTypes.at(i), visitedTypes);
+ }
+}
+
+void XsdSchemaResolver::resolveComplexContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes)
+{
+ if (visitedTypes.contains(complexType))
+ return;
+ else
+ visitedTypes.insert(complexType);
+
+ ComplexContentType item;
+ bool foundCorrespondingItem = false;
+ for (int i = 0; i < m_complexContentTypes.count(); ++i) {
+ if (m_complexContentTypes.at(i).complexType == complexType) {
+ item = m_complexContentTypes.at(i);
+ foundCorrespondingItem = true;
+ break;
+ }
+ }
+
+ if (!foundCorrespondingItem)
+ return;
+
+ const SchemaType::Ptr baseType = complexType->wxsSuperType();
+
+ // at this point simple types have been resolved already, so we care about
+ // complex types here only
+ if (baseType->isComplexType() && baseType->isDefinedBySchema())
+ resolveComplexContentComplexTypes(XsdComplexType::Ptr(baseType), visitedTypes);
+
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctcc.common
+
+ // 3
+ XsdParticle::Ptr effectiveContent;
+ if (!item.explicitContent) { // 3.1
+ if (item.effectiveMixed == true) { // 3.1.1
+ const XsdParticle::Ptr particle(new XsdParticle());
+ particle->setMinimumOccurs(1);
+ particle->setMaximumOccurs(1);
+ particle->setMaximumOccursUnbounded(false);
+
+ const XsdModelGroup::Ptr sequence(new XsdModelGroup());
+ sequence->setCompositor(XsdModelGroup::SequenceCompositor);
+ particle->setTerm(sequence);
+
+ effectiveContent = particle;
+ } else { // 3.1.2
+ effectiveContent = XsdParticle::Ptr();
+ }
+ } else { // 3.2
+ effectiveContent = item.explicitContent;
+ }
+
+ // 4
+ XsdComplexType::ContentType::Ptr explicitContentType(new XsdComplexType::ContentType());
+ if (item.complexType->derivationMethod() == XsdComplexType::DerivationRestriction) { // 4.1
+ if (!effectiveContent) { // 4.1.1
+ explicitContentType->setVariety(XsdComplexType::ContentType::Empty);
+ } else { // 4.1.2
+ if (item.effectiveMixed == true)
+ explicitContentType->setVariety(XsdComplexType::ContentType::Mixed);
+ else
+ explicitContentType->setVariety(XsdComplexType::ContentType::ElementOnly);
+
+ explicitContentType->setParticle(effectiveContent);
+ }
+ } else if (item.complexType->derivationMethod() == XsdComplexType::DerivationExtension) { // 4.2
+ const SchemaType::Ptr baseType = item.complexType->wxsSuperType();
+ if (baseType->isSimpleType() || (baseType->isComplexType() && baseType->isDefinedBySchema() && (XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::Empty ||
+ XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::Simple))) { // 4.2.1
+ if (!effectiveContent) {
+ explicitContentType->setVariety(XsdComplexType::ContentType::Empty);
+ } else {
+ if (item.effectiveMixed == true)
+ explicitContentType->setVariety(XsdComplexType::ContentType::Mixed);
+ else
+ explicitContentType->setVariety(XsdComplexType::ContentType::ElementOnly);
+
+ explicitContentType->setParticle(effectiveContent);
+ }
+ } else if (baseType->isComplexType() && baseType->isDefinedBySchema() && (XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::ElementOnly ||
+ XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::Mixed) && !effectiveContent) { // 4.2.2
+ const XsdComplexType::Ptr complexBaseType(baseType);
+
+ explicitContentType = complexBaseType->contentType();
+ } else { // 4.2.3
+ explicitContentType->setVariety(item.effectiveMixed ? XsdComplexType::ContentType::Mixed : XsdComplexType::ContentType::ElementOnly);
+
+ XsdParticle::Ptr baseParticle;
+ if (baseType == BuiltinTypes::xsAnyType) {
+ // we need a workaround here, since the xsAnyType is no real (aka XsdComplexType) complex type...
+
+ baseParticle = XsdParticle::Ptr(new XsdParticle());
+ baseParticle->setMinimumOccurs(1);
+ baseParticle->setMaximumOccurs(1);
+ baseParticle->setMaximumOccursUnbounded(false);
+
+ const XsdModelGroup::Ptr group(new XsdModelGroup());
+ group->setCompositor(XsdModelGroup::SequenceCompositor);
+
+ const XsdParticle::Ptr particle(new XsdParticle());
+ particle->setMinimumOccurs(0);
+ particle->setMaximumOccursUnbounded(true);
+
+ const XsdWildcard::Ptr wildcard(new XsdWildcard());
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ wildcard->setProcessContents(XsdWildcard::Lax);
+
+ particle->setTerm(wildcard);
+ XsdParticle::List particles;
+ particles.append(particle);
+ group->setParticles(particles);
+ baseParticle->setTerm(group);
+ } else {
+ const XsdComplexType::Ptr complexBaseType(baseType);
+ baseParticle = complexBaseType->contentType()->particle();
+ }
+ if (baseParticle && baseParticle->term()->isModelGroup() && (XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) &&
+ (!item.explicitContent)) { // 4.2.3.1
+
+ explicitContentType->setParticle(baseParticle);
+ } else if (baseParticle && baseParticle->term()->isModelGroup() && (XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) &&
+ (effectiveContent->term()->isModelGroup() && (XsdModelGroup::Ptr(effectiveContent->term())->compositor() == XsdModelGroup::AllCompositor))) { // 4.2.3.2
+ const XsdParticle::Ptr particle(new XsdParticle());
+ particle->setMinimumOccurs(effectiveContent->minimumOccurs());
+ particle->setMaximumOccurs(1);
+ particle->setMaximumOccursUnbounded(false);
+
+ const XsdModelGroup::Ptr group(new XsdModelGroup());
+ group->setCompositor(XsdModelGroup::AllCompositor);
+ XsdParticle::List particles = XsdModelGroup::Ptr(baseParticle->term())->particles();
+ particles << XsdModelGroup::Ptr(effectiveContent->term())->particles();
+ group->setParticles(particles);
+ particle->setTerm(group);
+
+ explicitContentType->setParticle(particle);
+ } else { // 4.2.3.3
+ const XsdParticle::Ptr particle(new XsdParticle());
+ particle->setMinimumOccurs(1);
+ particle->setMaximumOccurs(1);
+ particle->setMaximumOccursUnbounded(false);
+
+ const XsdModelGroup::Ptr group(new XsdModelGroup());
+ group->setCompositor(XsdModelGroup::SequenceCompositor);
+
+ if (effectiveContent && effectiveContent->term()->isModelGroup() && XsdModelGroup::Ptr(effectiveContent->term())->compositor() == XsdModelGroup::AllCompositor) {
+ m_context->error(QtXmlPatterns::tr("content model of complex type %1 contains %2 element so it cannot be derived by extension from a non-empty type")
+ .arg(formatType(m_namePool, complexType)).arg(formatKeyword("all")), XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+
+ if (baseParticle && baseParticle->term()->isModelGroup() && XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) {
+ m_context->error(QtXmlPatterns::tr("complex type %1 cannot be derived by extension from %2 as the latter contains %3 element in its content model")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, baseType))
+ .arg(formatKeyword("all")), XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+
+ XsdParticle::List particles;
+ if (baseParticle)
+ particles << baseParticle;
+ if (effectiveContent)
+ particles << effectiveContent;
+ group->setParticles(particles);
+ particle->setTerm(group);
+
+ explicitContentType->setParticle(particle);
+ }
+
+ if (baseType->isDefinedBySchema()) { // xs:anyType has no open content
+ const XsdComplexType::Ptr complexBaseType(baseType);
+ explicitContentType->setOpenContent(complexBaseType->contentType()->openContent());
+ }
+ }
+ }
+
+ // 5
+ XsdComplexType::OpenContent::Ptr wildcardElement;
+ if (item.complexType->contentType()->openContent()) { // 5.1
+ wildcardElement = item.complexType->contentType()->openContent();
+ } else {
+ if (m_defaultOpenContent) { // 5.2
+ if ((explicitContentType->variety() != XsdComplexType::ContentType::Empty) || // 5.2.1
+ (explicitContentType->variety() == XsdComplexType::ContentType::Empty && m_defaultOpenContentAppliesToEmpty)) { // 5.2.2
+ wildcardElement = m_defaultOpenContent;
+ }
+ }
+ }
+
+ // 6
+ if (!wildcardElement) { // 6.1
+ item.complexType->setContentType(explicitContentType);
+ } else {
+ if (wildcardElement->mode() == XsdComplexType::OpenContent::None) { // 6.2
+ const XsdComplexType::ContentType::Ptr contentType(new XsdComplexType::ContentType());
+ contentType->setVariety(explicitContentType->variety());
+ contentType->setParticle(explicitContentType->particle());
+
+ item.complexType->setContentType(contentType);
+ } else { // 6.3
+ const XsdComplexType::ContentType::Ptr contentType(new XsdComplexType::ContentType());
+
+ if (explicitContentType->variety() == XsdComplexType::ContentType::Empty)
+ contentType->setVariety(XsdComplexType::ContentType::ElementOnly);
+ else
+ contentType->setVariety(explicitContentType->variety());
+
+ if (explicitContentType->variety() == XsdComplexType::ContentType::Empty) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ particle->setMinimumOccurs(1);
+ particle->setMaximumOccurs(1);
+ const XsdModelGroup::Ptr sequence(new XsdModelGroup());
+ sequence->setCompositor(XsdModelGroup::SequenceCompositor);
+ particle->setTerm(sequence);
+ contentType->setParticle(particle);
+ } else {
+ contentType->setParticle(explicitContentType->particle());
+ }
+
+ const XsdComplexType::OpenContent::Ptr openContent(new XsdComplexType::OpenContent());
+ if (wildcardElement)
+ openContent->setMode(wildcardElement->mode());
+ else
+ openContent->setMode(XsdComplexType::OpenContent::Interleave);
+
+ if (wildcardElement)
+ openContent->setWildcard(wildcardElement->wildcard());
+
+ item.complexType->setContentType(contentType);
+ }
+ }
+}
+
+void XsdSchemaResolver::resolveAttributeTypes()
+{
+ for (int i = 0; i < m_attributeTypes.count(); ++i) {
+ const AttributeType item = m_attributeTypes.at(i);
+
+ SchemaType::Ptr type = m_schema->type(item.typeName);
+ if (!type) {
+ // maybe it's a basic type...
+ type = m_context->schemaTypeFactory()->createSchemaType(item.typeName);
+ if (!type) {
+ m_context->error(QtXmlPatterns::tr("type %1 of %2 element cannot be resolved")
+ .arg(formatType(m_namePool, item.typeName))
+ .arg(formatElement("attribute")),
+ XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+ }
+
+ if (!type->isSimpleType() && type->category() != SchemaType::None) {
+ m_context->error(QtXmlPatterns::tr("type of %1 element must be a simple type, %2 is not")
+ .arg(formatElement("attribute"))
+ .arg(formatType(m_namePool, item.typeName)),
+ XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+
+ item.attribute->setType(type);
+ }
+}
+
+void XsdSchemaResolver::resolveAlternativeTypes()
+{
+ for (int i = 0; i < m_alternativeTypes.count(); ++i) {
+ const AlternativeType item = m_alternativeTypes.at(i);
+
+ SchemaType::Ptr type = m_schema->type(item.typeName);
+ if (!type) {
+ // maybe it's a basic type...
+ type = m_context->schemaTypeFactory()->createSchemaType(item.typeName);
+ if (!type) {
+ m_context->error(QtXmlPatterns::tr("type %1 of %2 element cannot be resolved")
+ .arg(formatType(m_namePool, item.typeName))
+ .arg(formatElement("alternative")),
+ XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+ }
+
+ item.alternative->setType(type);
+ }
+
+ for (int i = 0; i < m_alternativeTypeElements.count(); ++i) {
+ const AlternativeTypeElement item = m_alternativeTypeElements.at(i);
+ item.alternative->setType(item.element->type());
+ }
+}
+
+bool hasCircularSubstitutionGroup(const XsdElement::Ptr &current, const XsdElement::Ptr &head, const NamePool::Ptr &namePool)
+{
+ if (current == head)
+ return true;
+ else {
+ const XsdElement::List elements = current->substitutionGroupAffiliations();
+ for (int i = 0; i < elements.count(); ++i) {
+ if (hasCircularSubstitutionGroup(elements.at(i), head, namePool))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void XsdSchemaResolver::resolveSubstitutionGroupAffiliations()
+{
+ for (int i = 0; i < m_substitutionGroupAffiliations.count(); ++i) {
+ const SubstitutionGroupAffiliation item = m_substitutionGroupAffiliations.at(i);
+
+ XsdElement::List affiliations;
+ for (int j = 0; j < item.elementNames.count(); ++j) {
+ const XsdElement::Ptr element = m_schema->element(item.elementNames.at(j));
+ if (!element) {
+ m_context->error(QtXmlPatterns::tr("substitution group %1 of %2 element cannot be resolved")
+ .arg(formatKeyword(m_namePool, item.elementNames.at(j)))
+ .arg(formatElement("element")),
+ XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#e-props-correct 5)
+ if (hasCircularSubstitutionGroup(element, item.element, m_namePool)) {
+ m_context->error(QtXmlPatterns::tr("substitution group %1 has circular definition").arg(formatKeyword(m_namePool, item.elementNames.at(j))), XsdSchemaContext::XSDError, item.location);
+ return;
+ }
+
+ affiliations.append(element);
+ }
+
+ item.element->setSubstitutionGroupAffiliations(affiliations);
+ }
+
+ for (int i = 0; i < m_substitutionGroupTypes.count(); ++i) {
+ const XsdElement::Ptr element = m_substitutionGroupTypes.at(i);
+ element->setType(element->substitutionGroupAffiliations().first()->type());
+ }
+}
+
+bool isSubstGroupHeadOf(const XsdElement::Ptr &head, const XsdElement::Ptr &element, const NamePool::Ptr &namePool)
+{
+ if (head->name(namePool) == element->name(namePool))
+ return true;
+
+ const XsdElement::List affiliations = element->substitutionGroupAffiliations();
+ for (int i = 0; i < affiliations.count(); ++i) {
+ if (isSubstGroupHeadOf(head, affiliations.at(i), namePool))
+ return true;
+ }
+
+ return false;
+}
+
+void XsdSchemaResolver::resolveSubstitutionGroups()
+{
+ const XsdElement::List elements = m_schema->elements();
+ for (int i = 0; i < elements.count(); ++i) {
+ const XsdElement::Ptr element = elements.at(i);
+
+ // the element is always itself in the substitution group
+ element->addSubstitutionGroup(element);
+
+ for (int j = 0; j < elements.count(); ++j) {
+ if (i == j)
+ continue;
+
+ if (isSubstGroupHeadOf(element, elements.at(j), m_namePool))
+ element->addSubstitutionGroup(elements.at(j));
+ }
+ }
+}
+
+void XsdSchemaResolver::resolveTermReferences()
+{
+ // first the global complex types
+ const SchemaType::List types = m_schema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType = types.at(i);
+ if (complexType->contentType()->variety() != XsdComplexType::ContentType::ElementOnly && complexType->contentType()->variety() != XsdComplexType::ContentType::Mixed)
+ continue;
+
+ resolveTermReference(complexType->contentType()->particle(), QSet<QXmlName>());
+ }
+
+ // then all anonymous complex types
+ const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
+ for (int i = 0; i < anonymousTypes.count(); ++i) {
+ if (!(anonymousTypes.at(i)->isComplexType()) || !anonymousTypes.at(i)->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType = anonymousTypes.at(i);
+ if (complexType->contentType()->variety() != XsdComplexType::ContentType::ElementOnly && complexType->contentType()->variety() != XsdComplexType::ContentType::Mixed)
+ continue;
+
+ resolveTermReference(complexType->contentType()->particle(), QSet<QXmlName>());
+ }
+
+ const XsdModelGroup::List groups = m_schema->elementGroups();
+ for (int i = 0; i < groups.count(); ++i) {
+ const XsdParticle::Ptr particle(new XsdParticle());
+ particle->setTerm(groups.at(i));
+ resolveTermReference(particle, QSet<QXmlName>());
+ }
+}
+
+void XsdSchemaResolver::resolveTermReference(const XsdParticle::Ptr &particle, QSet<QXmlName> visitedGroups)
+{
+ if (!particle)
+ return;
+
+ const XsdTerm::Ptr term = particle->term();
+
+ // if it is a model group, we iterate over it recursive...
+ if (term->isModelGroup()) {
+ const XsdModelGroup::Ptr modelGroup = term;
+ const XsdParticle::List particles = modelGroup->particles();
+
+ for (int i = 0; i < particles.count(); ++i) {
+ resolveTermReference(particles.at(i), visitedGroups);
+ }
+
+ // check for unique names of elements inside all compositor
+ if (modelGroup->compositor() != XsdModelGroup::ChoiceCompositor) {
+ for (int i = 0; i < particles.count(); ++i) {
+ const XsdParticle::Ptr particle = particles.at(i);
+ const XsdTerm::Ptr term = particle->term();
+
+ if (!(term->isElement()))
+ continue;
+
+ for (int j = 0; j < particles.count(); ++j) {
+ const XsdParticle::Ptr otherParticle = particles.at(j);
+ const XsdTerm::Ptr otherTerm = otherParticle->term();
+
+ if (otherTerm->isElement() && i != j) {
+ const XsdElement::Ptr element = term;
+ const XsdElement::Ptr otherElement = otherTerm;
+
+ if (element->name(m_namePool) == otherElement->name(m_namePool)) {
+ if (modelGroup->compositor() == XsdModelGroup::AllCompositor) {
+ m_context->error(QtXmlPatterns::tr("duplicated element names %1 in %2 element")
+ .arg(formatKeyword(element->displayName(m_namePool)))
+ .arg(formatElement("all")),
+ XsdSchemaContext::XSDError, sourceLocation(modelGroup));
+ return;
+ } else if (modelGroup->compositor() == XsdModelGroup::SequenceCompositor) {
+ if (element->type() != otherElement->type()) { // not same variety
+ m_context->error(QtXmlPatterns::tr("duplicated element names %1 in %2 element")
+ .arg(formatKeyword(element->displayName(m_namePool)))
+ .arg(formatElement("sequence")),
+ XsdSchemaContext::XSDError, sourceLocation(modelGroup));
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return;
+ }
+
+ // ...otherwise we have reached the end of recursion...
+ if (!term->isReference())
+ return;
+
+ // ...or we have reached a reference term that must be resolved
+ const XsdReference::Ptr reference = term;
+ switch (reference->type()) {
+ case XsdReference::Element:
+ {
+ const XsdElement::Ptr element = m_schema->element(reference->referenceName());
+ if (element) {
+ particle->setTerm(element);
+ } else {
+ m_context->error(QtXmlPatterns::tr("reference %1 of %2 element cannot be resolved")
+ .arg(formatKeyword(m_namePool, reference->referenceName()))
+ .arg(formatElement("element")),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ return;
+ }
+ }
+ break;
+ case XsdReference::ModelGroup:
+ {
+ const XsdModelGroup::Ptr modelGroup = m_schema->elementGroup(reference->referenceName());
+ if (modelGroup) {
+ if (visitedGroups.contains(modelGroup->name(m_namePool))) {
+ m_context->error(QtXmlPatterns::tr("circular group reference for %1").arg(formatKeyword(modelGroup->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ } else {
+ visitedGroups.insert(modelGroup->name(m_namePool));
+ }
+
+ particle->setTerm(modelGroup);
+
+ // start recursive iteration here as well to get all references resolved
+ const XsdParticle::List particles = modelGroup->particles();
+ for (int i = 0; i < particles.count(); ++i) {
+ resolveTermReference(particles.at(i), visitedGroups);
+ }
+
+ if (modelGroup->compositor() == XsdModelGroup::AllCompositor) {
+ if (m_allGroups.contains(reference)) {
+ m_context->error(QtXmlPatterns::tr("%1 element is not allowed in this scope").arg(formatElement("all")),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ return;
+ }
+ if (particle->maximumOccursUnbounded() || particle->maximumOccurs() != 1) {
+ m_context->error(QtXmlPatterns::tr("%1 element cannot have %2 attribute with value other than %3")
+ .arg(formatElement("all"))
+ .arg(formatAttribute("maxOccurs"))
+ .arg(formatData("1")),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ return;
+ }
+ if (particle->minimumOccurs() != 0 && particle->minimumOccurs() != 1) {
+ m_context->error(QtXmlPatterns::tr("%1 element cannot have %2 attribute with value other than %3 or %4")
+ .arg(formatElement("all"))
+ .arg(formatAttribute("minOccurs"))
+ .arg(formatData("0"))
+ .arg(formatData("1")),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ return;
+ }
+ }
+ } else {
+ m_context->error(QtXmlPatterns::tr("reference %1 of %2 element cannot be resolved")
+ .arg(formatKeyword(m_namePool, reference->referenceName()))
+ .arg(formatElement("group")),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ return;
+ }
+ }
+ break;
+ }
+}
+
+void XsdSchemaResolver::resolveAttributeTermReferences()
+{
+ // first all global attribute groups
+ const XsdAttributeGroup::List attributeGroups = m_schema->attributeGroups();
+ for (int i = 0; i < attributeGroups.count(); ++i) {
+ XsdWildcard::Ptr wildcard = attributeGroups.at(i)->wildcard();
+ const XsdAttributeUse::List uses = resolveAttributeTermReferences(attributeGroups.at(i)->attributeUses(), wildcard, QSet<QXmlName>());
+ attributeGroups.at(i)->setAttributeUses(uses);
+ attributeGroups.at(i)->setWildcard(wildcard);
+ }
+
+ // then the global complex types
+ const SchemaType::List types = m_schema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType = types.at(i);
+ const XsdAttributeUse::List attributeUses = complexType->attributeUses();
+
+ XsdWildcard::Ptr wildcard = complexType->attributeWildcard();
+ const XsdAttributeUse::List uses = resolveAttributeTermReferences(attributeUses, wildcard, QSet<QXmlName>());
+ complexType->setAttributeUses(uses);
+ complexType->setAttributeWildcard(wildcard);
+ }
+
+ // and afterwards all anonymous complex types
+ const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
+ for (int i = 0; i < anonymousTypes.count(); ++i) {
+ if (!(anonymousTypes.at(i)->isComplexType()) || !anonymousTypes.at(i)->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType = anonymousTypes.at(i);
+ const XsdAttributeUse::List attributeUses = complexType->attributeUses();
+
+ XsdWildcard::Ptr wildcard = complexType->attributeWildcard();
+ const XsdAttributeUse::List uses = resolveAttributeTermReferences(attributeUses, wildcard, QSet<QXmlName>());
+ complexType->setAttributeUses(uses);
+ complexType->setAttributeWildcard(wildcard);
+ }
+}
+
+XsdAttributeUse::List XsdSchemaResolver::resolveAttributeTermReferences(const XsdAttributeUse::List &attributeUses, XsdWildcard::Ptr &wildcard, QSet<QXmlName> visitedAttributeGroups)
+{
+ XsdAttributeUse::List resolvedAttributeUses;
+
+ for (int i = 0; i < attributeUses.count(); ++i) {
+ const XsdAttributeUse::Ptr attributeUse = attributeUses.at(i);
+ if (attributeUse->isAttributeUse()) {
+ // it is a real attribute use, so no need to resolve it
+ resolvedAttributeUses.append(attributeUse);
+ } else if (attributeUse->isReference()) {
+ // it is just a reference, so resolve it to the real attribute use
+
+ const XsdAttributeReference::Ptr reference = attributeUse;
+ if (reference->type() == XsdAttributeReference::AttributeUse) {
+
+ // lookup the real attribute
+ const XsdAttribute::Ptr attribute = m_schema->attribute(reference->referenceName());
+ if (!attribute) {
+ m_context->error(QtXmlPatterns::tr("reference %1 of %2 element cannot be resolved")
+ .arg(formatKeyword(m_namePool, reference->referenceName()))
+ .arg(formatElement("attribute")),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ return XsdAttributeUse::List();
+ }
+
+ // if both, reference and definition have a fixed or default value set, then they must be equal
+ if (attribute->valueConstraint() && attributeUse->valueConstraint()) {
+ if (attribute->valueConstraint()->value() != attributeUse->valueConstraint()->value()) {
+ m_context->error(QtXmlPatterns::tr("%1 or %2 attribute of reference %3 does not match with the attribute declaration %4")
+ .arg(formatAttribute("fixed"))
+ .arg(formatAttribute("default"))
+ .arg(formatKeyword(m_namePool, reference->referenceName()))
+ .arg(formatKeyword(attribute->displayName(m_namePool))),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ return XsdAttributeUse::List();
+ }
+ }
+
+ attributeUse->setAttribute(attribute);
+ if (!attributeUse->valueConstraint() && attribute->valueConstraint())
+ attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(attribute->valueConstraint()));
+
+ resolvedAttributeUses.append(attributeUse);
+ } else if (reference->type() == XsdAttributeReference::AttributeGroup) {
+ const XsdAttributeGroup::Ptr attributeGroup = m_schema->attributeGroup(reference->referenceName());
+ if (!attributeGroup) {
+ m_context->error(QtXmlPatterns::tr("reference %1 of %2 element cannot be resolved")
+ .arg(formatKeyword(m_namePool, reference->referenceName()))
+ .arg(formatElement("attributeGroup")),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ return XsdAttributeUse::List();
+ }
+ if (visitedAttributeGroups.contains(attributeGroup->name(m_namePool))) {
+ m_context->error(QtXmlPatterns::tr("attribute group %1 has circular reference").arg(formatKeyword(m_namePool, reference->referenceName())),
+ XsdSchemaContext::XSDError, reference->sourceLocation());
+ return XsdAttributeUse::List();
+ } else {
+ visitedAttributeGroups.insert(attributeGroup->name(m_namePool));
+ }
+
+ // resolve attribute wildcards as defined in http://www.w3.org/TR/xmlschema11-1/#declare-attributeGroup-wildcard
+ XsdWildcard::Ptr childWildcard;
+ resolvedAttributeUses << resolveAttributeTermReferences(attributeGroup->attributeUses(), childWildcard, visitedAttributeGroups);
+ if (!childWildcard) {
+ if (attributeGroup->wildcard()) {
+ if (wildcard) {
+ const XsdWildcard::ProcessContents contents = wildcard->processContents();
+ wildcard = XsdSchemaHelper::wildcardIntersection(wildcard, attributeGroup->wildcard());
+ wildcard->setProcessContents(contents);
+ } else {
+ wildcard = attributeGroup->wildcard();
+ }
+ }
+ } else {
+ XsdWildcard::Ptr newWildcard;
+ if (attributeGroup->wildcard()) {
+ const XsdWildcard::ProcessContents contents = attributeGroup->wildcard()->processContents();
+ newWildcard = XsdSchemaHelper::wildcardIntersection(attributeGroup->wildcard(), childWildcard);
+ newWildcard->setProcessContents(contents);
+ } else {
+ newWildcard = childWildcard;
+ }
+
+ if (wildcard) {
+ const XsdWildcard::ProcessContents contents = wildcard->processContents();
+ wildcard = XsdSchemaHelper::wildcardIntersection(wildcard, newWildcard);
+ wildcard->setProcessContents(contents);
+ } else {
+ wildcard = newWildcard;
+ }
+ }
+ }
+ }
+ }
+
+ return resolvedAttributeUses;
+}
+
+void XsdSchemaResolver::resolveAttributeInheritance()
+{
+ // collect the global and anonymous complex types
+ SchemaType::List types = m_schema->types();
+ types << m_schema->anonymousTypes();
+
+ QSet<XsdComplexType::Ptr> visitedTypes;
+ for (int i = 0; i < types.count(); ++i) {
+ if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema())
+ continue;
+
+ const XsdComplexType::Ptr complexType = types.at(i);
+
+ resolveAttributeInheritance(complexType, visitedTypes);
+ }
+}
+
+bool isValidWildcardRestriction(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &baseWildcard)
+{
+ if (wildcard->namespaceConstraint()->variety() == baseWildcard->namespaceConstraint()->variety()) {
+ if (!XsdSchemaHelper::checkWildcardProcessContents(baseWildcard, wildcard))
+ return false;
+ }
+
+ if (wildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Any &&
+ baseWildcard->namespaceConstraint()->variety() != XsdWildcard::NamespaceConstraint::Any ) {
+ return false;
+ }
+ if (baseWildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Not &&
+ wildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Enumeration) {
+ if (!baseWildcard->namespaceConstraint()->namespaces().intersect(wildcard->namespaceConstraint()->namespaces()).isEmpty())
+ return false;
+ }
+ if (baseWildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Enumeration &&
+ wildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Enumeration) {
+ if (!wildcard->namespaceConstraint()->namespaces().subtract(baseWildcard->namespaceConstraint()->namespaces()).isEmpty())
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Since we inherit the attributes from our base class we have to walk up in the
+ * inheritance hierarchy first and resolve the attribute inheritance top-down.
+ */
+void XsdSchemaResolver::resolveAttributeInheritance(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes)
+{
+ if (visitedTypes.contains(complexType))
+ return;
+ else
+ visitedTypes.insert(complexType);
+
+ const SchemaType::Ptr baseType = complexType->wxsSuperType();
+ Q_ASSERT(baseType);
+
+ if (!(baseType->isComplexType()) || !baseType->isDefinedBySchema())
+ return;
+
+ const XsdComplexType::Ptr complexBaseType = baseType;
+
+ resolveAttributeInheritance(complexBaseType, visitedTypes);
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.attuses
+
+ // 1 and 2 (the attribute groups have been resolved here already)
+ const XsdAttributeUse::List uses = complexBaseType->attributeUses();
+
+ if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) { // 3.2
+ const XsdAttributeUse::List currentUses = complexType->attributeUses();
+
+ // 3.2.1 and 3.2.2 As we also keep the prohibited attributes as objects, the algorithm below
+ // handles both the same way
+
+ // add only these attribute uses of the base type that match one of the following criteria:
+ // 1: there is no attribute use with the same name in type
+ // 2: there is no attribute with the same name marked as prohibited in type
+ for (int j = 0; j < uses.count(); ++j) {
+ const XsdAttributeUse::Ptr use = uses.at(j);
+ bool found = false;
+ for (int k = 0; k < currentUses.count(); ++k) {
+ if (use->attribute()->name(m_namePool) == currentUses.at(k)->attribute()->name(m_namePool)) {
+ found = true;
+
+ // check if prohibited usage is violated
+ if ((use->useType() == XsdAttributeUse::ProhibitedUse) && (currentUses.at(k)->useType() != XsdAttributeUse::ProhibitedUse)) {
+ m_context->error(QtXmlPatterns::tr("%1 attribute in %2 must have %3 use like in base type %4")
+ .arg(formatAttribute(use->attribute()->displayName(m_namePool)))
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatData("prohibited"))
+ .arg(formatType(m_namePool, complexBaseType)),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+
+ break;
+ }
+ }
+
+ if (!found && uses.at(j)->useType() != XsdAttributeUse::ProhibitedUse) {
+ complexType->addAttributeUse(uses.at(j));
+ }
+ }
+ } else if (complexType->derivationMethod() == XsdComplexType::DerivationExtension) { // 3.1
+ QHash<QXmlName, XsdAttributeUse::Ptr> availableUses;
+
+ // fill hash with attribute uses of current type for faster lookup
+ {
+ const XsdAttributeUse::List attributeUses = complexType->attributeUses();
+
+ for (int i = 0; i < attributeUses.count(); ++i) {
+ availableUses.insert(attributeUses.at(i)->attribute()->name(m_namePool), attributeUses.at(i));
+ }
+ }
+
+ // just add the attribute uses of the base type
+ for (int i = 0; i < uses.count(); ++i) {
+ const XsdAttributeUse::Ptr currentAttributeUse = uses.at(i);
+
+ // if the base type defines the attribute as prohibited but we override it in current type, then don't copy the prohibited attribute use
+ if ((currentAttributeUse->useType() == XsdAttributeUse::ProhibitedUse) && availableUses.contains(currentAttributeUse->attribute()->name(m_namePool)))
+ continue;
+
+ complexType->addAttributeUse(uses.at(i));
+ }
+ }
+
+ // handle attribute wildcards: @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.anyatt
+
+ // 1
+ const XsdWildcard::Ptr completeWildcard(complexType->attributeWildcard());
+
+ if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) {
+ if (complexType->wxsSuperType()->isComplexType() && complexType->wxsSuperType()->isDefinedBySchema()) {
+ const XsdComplexType::Ptr complexBaseType(complexType->wxsSuperType());
+ if (complexType->attributeWildcard()) {
+ if (complexBaseType->attributeWildcard()) {
+ if (!isValidWildcardRestriction(complexType->attributeWildcard(), complexBaseType->attributeWildcard())) {
+ m_context->error(QtXmlPatterns::tr("attribute wildcard of %1 is not a valid restriction of attribute wildcard of base type %2")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, complexBaseType)),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+ } else {
+ m_context->error(QtXmlPatterns::tr("%1 has attribute wildcard but its base type %2 has not")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, complexBaseType)),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+ }
+ }
+ complexType->setAttributeWildcard(completeWildcard); // 2.1
+ } else if (complexType->derivationMethod() == XsdComplexType::DerivationExtension) {
+ XsdWildcard::Ptr baseWildcard; // 2.2.1
+ if (complexType->wxsSuperType()->isComplexType() && complexType->wxsSuperType()->isDefinedBySchema())
+ baseWildcard = XsdComplexType::Ptr(complexType->wxsSuperType())->attributeWildcard(); // 2.2.1.1
+ else
+ baseWildcard = XsdWildcard::Ptr(); // 2.2.1.2
+
+ if (!baseWildcard) {
+ complexType->setAttributeWildcard(completeWildcard); // 2.2.2.1
+ } else if (!completeWildcard) {
+ complexType->setAttributeWildcard(baseWildcard); // 2.2.2.2
+ } else {
+ XsdWildcard::Ptr unionWildcard = XsdSchemaHelper::wildcardUnion(completeWildcard, baseWildcard);
+ if (unionWildcard) {
+ unionWildcard->setProcessContents(completeWildcard->processContents());
+ complexType->setAttributeWildcard(unionWildcard); // 2.2.2.3
+ } else {
+ m_context->error(QtXmlPatterns::tr("union of attribute wildcard of type %1 and attribute wildcard of its base type %2 is not expressible")
+ .arg(formatType(m_namePool, complexType))
+ .arg(formatType(m_namePool, complexBaseType)),
+ XsdSchemaContext::XSDError, sourceLocation(complexType));
+ return;
+ }
+ }
+ }
+}
+
+void XsdSchemaResolver::resolveEnumerationFacetValues()
+{
+ XsdSimpleType::List simpleTypes;
+
+ // first collect the global simple types
+ const SchemaType::List types = m_schema->types();
+ for (int i = 0; i < types.count(); ++i) {
+ if (types.at(i)->isSimpleType())
+ simpleTypes.append(types.at(i));
+ }
+
+ // then collect all anonymous simple types
+ const SchemaType::List anonymousTypes = m_schema->anonymousTypes();
+ for (int i = 0; i < anonymousTypes.count(); ++i) {
+ if (anonymousTypes.at(i)->isSimpleType())
+ simpleTypes.append(anonymousTypes.at(i));
+ }
+ // process all simple types
+ for (int i = 0; i < simpleTypes.count(); ++i) {
+ const XsdSimpleType::Ptr simpleType = simpleTypes.at(i);
+
+ // we resolve the enumeration values only for xs:QName and xs:NOTATION based types
+ if (BuiltinTypes::xsQName->wxsTypeMatches(simpleType) ||
+ BuiltinTypes::xsNOTATION->wxsTypeMatches(simpleType)) {
+ const XsdFacet::Hash facets = simpleType->facets();
+ if (facets.contains(XsdFacet::Enumeration)) {
+ AtomicValue::List newValues;
+
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const AtomicValue::List values = facet->multiValue();
+ for (int j = 0; j < values.count(); ++j) {
+ const AtomicValue::Ptr value = values.at(j);
+
+ Q_ASSERT(m_enumerationFacetValues.contains(value));
+ const NamespaceSupport support( m_enumerationFacetValues.value(value) );
+
+ const QString qualifiedName = value->as<DerivedString<TypeString> >()->stringValue();
+ if (!XPathHelper::isQName(qualifiedName)) {
+ m_context->error(QtXmlPatterns::tr("enumeration facet contains invalid content: {%1} is not a value of type %2")
+ .arg(formatData(qualifiedName))
+ .arg(formatType(m_namePool, BuiltinTypes::xsQName)),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+
+ QXmlName qNameValue;
+ bool result = support.processName(qualifiedName, NamespaceSupport::ElementName, qNameValue);
+ if (!result) {
+ m_context->error(QtXmlPatterns::tr("namespace prefix of qualified name %1 is not defined").arg(formatData(qualifiedName)),
+ XsdSchemaContext::XSDError, sourceLocation(simpleType));
+ return;
+ }
+
+ newValues.append(QNameValue::fromValue(m_namePool, qNameValue));
+ }
+ facet->setMultiValue(newValues);
+ }
+ }
+ }
+}
+
+QSourceLocation XsdSchemaResolver::sourceLocation(const NamedSchemaComponent::Ptr component) const
+{
+ if (m_componentLocationHash.contains(component)) {
+ return m_componentLocationHash.value(component);
+ } else {
+ QSourceLocation location;
+ location.setLine(1);
+ location.setColumn(1);
+ location.setUri(QString::fromLatin1("dummyUri"));
+
+ return location;
+ }
+}
+
+XsdFacet::Hash XsdSchemaResolver::complexTypeFacets(const XsdComplexType::Ptr &complexType) const
+{
+ for (int i = 0; i < m_complexBaseTypes.count(); ++i) {
+ if (m_complexBaseTypes.at(i).complexType == complexType)
+ return m_complexBaseTypes.at(i).facets;
+ }
+
+ return XsdFacet::Hash();
+}
+
+void XsdSchemaResolver::checkRedefinedGroups()
+{
+ for (int i = 0; i < m_redefinedGroups.count(); ++i) {
+ const RedefinedGroups item = m_redefinedGroups.at(i);
+
+ // create dummy particles...
+ const XsdParticle::Ptr redefinedParticle(new XsdParticle());
+ redefinedParticle->setTerm(item.redefinedGroup);
+ const XsdParticle::Ptr particle(new XsdParticle());
+ particle->setTerm(item.group);
+
+ // so that we can pass them to XsdParticleChecker::subsumes()
+ QString errorMsg;
+ if (!XsdParticleChecker::subsumes(particle, redefinedParticle, m_context, errorMsg)) {
+ m_context->error(QtXmlPatterns::tr("%1 element %2 is not a valid restriction of the %3 element it redefines: %4")
+ .arg(formatElement("group"))
+ .arg(formatData(item.redefinedGroup->displayName(m_namePool)))
+ .arg(formatElement("group"))
+ .arg(errorMsg),
+ XsdSchemaContext::XSDError, sourceLocation(item.redefinedGroup));
+ return;
+ }
+ }
+}
+
+void XsdSchemaResolver::checkRedefinedAttributeGroups()
+{
+ for (int i = 0; i < m_redefinedAttributeGroups.count(); ++i) {
+ const RedefinedAttributeGroups item = m_redefinedAttributeGroups.at(i);
+
+ QString errorMsg;
+ if (!XsdSchemaHelper::isValidAttributeGroupRestriction(item.redefinedGroup, item.group, m_context, errorMsg)) {
+ m_context->error(QtXmlPatterns::tr("%1 element %2 is not a valid restriction of the %3 element it redefines: %4")
+ .arg(formatElement("attributeGroup"))
+ .arg(formatData(item.redefinedGroup->displayName(m_namePool)))
+ .arg(formatElement("attributeGroup"))
+ .arg(errorMsg),
+ XsdSchemaContext::XSDError, sourceLocation(item.redefinedGroup));
+ return;
+ }
+ }
+}
+
+AnySimpleType::Ptr XsdSchemaResolver::findPrimitiveType(const AnySimpleType::Ptr &type, QSet<AnySimpleType::Ptr> &visitedTypes)
+{
+ if (visitedTypes.contains(type)) {
+ // found invalid circular reference...
+ return AnySimpleType::Ptr();
+ } else {
+ visitedTypes.insert(type);
+ }
+
+ const QXmlName typeName = type->name(m_namePool);
+ if (typeName == BuiltinTypes::xsString->name(m_namePool) ||
+ typeName == BuiltinTypes::xsBoolean->name(m_namePool) ||
+ typeName == BuiltinTypes::xsFloat->name(m_namePool) ||
+ typeName == BuiltinTypes::xsDouble->name(m_namePool) ||
+ typeName == BuiltinTypes::xsDecimal->name(m_namePool) ||
+ typeName == BuiltinTypes::xsDuration->name(m_namePool) ||
+ typeName == BuiltinTypes::xsDateTime->name(m_namePool) ||
+ typeName == BuiltinTypes::xsTime->name(m_namePool) ||
+ typeName == BuiltinTypes::xsDate->name(m_namePool) ||
+ typeName == BuiltinTypes::xsGYearMonth->name(m_namePool) ||
+ typeName == BuiltinTypes::xsGYear->name(m_namePool) ||
+ typeName == BuiltinTypes::xsGMonthDay->name(m_namePool) ||
+ typeName == BuiltinTypes::xsGDay->name(m_namePool) ||
+ typeName == BuiltinTypes::xsGMonth->name(m_namePool) ||
+ typeName == BuiltinTypes::xsHexBinary->name(m_namePool) ||
+ typeName == BuiltinTypes::xsBase64Binary->name(m_namePool) ||
+ typeName == BuiltinTypes::xsAnyURI->name(m_namePool) ||
+ typeName == BuiltinTypes::xsQName->name(m_namePool) ||
+ typeName == BuiltinTypes::xsNOTATION->name(m_namePool) ||
+ typeName == BuiltinTypes::xsAnySimpleType->name(m_namePool))
+ return type;
+ else {
+ if (type->wxsSuperType())
+ return findPrimitiveType(type->wxsSuperType(), visitedTypes);
+ else {
+ return AnySimpleType::Ptr();
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschemaresolver_p.h b/src/xmlpatterns/schema/qxsdschemaresolver_p.h
new file mode 100644
index 0000000000..12226193f8
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschemaresolver_p.h
@@ -0,0 +1,548 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchemaResolver_H
+#define Patternist_XsdSchemaResolver_H
+
+#include "qnamespacesupport_p.h"
+#include "qschematype_p.h"
+#include "qschematypefactory_p.h"
+#include "qxsdalternative_p.h"
+#include "qxsdattribute_p.h"
+#include "qxsdattributegroup_p.h"
+#include "qxsdelement_p.h"
+#include "qxsdmodelgroup_p.h"
+#include "qxsdnotation_p.h"
+#include "qxsdreference_p.h"
+#include "qxsdschema_p.h"
+#include "qxsdschemachecker_p.h"
+#include "qxsdsimpletype_p.h"
+
+#include <QtCore/QExplicitlySharedDataPointer>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ class XsdSchemaContext;
+ class XsdSchemaParserContext;
+
+ /**
+ * @short Encapsulates the resolving of type/element references in a schema after parsing has finished.
+ *
+ * This class collects task for resolving types or element references. After the parsing has finished,
+ * one can start the resolve process by calling resolve().
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSchemaResolver : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdSchemaResolver> Ptr;
+
+ /**
+ * Creates a new schema resolver.
+ *
+ * @param context The schema context used for error reporting etc..
+ * @param parserContext The schema parser context where all objects to resolve belong to.
+ */
+ XsdSchemaResolver(const QExplicitlySharedDataPointer<XsdSchemaContext> &context, const XsdSchemaParserContext *parserContext);
+
+ /**
+ * Destroys the schema resolver.
+ */
+ ~XsdSchemaResolver();
+
+ /**
+ * Starts the resolve process.
+ */
+ void resolve();
+
+ /**
+ * Adds a resolve task for key references.
+ *
+ * The resolver will try to set the referencedKey property of @p keyRef to the <em>key</em> or <em>unique</em> object
+ * of @p element that has the given @p name.
+ */
+ void addKeyReference(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &keyRef, const QXmlName &name, const QSourceLocation &location);
+
+ /**
+ * Adds a resolve task for the base type of restriction of a simple type.
+ *
+ * The resolver will set the base type of @p simpleType to the type named by @p baseName.
+ */
+ void addSimpleRestrictionBase(const XsdSimpleType::Ptr &simpleType, const QXmlName &baseName, const QSourceLocation &location);
+
+ /**
+ * Removes the resolve task for the base type of restriction of the simple @p type.
+ */
+ void removeSimpleRestrictionBase(const XsdSimpleType::Ptr &type);
+
+ /**
+ * Adds a resolve task for the list type of a simple type.
+ *
+ * The resolver will set the itemType property of @p simpleType to the type named by @p typeName.
+ */
+ void addSimpleListType(const XsdSimpleType::Ptr &simpleType, const QXmlName &typeName, const QSourceLocation &location);
+
+ /**
+ * Adds a resolve task for the member types of a simple type.
+ *
+ * The resolver will set the memberTypes property of @p simpleType to the types named by @p typeNames.
+ */
+ void addSimpleUnionTypes(const XsdSimpleType::Ptr &simpleType, const QList<QXmlName> &typeNames, const QSourceLocation &location);
+
+ /**
+ * Adds a resolve task for the type of an element.
+ *
+ * The resolver will set the type of the @p element to the type named by @p typeName.
+ */
+ void addElementType(const XsdElement::Ptr &element, const QXmlName &typeName, const QSourceLocation &location);
+
+ /**
+ * Adds a resolve task for the base type of a complex type.
+ *
+ * The resolver will set the base type of @p complexType to the type named by @p baseName.
+ */
+ void addComplexBaseType(const XsdComplexType::Ptr &complexType, const QXmlName &baseName, const QSourceLocation &location, const XsdFacet::Hash &facets = XsdFacet::Hash());
+
+ /**
+ * Removes the resolve task for the base type of the complex @p type.
+ */
+ void removeComplexBaseType(const XsdComplexType::Ptr &type);
+
+ /**
+ * Adds a resolve task for the content type of a complex type.
+ *
+ * The resolver will set the content type properties for @p complexType based on the
+ * given explicit @p content and effective @p mixed value.
+ */
+ void addComplexContentType(const XsdComplexType::Ptr &complexType, const XsdParticle::Ptr &content, bool mixed);
+
+ /**
+ * Adds a resolve task for the type of an attribute.
+ *
+ * The resolver will set the type of the @p attribute to the type named by @p typeName.
+ */
+ void addAttributeType(const XsdAttribute::Ptr &attribute, const QXmlName &typeName, const QSourceLocation &location);
+
+ /**
+ * Adds a resolve task for the type of an alternative.
+ *
+ * The resolver will set the type of the @p alternative to the type named by @p typeName.
+ */
+ void addAlternativeType(const XsdAlternative::Ptr &alternative, const QXmlName &typeName, const QSourceLocation &location);
+
+ /**
+ * Adds a resolve task for the type of an alternative.
+ *
+ * The resolver will set the type of the @p alternative to the type of the @p element after
+ * the type of the @p element has been resolved.
+ */
+ void addAlternativeType(const XsdAlternative::Ptr &alternative, const XsdElement::Ptr &element);
+
+ /**
+ * Adds a resolve task for the substituion group affiliations of an element.
+ *
+ * The resolver will set the substitution group affiliations of the @p element to the
+ * top-level element named by @p elementNames.
+ */
+ void addSubstitutionGroupAffiliation(const XsdElement::Ptr &element, const QList<QXmlName> &elementName, const QSourceLocation &location);
+
+ /**
+ * Adds a resolve task for an element that has no type specified, only a substitution group
+ * affiliation.
+ *
+ * The resolver will set the type of the substitution group affiliation as type for the element.
+ */
+ void addSubstitutionGroupType(const XsdElement::Ptr &element);
+
+ /**
+ * Adds the component location hash, so the resolver is able to report meaning full
+ * error messages.
+ */
+ void addComponentLocationHash(const QHash<NamedSchemaComponent::Ptr, QSourceLocation> &hash);
+
+ /**
+ * Add a resolve task for enumeration facet values.
+ *
+ * In case the enumeration is of type QName or NOTATION, we have to resolve the QName later,
+ * so we store the namespace bindings together with the facet value here and resolve it as soon as
+ * we have all type information available.
+ */
+ void addEnumerationFacetValue(const AtomicValue::Ptr &facetValue, const NamespaceSupport &namespaceSupport);
+
+ /**
+ * Add a check job for redefined groups.
+ *
+ * When an element group is redefined, we have to check whether the redefined group is a valid
+ * restriction of the group it redefines. As we need all type information for that, we keep them
+ * here for later checking.
+ */
+ void addRedefinedGroups(const XsdModelGroup::Ptr &redefinedGroup, const XsdModelGroup::Ptr &group);
+
+ /**
+ * Add a check job for redefined attribute groups.
+ *
+ * When an attribute group is redefined, we have to check whether the redefined group is a valid
+ * restriction of the group it redefines. As we need all type information for that, we keep them
+ * here for later checking.
+ */
+ void addRedefinedAttributeGroups(const XsdAttributeGroup::Ptr &redefinedGroup, const XsdAttributeGroup::Ptr &group);
+
+ /**
+ * Adds a check for nested <em>all</em> groups.
+ */
+ void addAllGroupCheck(const XsdReference::Ptr &reference);
+
+ /**
+ * Copies the data to resolve to an @p other resolver.
+ *
+ * @note That functionality is only used by the redefine algorithm in the XsdSchemaParser.
+ */
+ void copyDataTo(const XsdSchemaResolver::Ptr &other) const;
+
+ /**
+ * Returns the to resolve base type name for the given @p type.
+ *
+ * @note That functionality is only used by the redefine algorithm in the XsdSchemaParser.
+ */
+ QXmlName baseTypeNameOfType(const SchemaType::Ptr &type) const;
+
+ /**
+ * Returns the to resolve type name for the given @p attribute.
+ *
+ * @note That functionality is only used by the redefine algorithm in the XsdSchemaParser.
+ */
+ QXmlName typeNameOfAttribute(const XsdAttribute::Ptr &attribute) const;
+
+ /**
+ * Sets the defaultOpenContent object from the schema parser.
+ */
+ void setDefaultOpenContent(const XsdComplexType::OpenContent::Ptr &openContent, bool appliesToEmpty);
+
+ private:
+ /**
+ * Resolves key references.
+ */
+ void resolveKeyReferences();
+
+ /**
+ * Resolves the base types of simple types derived by restriction.
+ */
+ void resolveSimpleRestrictionBaseTypes();
+
+ /**
+ * Resolves the other properties except the base type
+ * of all simple restrictions.
+ */
+ void resolveSimpleRestrictions();
+
+ /**
+ * Resolves the other properties except the base type
+ * of the given simple restriction.
+ *
+ * @param simpleType The restricted type to resolve.
+ * @param visitedTypes A set of already resolved types, used for termination of recursion.
+ */
+ void resolveSimpleRestrictions(const XsdSimpleType::Ptr &simpleType, QSet<XsdSimpleType::Ptr> &visitedTypes);
+
+ /**
+ * Resolves the item type property of simple types derived by list.
+ */
+ void resolveSimpleListType();
+
+ /**
+ * Resolves the member types property of simple types derived by union.
+ */
+ void resolveSimpleUnionTypes();
+
+ /**
+ * Resolves element types.
+ */
+ void resolveElementTypes();
+
+ /**
+ * Resolves base type of complex types.
+ */
+ void resolveComplexBaseTypes();
+
+ /**
+ * Resolves the simple content model of a complex type
+ * depending on its base type.
+ */
+ void resolveSimpleContentComplexTypes();
+
+ /**
+ * Resolves the complex content model of a complex type
+ * depending on its base type.
+ */
+ void resolveComplexContentComplexTypes();
+
+ /**
+ * Resolves the simple content model of a complex type
+ * depending on its base type.
+ *
+ * @param complexType The complex type to resolve.
+ * @param visitedTypes A set of already resolved types, used for termination of recursion.
+ */
+ void resolveSimpleContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes);
+
+ /**
+ * Resolves the complex content model of a complex type
+ * depending on its base type.
+ *
+ * @param complexType The complex type to resolve.
+ * @param visitedTypes A set of already resolved types, used for termination of recursion.
+ */
+ void resolveComplexContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes);
+
+ /**
+ * Resolves attribute types.
+ */
+ void resolveAttributeTypes();
+
+ /**
+ * Resolves alternative types.
+ */
+ void resolveAlternativeTypes();
+
+ /**
+ * Resolves substitution group affiliations.
+ */
+ void resolveSubstitutionGroupAffiliations();
+
+ /**
+ * Resolves substitution groups.
+ */
+ void resolveSubstitutionGroups();
+
+ /**
+ * Resolves all XsdReferences in the schema by their corresponding XsdElement or XsdModelGroup terms.
+ */
+ void resolveTermReferences();
+
+ /**
+ * Resolves all XsdReferences in the @p particle recursive by their corresponding XsdElement or XsdModelGroup terms.
+ */
+ void resolveTermReference(const XsdParticle::Ptr &particle, QSet<QXmlName> visitedGroups);
+
+ /**
+ * Resolves all XsdAttributeReferences in the schema by their corresponding XsdAttributeUse objects.
+ */
+ void resolveAttributeTermReferences();
+
+ /**
+ * Resolves all XsdAttributeReferences in the list of @p attributeUses by their corresponding XsdAttributeUse objects.
+ */
+ XsdAttributeUse::List resolveAttributeTermReferences(const XsdAttributeUse::List &attributeUses, XsdWildcard::Ptr &wildcard, QSet<QXmlName> visitedAttributeGroups);
+
+ /**
+ * Resolves the attribute inheritance of complex types.
+ *
+ * @note This method must be called after all base types have been resolved.
+ */
+ void resolveAttributeInheritance();
+
+ /**
+ * Resolves the attribute inheritance of the given complex types.
+ *
+ * @param complexType The complex type to resolve.
+ * @param visitedTypes A set of already resolved types, used for termination of recursion.
+ *
+ * @note This method must be called after all base types have been resolved.
+ */
+ void resolveAttributeInheritance(const XsdComplexType::Ptr &complexType, QSet<XsdComplexType::Ptr> &visitedTypes);
+
+ /**
+ * Resolves the enumeration facet values for QName and NOTATION based facets.
+ */
+ void resolveEnumerationFacetValues();
+
+ /**
+ * Returns the source location of the given schema @p component or a dummy
+ * source location if the component is not found in the component location hash.
+ */
+ QSourceLocation sourceLocation(const NamedSchemaComponent::Ptr component) const;
+
+ /**
+ * Returns the facets that are marked for the given complex @p type with a simple
+ * type restriction.
+ */
+ XsdFacet::Hash complexTypeFacets(const XsdComplexType::Ptr &complexType) const;
+
+ /**
+ * Finds the primitive type for the given simple @p type.
+ *
+ * The type is found by walking up the inheritance tree, until one of the builtin
+ * primitive type definitions is reached.
+ */
+ AnySimpleType::Ptr findPrimitiveType(const AnySimpleType::Ptr &type, QSet<AnySimpleType::Ptr> &visitedTypes);
+
+ /**
+ * Checks the redefined groups.
+ */
+ void checkRedefinedGroups();
+
+ /**
+ * Checks the redefined attribute groups.
+ */
+ void checkRedefinedAttributeGroups();
+
+ class KeyReference
+ {
+ public:
+ XsdElement::Ptr element;
+ XsdIdentityConstraint::Ptr keyRef;
+ QXmlName reference;
+ QSourceLocation location;
+ };
+
+ class SimpleRestrictionBase
+ {
+ public:
+ XsdSimpleType::Ptr simpleType;
+ QXmlName baseName;
+ QSourceLocation location;
+ };
+
+ class SimpleListType
+ {
+ public:
+ XsdSimpleType::Ptr simpleType;
+ QXmlName typeName;
+ QSourceLocation location;
+ };
+
+ class SimpleUnionType
+ {
+ public:
+ XsdSimpleType::Ptr simpleType;
+ QList<QXmlName> typeNames;
+ QSourceLocation location;
+ };
+
+ class ElementType
+ {
+ public:
+ XsdElement::Ptr element;
+ QXmlName typeName;
+ QSourceLocation location;
+ };
+
+ class ComplexBaseType
+ {
+ public:
+ XsdComplexType::Ptr complexType;
+ QXmlName baseName;
+ QSourceLocation location;
+ XsdFacet::Hash facets;
+ };
+
+ class ComplexContentType
+ {
+ public:
+ XsdComplexType::Ptr complexType;
+ XsdParticle::Ptr explicitContent;
+ bool effectiveMixed;
+ };
+
+ class AttributeType
+ {
+ public:
+ XsdAttribute::Ptr attribute;
+ QXmlName typeName;
+ QSourceLocation location;
+ };
+
+ class AlternativeType
+ {
+ public:
+ XsdAlternative::Ptr alternative;
+ QXmlName typeName;
+ QSourceLocation location;
+ };
+
+ class AlternativeTypeElement
+ {
+ public:
+ XsdAlternative::Ptr alternative;
+ XsdElement::Ptr element;
+ };
+
+ class SubstitutionGroupAffiliation
+ {
+ public:
+ XsdElement::Ptr element;
+ QList<QXmlName> elementNames;
+ QSourceLocation location;
+ };
+
+ class RedefinedGroups
+ {
+ public:
+ XsdModelGroup::Ptr redefinedGroup;
+ XsdModelGroup::Ptr group;
+ };
+
+ class RedefinedAttributeGroups
+ {
+ public:
+ XsdAttributeGroup::Ptr redefinedGroup;
+ XsdAttributeGroup::Ptr group;
+ };
+
+ QVector<KeyReference> m_keyReferences;
+ QVector<SimpleRestrictionBase> m_simpleRestrictionBases;
+ QVector<SimpleListType> m_simpleListTypes;
+ QVector<SimpleUnionType> m_simpleUnionTypes;
+ QVector<ElementType> m_elementTypes;
+ QVector<ComplexBaseType> m_complexBaseTypes;
+ QVector<ComplexContentType> m_complexContentTypes;
+ QVector<AttributeType> m_attributeTypes;
+ QVector<AlternativeType> m_alternativeTypes;
+ QVector<AlternativeTypeElement> m_alternativeTypeElements;
+ QVector<SubstitutionGroupAffiliation> m_substitutionGroupAffiliations;
+ QVector<XsdElement::Ptr> m_substitutionGroupTypes;
+ QVector<RedefinedGroups> m_redefinedGroups;
+ QVector<RedefinedAttributeGroups> m_redefinedAttributeGroups;
+ QHash<AtomicValue::Ptr, NamespaceSupport> m_enumerationFacetValues;
+ QSet<XsdReference::Ptr> m_allGroups;
+
+ QExplicitlySharedDataPointer<XsdSchemaContext> m_context;
+ QExplicitlySharedDataPointer<XsdSchemaChecker> m_checker;
+ NamePool::Ptr m_namePool;
+ XsdSchema::Ptr m_schema;
+ QHash<NamedSchemaComponent::Ptr, QSourceLocation> m_componentLocationHash;
+ XsdComplexType::OpenContent::Ptr m_defaultOpenContent;
+ bool m_defaultOpenContentAppliesToEmpty;
+ SchemaType::List m_predefinedSchemaTypes;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschematoken.cpp b/src/xmlpatterns/schema/qxsdschematoken.cpp
new file mode 100644
index 0000000000..b527de6fdd
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschematoken.cpp
@@ -0,0 +1,2951 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+/* NOTE: This file is AUTO GENERATED by qautomaton2cpp.xsl. */
+
+#include "qxsdschematoken_p.h"
+
+QT_BEGIN_NAMESPACE
+
+XsdSchemaToken::NodeName XsdSchemaToken::classifier2(const QChar *data)
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 105, 100
+ };
+ if(memcmp(&data[0], &string, sizeof(QChar) * 2) == 0)
+
+
+ return Id;
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier3(const QChar *data)
+
+ {
+ if (data[0] == 97)
+
+
+ {
+ if (data[1] == 108)
+
+
+ {
+
+ if(data[2] == 108)
+
+
+ return All;
+
+ }
+
+ else if (data[1] == 110)
+
+
+ {
+
+ if(data[2] == 121)
+
+
+ return Any;
+
+ }
+
+
+ }
+
+ else if (data[0] == 107)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 121
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 2) == 0)
+
+
+ return Key;
+
+ }
+
+ else if (data[0] == 114)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 102
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 2) == 0)
+
+
+ return Ref;
+
+ }
+
+ else if (data[0] == 117)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 115, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 2) == 0)
+
+
+ return Use;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier4(const QChar *data)
+
+ {
+ if (data[0] == 98)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 97, 115, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0)
+
+
+ return Base;
+
+ }
+
+ else if (data[0] == 102)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 111, 114, 109
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0)
+
+
+ return Form;
+
+ }
+
+ else if (data[0] == 108)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 105, 115, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0)
+
+
+ return List;
+
+ }
+
+ else if (data[0] == 109)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 111, 100, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0)
+
+
+ return Mode;
+
+ }
+
+ else if (data[0] == 110)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 97, 109, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0)
+
+
+ return Name;
+
+ }
+
+ else if (data[0] == 116)
+
+
+ {
+ if (data[1] == 101)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 115, 116
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 2) == 0)
+
+
+ return Test;
+
+ }
+
+ else if (data[1] == 121)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 112, 101
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 2) == 0)
+
+
+ return Type;
+
+ }
+
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier5(const QChar *data)
+
+ {
+ if (data[0] == 98)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 108, 111, 99, 107
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Block;
+
+ }
+
+ else if (data[0] == 102)
+
+
+ {
+ if (data[1] == 105)
+
+
+ {
+ if (data[2] == 101)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 108, 100
+ };
+ if(memcmp(&data[3], &string, sizeof(QChar) * 2) == 0)
+
+
+ return Field;
+
+ }
+
+ else if (data[2] == 110)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 97, 108
+ };
+ if(memcmp(&data[3], &string, sizeof(QChar) * 2) == 0)
+
+
+ return Final;
+
+ }
+
+ else if (data[2] == 120)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 100
+ };
+ if(memcmp(&data[3], &string, sizeof(QChar) * 2) == 0)
+
+
+ return Fixed;
+
+ }
+
+
+ }
+
+
+ }
+
+ else if (data[0] == 103)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 114, 111, 117, 112
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Group;
+
+ }
+
+ else if (data[0] == 109)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 105, 120, 101, 100
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Mixed;
+
+ }
+
+ else if (data[0] == 114)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 102, 101, 114
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Refer;
+
+ }
+
+ else if (data[0] == 117)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 110, 105, 111, 110
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Union;
+
+ }
+
+ else if (data[0] == 118)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 97, 108, 117, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Value;
+
+ }
+
+ else if (data[0] == 120)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 112, 97, 116, 104
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Xpath;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier6(const QChar *data)
+
+ {
+ if (data[0] == 97)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 115, 115, 101, 114, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0)
+
+
+ return Assert;
+
+ }
+
+ else if (data[0] == 99)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 104, 111, 105, 99, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0)
+
+
+ return Choice;
+
+ }
+
+ else if (data[0] == 105)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 109, 112, 111, 114, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0)
+
+
+ return Import;
+
+ }
+
+ else if (data[0] == 107)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 121, 114, 101, 102
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0)
+
+
+ return Keyref;
+
+ }
+
+ else if (data[0] == 108)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 110, 103, 116, 104
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0)
+
+
+ return Length;
+
+ }
+
+ else if (data[0] == 112)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 117, 98, 108, 105, 99
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0)
+
+
+ return Public;
+
+ }
+
+ else if (data[0] == 115)
+
+
+ {
+ if (data[1] == 99)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 104, 101, 109, 97
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Schema;
+
+ }
+
+ else if (data[1] == 111)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 117, 114, 99, 101
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Source;
+
+ }
+
+ else if (data[1] == 121)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 115, 116, 101, 109
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 4) == 0)
+
+
+ return System;
+
+ }
+
+
+ }
+
+ else if (data[0] == 117)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 110, 105, 113, 117, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0)
+
+
+ return Unique;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier7(const QChar *data)
+
+ {
+ if (data[0] == 97)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 112, 112, 105, 110, 102, 111
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0)
+
+
+ return Appinfo;
+
+ }
+
+ else if (data[0] == 100)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 102, 97, 117, 108, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0)
+
+
+ return Default;
+
+ }
+
+ else if (data[0] == 101)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 108, 101, 109, 101, 110, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0)
+
+
+ return Element;
+
+ }
+
+ else if (data[0] == 105)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 110, 99, 108, 117, 100, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0)
+
+
+ return Include;
+
+ }
+
+ else if (data[0] == 112)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 97, 116, 116, 101, 114, 110
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0)
+
+
+ return Pattern;
+
+ }
+
+ else if (data[0] == 114)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 112, 108, 97, 99, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0)
+
+
+ return Replace;
+
+ }
+
+ else if (data[0] == 118)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 114, 115, 105, 111, 110
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0)
+
+
+ return Version;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier8(const QChar *data)
+
+ {
+ if (data[0] == 97)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 98, 115, 116, 114, 97, 99, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0)
+
+
+ return Abstract;
+
+ }
+
+ else if (data[0] == 99)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 111, 108, 108, 97, 112, 115, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0)
+
+
+ return Collapse;
+
+ }
+
+ else if (data[0] == 105)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 116, 101, 109, 84, 121, 112, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0)
+
+
+ return ItemType;
+
+ }
+
+ else if (data[0] == 110)
+
+
+ {
+ if (data[1] == 105)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 108, 108, 97, 98, 108, 101
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 6) == 0)
+
+
+ return Nillable;
+
+ }
+
+ else if (data[1] == 111)
+
+
+ {
+ if (data[2] == 116)
+
+
+ {
+ if (data[3] == 97)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 116, 105, 111, 110
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 4) == 0)
+
+
+ return Notation;
+
+ }
+
+ else if (data[3] == 81)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 78, 97, 109, 101
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 4) == 0)
+
+
+ return NotQName;
+
+ }
+
+
+ }
+
+
+ }
+
+
+ }
+
+ else if (data[0] == 111)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 118, 101, 114, 114, 105, 100, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0)
+
+
+ return Override;
+
+ }
+
+ else if (data[0] == 112)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 114, 101, 115, 101, 114, 118, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0)
+
+
+ return Preserve;
+
+ }
+
+ else if (data[0] == 114)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 100, 101, 102, 105, 110, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0)
+
+
+ return Redefine;
+
+ }
+
+ else if (data[0] == 115)
+
+
+ {
+ if (data[1] == 101)
+
+
+ {
+ if (data[2] == 108)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 99, 116, 111, 114
+ };
+ if(memcmp(&data[3], &string, sizeof(QChar) * 5) == 0)
+
+
+ return Selector;
+
+ }
+
+ else if (data[2] == 113)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 117, 101, 110, 99, 101
+ };
+ if(memcmp(&data[3], &string, sizeof(QChar) * 5) == 0)
+
+
+ return Sequence;
+
+ }
+
+
+ }
+
+
+ }
+
+ else if (data[0] == 120)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 109, 108, 58, 108, 97, 110, 103
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0)
+
+
+ return XmlLanguage;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier9(const QChar *data)
+
+ {
+ if (data[0] == 97)
+
+
+ {
+ if (data[1] == 115)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 115, 101, 114, 116, 105, 111, 110
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 7) == 0)
+
+
+ return Assertion;
+
+ }
+
+ else if (data[1] == 116)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 116, 114, 105, 98, 117, 116, 101
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 7) == 0)
+
+
+ return Attribute;
+
+ }
+
+
+ }
+
+ else if (data[0] == 101)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 120, 116, 101, 110, 115, 105, 111, 110
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 8) == 0)
+
+
+ return Extension;
+
+ }
+
+ else if (data[0] == 109)
+
+
+ {
+ if (data[1] == 97)
+
+
+ {
+ if (data[2] == 120)
+
+
+ {
+ if (data[3] == 76)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 110, 103, 116, 104
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 5) == 0)
+
+
+ return MaxLength;
+
+ }
+
+ else if (data[3] == 79)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 99, 99, 117, 114, 115
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 5) == 0)
+
+
+ return MaxOccurs;
+
+ }
+
+
+ }
+
+
+ }
+
+ else if (data[1] == 105)
+
+
+ {
+ if (data[2] == 110)
+
+
+ {
+ if (data[3] == 76)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 110, 103, 116, 104
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 5) == 0)
+
+
+ return MinLength;
+
+ }
+
+ else if (data[3] == 79)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 99, 99, 117, 114, 115
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 5) == 0)
+
+
+ return MinOccurs;
+
+ }
+
+
+ }
+
+
+ }
+
+
+ }
+
+ else if (data[0] == 110)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 97, 109, 101, 115, 112, 97, 99, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 8) == 0)
+
+
+ return Namespace;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier10(const QChar *data)
+
+ {
+ if (data[0] == 97)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 110, 110, 111, 116, 97, 116, 105, 111, 110
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 9) == 0)
+
+
+ return Annotation;
+
+ }
+
+ else if (data[0] == 115)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 105, 109, 112, 108, 101, 84, 121, 112, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 9) == 0)
+
+
+ return SimpleType;
+
+ }
+
+ else if (data[0] == 119)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 104, 105, 116, 101, 83, 112, 97, 99, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 9) == 0)
+
+
+ return WhiteSpace;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier11(const QChar *data)
+
+ {
+ if (data[0] == 97)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 108, 116, 101, 114, 110, 97, 116, 105, 118, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0)
+
+
+ return Alternative;
+
+ }
+
+ else if (data[0] == 99)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 111, 109, 112, 108, 101, 120, 84, 121, 112, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0)
+
+
+ return ComplexType;
+
+ }
+
+ else if (data[0] == 101)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 110, 117, 109, 101, 114, 97, 116, 105, 111, 110
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0)
+
+
+ return Enumeration;
+
+ }
+
+ else if (data[0] == 109)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 109, 98, 101, 114, 84, 121, 112, 101, 115
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0)
+
+
+ return MemberTypes;
+
+ }
+
+ else if (data[0] == 111)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 112, 101, 110, 67, 111, 110, 116, 101, 110, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0)
+
+
+ return OpenContent;
+
+ }
+
+ else if (data[0] == 114)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 115, 116, 114, 105, 99, 116, 105, 111, 110
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0)
+
+
+ return Restriction;
+
+ }
+
+ else if (data[0] == 116)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 111, 116, 97, 108, 68, 105, 103, 105, 116, 115
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0)
+
+
+ return TotalDigits;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier12(const QChar *data)
+
+ {
+ if (data[0] == 97)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 110, 121, 65, 116, 116, 114, 105, 98, 117, 116, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 11) == 0)
+
+
+ return AnyAttribute;
+
+ }
+
+ else if (data[0] == 98)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 108, 111, 99, 107, 68, 101, 102, 97, 117, 108, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 11) == 0)
+
+
+ return BlockDefault;
+
+ }
+
+ else if (data[0] == 102)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 105, 110, 97, 108, 68, 101, 102, 97, 117, 108, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 11) == 0)
+
+
+ return FinalDefault;
+
+ }
+
+ else if (data[0] == 109)
+
+
+ {
+ if (data[1] == 97)
+
+
+ {
+ if (data[2] == 120)
+
+
+ {
+ if (data[3] == 69)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 120, 99, 108, 117, 115, 105, 118, 101
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 8) == 0)
+
+
+ return MaxExclusive;
+
+ }
+
+ else if (data[3] == 73)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 110, 99, 108, 117, 115, 105, 118, 101
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 8) == 0)
+
+
+ return MaxInclusive;
+
+ }
+
+
+ }
+
+
+ }
+
+ else if (data[1] == 105)
+
+
+ {
+ if (data[2] == 110)
+
+
+ {
+ if (data[3] == 69)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 120, 99, 108, 117, 115, 105, 118, 101
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 8) == 0)
+
+
+ return MinExclusive;
+
+ }
+
+ else if (data[3] == 73)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 110, 99, 108, 117, 115, 105, 118, 101
+ };
+ if(memcmp(&data[4], &string, sizeof(QChar) * 8) == 0)
+
+
+ return MinInclusive;
+
+ }
+
+
+ }
+
+
+ }
+
+
+ }
+
+ else if (data[0] == 110)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 111, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 11) == 0)
+
+
+ return NotNamespace;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier13(const QChar *data)
+
+ {
+ if (data[0] == 100)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 12) == 0)
+
+
+ return Documentation;
+
+ }
+
+ else if (data[0] == 115)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 105, 109, 112, 108, 101, 67, 111, 110, 116, 101, 110, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 12) == 0)
+
+
+ return SimpleContent;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier14(const QChar *data)
+
+ {
+ if (data[0] == 97)
+
+
+ {
+ if (data[1] == 112)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 112, 108, 105, 101, 115, 84, 111, 69, 109, 112, 116, 121
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 12) == 0)
+
+
+ return AppliesToEmpty;
+
+ }
+
+ else if (data[1] == 116)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 116, 114, 105, 98, 117, 116, 101, 71, 114, 111, 117, 112
+ };
+ if(memcmp(&data[2], &string, sizeof(QChar) * 12) == 0)
+
+
+ return AttributeGroup;
+
+ }
+
+
+ }
+
+ else if (data[0] == 99)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 111, 109, 112, 108, 101, 120, 67, 111, 110, 116, 101, 110, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 13) == 0)
+
+
+ return ComplexContent;
+
+ }
+
+ else if (data[0] == 102)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 114, 97, 99, 116, 105, 111, 110, 68, 105, 103, 105, 116, 115
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 13) == 0)
+
+
+ return FractionDigits;
+
+ }
+
+ else if (data[0] == 115)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 99, 104, 101, 109, 97, 76, 111, 99, 97, 116, 105, 111, 110
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 13) == 0)
+
+
+ return SchemaLocation;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier15(const QChar *data)
+
+ {
+ if (data[0] == 112)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 114, 111, 99, 101, 115, 115, 67, 111, 110, 116, 101, 110, 116, 115
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 14) == 0)
+
+
+ return ProcessContents;
+
+ }
+
+ else if (data[0] == 116)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 97, 114, 103, 101, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 14) == 0)
+
+
+ return TargetNamespace;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier17(const QChar *data)
+
+ {
+ if (data[0] == 100)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 102, 97, 117, 108, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 16) == 0)
+
+
+ return DefaultAttributes;
+
+ }
+
+ else if (data[0] == 115)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 117, 98, 115, 116, 105, 116, 117, 116, 105, 111, 110, 71, 114, 111, 117, 112
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 16) == 0)
+
+
+ return SubstitutionGroup;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier18(const QChar *data)
+
+ {
+ if (data[0] == 100)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 101, 102, 97, 117, 108, 116, 79, 112, 101, 110, 67, 111, 110, 116, 101, 110, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 17) == 0)
+
+
+ return DefaultOpenContent;
+
+ }
+
+ else if (data[0] == 101)
+
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 108, 101, 109, 101, 110, 116, 70, 111, 114, 109, 68, 101, 102, 97, 117, 108, 116
+ };
+ if(memcmp(&data[1], &string, sizeof(QChar) * 17) == 0)
+
+
+ return ElementFormDefault;
+
+ }
+
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier20(const QChar *data)
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 97, 116, 116, 114, 105, 98, 117, 116, 101, 70, 111, 114, 109, 68, 101, 102, 97, 117, 108, 116
+ };
+ if(memcmp(&data[0], &string, sizeof(QChar) * 20) == 0)
+
+
+ return AttributeFormDefault;
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier21(const QChar *data)
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 120, 112, 97, 116, 104, 68, 101, 102, 97, 117, 108, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101
+ };
+ if(memcmp(&data[0], &string, sizeof(QChar) * 21) == 0)
+
+
+ return XPathDefaultNamespace;
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier22(const QChar *data)
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 100, 101, 102, 97, 117, 108, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 65, 112, 112, 108, 121
+ };
+ if(memcmp(&data[0], &string, sizeof(QChar) * 22) == 0)
+
+
+ return DefaultAttributesApply;
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::classifier32(const QChar *data)
+
+ {
+
+ static const unsigned short string[] =
+ {
+ 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 49, 47, 88, 77, 76, 83, 99, 104, 101, 109, 97
+ };
+ if(memcmp(&data[0], &string, sizeof(QChar) * 32) == 0)
+
+
+ return XML_NS_SCHEMA_URI;
+
+
+ return NoKeyword;
+ }
+ XsdSchemaToken::NodeName XsdSchemaToken::toToken(const QChar *data, int length)
+ {
+ switch(length)
+ {
+
+ case 2:
+ return classifier2(data);
+
+
+ case 3:
+ return classifier3(data);
+
+
+ case 4:
+ return classifier4(data);
+
+
+ case 5:
+ return classifier5(data);
+
+
+ case 6:
+ return classifier6(data);
+
+
+ case 7:
+ return classifier7(data);
+
+
+ case 8:
+ return classifier8(data);
+
+
+ case 9:
+ return classifier9(data);
+
+
+ case 10:
+ return classifier10(data);
+
+
+ case 11:
+ return classifier11(data);
+
+
+ case 12:
+ return classifier12(data);
+
+
+ case 13:
+ return classifier13(data);
+
+
+ case 14:
+ return classifier14(data);
+
+
+ case 15:
+ return classifier15(data);
+
+
+ case 17:
+ return classifier17(data);
+
+
+ case 18:
+ return classifier18(data);
+
+
+ case 20:
+ return classifier20(data);
+
+
+ case 21:
+ return classifier21(data);
+
+
+ case 22:
+ return classifier22(data);
+
+
+ case 32:
+ return classifier32(data);
+
+
+ default:
+ return NoKeyword;
+ }
+ }
+
+
+ QString XsdSchemaToken::toString(NodeName token)
+ {
+ const unsigned short *data = 0;
+ int length = 0;
+
+ switch(token)
+ {
+
+ case Abstract:
+ {
+ static const unsigned short staticallyStoredAbstract[] =
+ {
+ 97, 98, 115, 116, 114, 97, 99, 116, 0
+ };
+ data = staticallyStoredAbstract;
+ length = 8;
+ break;
+ }
+
+ case All:
+ {
+ static const unsigned short staticallyStoredAll[] =
+ {
+ 97, 108, 108, 0
+ };
+ data = staticallyStoredAll;
+ length = 3;
+ break;
+ }
+
+ case Alternative:
+ {
+ static const unsigned short staticallyStoredAlternative[] =
+ {
+ 97, 108, 116, 101, 114, 110, 97, 116, 105, 118, 101, 0
+ };
+ data = staticallyStoredAlternative;
+ length = 11;
+ break;
+ }
+
+ case Annotation:
+ {
+ static const unsigned short staticallyStoredAnnotation[] =
+ {
+ 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0
+ };
+ data = staticallyStoredAnnotation;
+ length = 10;
+ break;
+ }
+
+ case Any:
+ {
+ static const unsigned short staticallyStoredAny[] =
+ {
+ 97, 110, 121, 0
+ };
+ data = staticallyStoredAny;
+ length = 3;
+ break;
+ }
+
+ case AnyAttribute:
+ {
+ static const unsigned short staticallyStoredAnyAttribute[] =
+ {
+ 97, 110, 121, 65, 116, 116, 114, 105, 98, 117, 116, 101, 0
+ };
+ data = staticallyStoredAnyAttribute;
+ length = 12;
+ break;
+ }
+
+ case Appinfo:
+ {
+ static const unsigned short staticallyStoredAppinfo[] =
+ {
+ 97, 112, 112, 105, 110, 102, 111, 0
+ };
+ data = staticallyStoredAppinfo;
+ length = 7;
+ break;
+ }
+
+ case AppliesToEmpty:
+ {
+ static const unsigned short staticallyStoredAppliesToEmpty[] =
+ {
+ 97, 112, 112, 108, 105, 101, 115, 84, 111, 69, 109, 112, 116, 121, 0
+ };
+ data = staticallyStoredAppliesToEmpty;
+ length = 14;
+ break;
+ }
+
+ case Assert:
+ {
+ static const unsigned short staticallyStoredAssert[] =
+ {
+ 97, 115, 115, 101, 114, 116, 0
+ };
+ data = staticallyStoredAssert;
+ length = 6;
+ break;
+ }
+
+ case Assertion:
+ {
+ static const unsigned short staticallyStoredAssertion[] =
+ {
+ 97, 115, 115, 101, 114, 116, 105, 111, 110, 0
+ };
+ data = staticallyStoredAssertion;
+ length = 9;
+ break;
+ }
+
+ case Attribute:
+ {
+ static const unsigned short staticallyStoredAttribute[] =
+ {
+ 97, 116, 116, 114, 105, 98, 117, 116, 101, 0
+ };
+ data = staticallyStoredAttribute;
+ length = 9;
+ break;
+ }
+
+ case AttributeFormDefault:
+ {
+ static const unsigned short staticallyStoredAttributeFormDefault[] =
+ {
+ 97, 116, 116, 114, 105, 98, 117, 116, 101, 70, 111, 114, 109, 68, 101, 102, 97, 117, 108, 116, 0
+ };
+ data = staticallyStoredAttributeFormDefault;
+ length = 20;
+ break;
+ }
+
+ case AttributeGroup:
+ {
+ static const unsigned short staticallyStoredAttributeGroup[] =
+ {
+ 97, 116, 116, 114, 105, 98, 117, 116, 101, 71, 114, 111, 117, 112, 0
+ };
+ data = staticallyStoredAttributeGroup;
+ length = 14;
+ break;
+ }
+
+ case Base:
+ {
+ static const unsigned short staticallyStoredBase[] =
+ {
+ 98, 97, 115, 101, 0
+ };
+ data = staticallyStoredBase;
+ length = 4;
+ break;
+ }
+
+ case Block:
+ {
+ static const unsigned short staticallyStoredBlock[] =
+ {
+ 98, 108, 111, 99, 107, 0
+ };
+ data = staticallyStoredBlock;
+ length = 5;
+ break;
+ }
+
+ case BlockDefault:
+ {
+ static const unsigned short staticallyStoredBlockDefault[] =
+ {
+ 98, 108, 111, 99, 107, 68, 101, 102, 97, 117, 108, 116, 0
+ };
+ data = staticallyStoredBlockDefault;
+ length = 12;
+ break;
+ }
+
+ case Choice:
+ {
+ static const unsigned short staticallyStoredChoice[] =
+ {
+ 99, 104, 111, 105, 99, 101, 0
+ };
+ data = staticallyStoredChoice;
+ length = 6;
+ break;
+ }
+
+ case Collapse:
+ {
+ static const unsigned short staticallyStoredCollapse[] =
+ {
+ 99, 111, 108, 108, 97, 112, 115, 101, 0
+ };
+ data = staticallyStoredCollapse;
+ length = 8;
+ break;
+ }
+
+ case ComplexContent:
+ {
+ static const unsigned short staticallyStoredComplexContent[] =
+ {
+ 99, 111, 109, 112, 108, 101, 120, 67, 111, 110, 116, 101, 110, 116, 0
+ };
+ data = staticallyStoredComplexContent;
+ length = 14;
+ break;
+ }
+
+ case ComplexType:
+ {
+ static const unsigned short staticallyStoredComplexType[] =
+ {
+ 99, 111, 109, 112, 108, 101, 120, 84, 121, 112, 101, 0
+ };
+ data = staticallyStoredComplexType;
+ length = 11;
+ break;
+ }
+
+ case Default:
+ {
+ static const unsigned short staticallyStoredDefault[] =
+ {
+ 100, 101, 102, 97, 117, 108, 116, 0
+ };
+ data = staticallyStoredDefault;
+ length = 7;
+ break;
+ }
+
+ case DefaultAttributes:
+ {
+ static const unsigned short staticallyStoredDefaultAttributes[] =
+ {
+ 100, 101, 102, 97, 117, 108, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 0
+ };
+ data = staticallyStoredDefaultAttributes;
+ length = 17;
+ break;
+ }
+
+ case DefaultAttributesApply:
+ {
+ static const unsigned short staticallyStoredDefaultAttributesApply[] =
+ {
+ 100, 101, 102, 97, 117, 108, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 65, 112, 112, 108, 121, 0
+ };
+ data = staticallyStoredDefaultAttributesApply;
+ length = 22;
+ break;
+ }
+
+ case DefaultOpenContent:
+ {
+ static const unsigned short staticallyStoredDefaultOpenContent[] =
+ {
+ 100, 101, 102, 97, 117, 108, 116, 79, 112, 101, 110, 67, 111, 110, 116, 101, 110, 116, 0
+ };
+ data = staticallyStoredDefaultOpenContent;
+ length = 18;
+ break;
+ }
+
+ case Documentation:
+ {
+ static const unsigned short staticallyStoredDocumentation[] =
+ {
+ 100, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 0
+ };
+ data = staticallyStoredDocumentation;
+ length = 13;
+ break;
+ }
+
+ case Element:
+ {
+ static const unsigned short staticallyStoredElement[] =
+ {
+ 101, 108, 101, 109, 101, 110, 116, 0
+ };
+ data = staticallyStoredElement;
+ length = 7;
+ break;
+ }
+
+ case ElementFormDefault:
+ {
+ static const unsigned short staticallyStoredElementFormDefault[] =
+ {
+ 101, 108, 101, 109, 101, 110, 116, 70, 111, 114, 109, 68, 101, 102, 97, 117, 108, 116, 0
+ };
+ data = staticallyStoredElementFormDefault;
+ length = 18;
+ break;
+ }
+
+ case Enumeration:
+ {
+ static const unsigned short staticallyStoredEnumeration[] =
+ {
+ 101, 110, 117, 109, 101, 114, 97, 116, 105, 111, 110, 0
+ };
+ data = staticallyStoredEnumeration;
+ length = 11;
+ break;
+ }
+
+ case Extension:
+ {
+ static const unsigned short staticallyStoredExtension[] =
+ {
+ 101, 120, 116, 101, 110, 115, 105, 111, 110, 0
+ };
+ data = staticallyStoredExtension;
+ length = 9;
+ break;
+ }
+
+ case Field:
+ {
+ static const unsigned short staticallyStoredField[] =
+ {
+ 102, 105, 101, 108, 100, 0
+ };
+ data = staticallyStoredField;
+ length = 5;
+ break;
+ }
+
+ case Final:
+ {
+ static const unsigned short staticallyStoredFinal[] =
+ {
+ 102, 105, 110, 97, 108, 0
+ };
+ data = staticallyStoredFinal;
+ length = 5;
+ break;
+ }
+
+ case FinalDefault:
+ {
+ static const unsigned short staticallyStoredFinalDefault[] =
+ {
+ 102, 105, 110, 97, 108, 68, 101, 102, 97, 117, 108, 116, 0
+ };
+ data = staticallyStoredFinalDefault;
+ length = 12;
+ break;
+ }
+
+ case Fixed:
+ {
+ static const unsigned short staticallyStoredFixed[] =
+ {
+ 102, 105, 120, 101, 100, 0
+ };
+ data = staticallyStoredFixed;
+ length = 5;
+ break;
+ }
+
+ case Form:
+ {
+ static const unsigned short staticallyStoredForm[] =
+ {
+ 102, 111, 114, 109, 0
+ };
+ data = staticallyStoredForm;
+ length = 4;
+ break;
+ }
+
+ case FractionDigits:
+ {
+ static const unsigned short staticallyStoredFractionDigits[] =
+ {
+ 102, 114, 97, 99, 116, 105, 111, 110, 68, 105, 103, 105, 116, 115, 0
+ };
+ data = staticallyStoredFractionDigits;
+ length = 14;
+ break;
+ }
+
+ case Group:
+ {
+ static const unsigned short staticallyStoredGroup[] =
+ {
+ 103, 114, 111, 117, 112, 0
+ };
+ data = staticallyStoredGroup;
+ length = 5;
+ break;
+ }
+
+ case Id:
+ {
+ static const unsigned short staticallyStoredId[] =
+ {
+ 105, 100, 0
+ };
+ data = staticallyStoredId;
+ length = 2;
+ break;
+ }
+
+ case Import:
+ {
+ static const unsigned short staticallyStoredImport[] =
+ {
+ 105, 109, 112, 111, 114, 116, 0
+ };
+ data = staticallyStoredImport;
+ length = 6;
+ break;
+ }
+
+ case Include:
+ {
+ static const unsigned short staticallyStoredInclude[] =
+ {
+ 105, 110, 99, 108, 117, 100, 101, 0
+ };
+ data = staticallyStoredInclude;
+ length = 7;
+ break;
+ }
+
+ case ItemType:
+ {
+ static const unsigned short staticallyStoredItemType[] =
+ {
+ 105, 116, 101, 109, 84, 121, 112, 101, 0
+ };
+ data = staticallyStoredItemType;
+ length = 8;
+ break;
+ }
+
+ case Key:
+ {
+ static const unsigned short staticallyStoredKey[] =
+ {
+ 107, 101, 121, 0
+ };
+ data = staticallyStoredKey;
+ length = 3;
+ break;
+ }
+
+ case Keyref:
+ {
+ static const unsigned short staticallyStoredKeyref[] =
+ {
+ 107, 101, 121, 114, 101, 102, 0
+ };
+ data = staticallyStoredKeyref;
+ length = 6;
+ break;
+ }
+
+ case Length:
+ {
+ static const unsigned short staticallyStoredLength[] =
+ {
+ 108, 101, 110, 103, 116, 104, 0
+ };
+ data = staticallyStoredLength;
+ length = 6;
+ break;
+ }
+
+ case List:
+ {
+ static const unsigned short staticallyStoredList[] =
+ {
+ 108, 105, 115, 116, 0
+ };
+ data = staticallyStoredList;
+ length = 4;
+ break;
+ }
+
+ case MaxExclusive:
+ {
+ static const unsigned short staticallyStoredMaxExclusive[] =
+ {
+ 109, 97, 120, 69, 120, 99, 108, 117, 115, 105, 118, 101, 0
+ };
+ data = staticallyStoredMaxExclusive;
+ length = 12;
+ break;
+ }
+
+ case MaxInclusive:
+ {
+ static const unsigned short staticallyStoredMaxInclusive[] =
+ {
+ 109, 97, 120, 73, 110, 99, 108, 117, 115, 105, 118, 101, 0
+ };
+ data = staticallyStoredMaxInclusive;
+ length = 12;
+ break;
+ }
+
+ case MaxLength:
+ {
+ static const unsigned short staticallyStoredMaxLength[] =
+ {
+ 109, 97, 120, 76, 101, 110, 103, 116, 104, 0
+ };
+ data = staticallyStoredMaxLength;
+ length = 9;
+ break;
+ }
+
+ case MaxOccurs:
+ {
+ static const unsigned short staticallyStoredMaxOccurs[] =
+ {
+ 109, 97, 120, 79, 99, 99, 117, 114, 115, 0
+ };
+ data = staticallyStoredMaxOccurs;
+ length = 9;
+ break;
+ }
+
+ case MemberTypes:
+ {
+ static const unsigned short staticallyStoredMemberTypes[] =
+ {
+ 109, 101, 109, 98, 101, 114, 84, 121, 112, 101, 115, 0
+ };
+ data = staticallyStoredMemberTypes;
+ length = 11;
+ break;
+ }
+
+ case MinExclusive:
+ {
+ static const unsigned short staticallyStoredMinExclusive[] =
+ {
+ 109, 105, 110, 69, 120, 99, 108, 117, 115, 105, 118, 101, 0
+ };
+ data = staticallyStoredMinExclusive;
+ length = 12;
+ break;
+ }
+
+ case MinInclusive:
+ {
+ static const unsigned short staticallyStoredMinInclusive[] =
+ {
+ 109, 105, 110, 73, 110, 99, 108, 117, 115, 105, 118, 101, 0
+ };
+ data = staticallyStoredMinInclusive;
+ length = 12;
+ break;
+ }
+
+ case MinLength:
+ {
+ static const unsigned short staticallyStoredMinLength[] =
+ {
+ 109, 105, 110, 76, 101, 110, 103, 116, 104, 0
+ };
+ data = staticallyStoredMinLength;
+ length = 9;
+ break;
+ }
+
+ case MinOccurs:
+ {
+ static const unsigned short staticallyStoredMinOccurs[] =
+ {
+ 109, 105, 110, 79, 99, 99, 117, 114, 115, 0
+ };
+ data = staticallyStoredMinOccurs;
+ length = 9;
+ break;
+ }
+
+ case Mixed:
+ {
+ static const unsigned short staticallyStoredMixed[] =
+ {
+ 109, 105, 120, 101, 100, 0
+ };
+ data = staticallyStoredMixed;
+ length = 5;
+ break;
+ }
+
+ case Mode:
+ {
+ static const unsigned short staticallyStoredMode[] =
+ {
+ 109, 111, 100, 101, 0
+ };
+ data = staticallyStoredMode;
+ length = 4;
+ break;
+ }
+
+ case Name:
+ {
+ static const unsigned short staticallyStoredName[] =
+ {
+ 110, 97, 109, 101, 0
+ };
+ data = staticallyStoredName;
+ length = 4;
+ break;
+ }
+
+ case Namespace:
+ {
+ static const unsigned short staticallyStoredNamespace[] =
+ {
+ 110, 97, 109, 101, 115, 112, 97, 99, 101, 0
+ };
+ data = staticallyStoredNamespace;
+ length = 9;
+ break;
+ }
+
+ case Nillable:
+ {
+ static const unsigned short staticallyStoredNillable[] =
+ {
+ 110, 105, 108, 108, 97, 98, 108, 101, 0
+ };
+ data = staticallyStoredNillable;
+ length = 8;
+ break;
+ }
+
+ case NotNamespace:
+ {
+ static const unsigned short staticallyStoredNotNamespace[] =
+ {
+ 110, 111, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 0
+ };
+ data = staticallyStoredNotNamespace;
+ length = 12;
+ break;
+ }
+
+ case NotQName:
+ {
+ static const unsigned short staticallyStoredNotQName[] =
+ {
+ 110, 111, 116, 81, 78, 97, 109, 101, 0
+ };
+ data = staticallyStoredNotQName;
+ length = 8;
+ break;
+ }
+
+ case Notation:
+ {
+ static const unsigned short staticallyStoredNotation[] =
+ {
+ 110, 111, 116, 97, 116, 105, 111, 110, 0
+ };
+ data = staticallyStoredNotation;
+ length = 8;
+ break;
+ }
+
+ case OpenContent:
+ {
+ static const unsigned short staticallyStoredOpenContent[] =
+ {
+ 111, 112, 101, 110, 67, 111, 110, 116, 101, 110, 116, 0
+ };
+ data = staticallyStoredOpenContent;
+ length = 11;
+ break;
+ }
+
+ case Override:
+ {
+ static const unsigned short staticallyStoredOverride[] =
+ {
+ 111, 118, 101, 114, 114, 105, 100, 101, 0
+ };
+ data = staticallyStoredOverride;
+ length = 8;
+ break;
+ }
+
+ case Pattern:
+ {
+ static const unsigned short staticallyStoredPattern[] =
+ {
+ 112, 97, 116, 116, 101, 114, 110, 0
+ };
+ data = staticallyStoredPattern;
+ length = 7;
+ break;
+ }
+
+ case Preserve:
+ {
+ static const unsigned short staticallyStoredPreserve[] =
+ {
+ 112, 114, 101, 115, 101, 114, 118, 101, 0
+ };
+ data = staticallyStoredPreserve;
+ length = 8;
+ break;
+ }
+
+ case ProcessContents:
+ {
+ static const unsigned short staticallyStoredProcessContents[] =
+ {
+ 112, 114, 111, 99, 101, 115, 115, 67, 111, 110, 116, 101, 110, 116, 115, 0
+ };
+ data = staticallyStoredProcessContents;
+ length = 15;
+ break;
+ }
+
+ case Public:
+ {
+ static const unsigned short staticallyStoredPublic[] =
+ {
+ 112, 117, 98, 108, 105, 99, 0
+ };
+ data = staticallyStoredPublic;
+ length = 6;
+ break;
+ }
+
+ case Redefine:
+ {
+ static const unsigned short staticallyStoredRedefine[] =
+ {
+ 114, 101, 100, 101, 102, 105, 110, 101, 0
+ };
+ data = staticallyStoredRedefine;
+ length = 8;
+ break;
+ }
+
+ case Ref:
+ {
+ static const unsigned short staticallyStoredRef[] =
+ {
+ 114, 101, 102, 0
+ };
+ data = staticallyStoredRef;
+ length = 3;
+ break;
+ }
+
+ case Refer:
+ {
+ static const unsigned short staticallyStoredRefer[] =
+ {
+ 114, 101, 102, 101, 114, 0
+ };
+ data = staticallyStoredRefer;
+ length = 5;
+ break;
+ }
+
+ case Replace:
+ {
+ static const unsigned short staticallyStoredReplace[] =
+ {
+ 114, 101, 112, 108, 97, 99, 101, 0
+ };
+ data = staticallyStoredReplace;
+ length = 7;
+ break;
+ }
+
+ case Restriction:
+ {
+ static const unsigned short staticallyStoredRestriction[] =
+ {
+ 114, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 0
+ };
+ data = staticallyStoredRestriction;
+ length = 11;
+ break;
+ }
+
+ case Schema:
+ {
+ static const unsigned short staticallyStoredSchema[] =
+ {
+ 115, 99, 104, 101, 109, 97, 0
+ };
+ data = staticallyStoredSchema;
+ length = 6;
+ break;
+ }
+
+ case SchemaLocation:
+ {
+ static const unsigned short staticallyStoredSchemaLocation[] =
+ {
+ 115, 99, 104, 101, 109, 97, 76, 111, 99, 97, 116, 105, 111, 110, 0
+ };
+ data = staticallyStoredSchemaLocation;
+ length = 14;
+ break;
+ }
+
+ case Selector:
+ {
+ static const unsigned short staticallyStoredSelector[] =
+ {
+ 115, 101, 108, 101, 99, 116, 111, 114, 0
+ };
+ data = staticallyStoredSelector;
+ length = 8;
+ break;
+ }
+
+ case Sequence:
+ {
+ static const unsigned short staticallyStoredSequence[] =
+ {
+ 115, 101, 113, 117, 101, 110, 99, 101, 0
+ };
+ data = staticallyStoredSequence;
+ length = 8;
+ break;
+ }
+
+ case SimpleContent:
+ {
+ static const unsigned short staticallyStoredSimpleContent[] =
+ {
+ 115, 105, 109, 112, 108, 101, 67, 111, 110, 116, 101, 110, 116, 0
+ };
+ data = staticallyStoredSimpleContent;
+ length = 13;
+ break;
+ }
+
+ case SimpleType:
+ {
+ static const unsigned short staticallyStoredSimpleType[] =
+ {
+ 115, 105, 109, 112, 108, 101, 84, 121, 112, 101, 0
+ };
+ data = staticallyStoredSimpleType;
+ length = 10;
+ break;
+ }
+
+ case Source:
+ {
+ static const unsigned short staticallyStoredSource[] =
+ {
+ 115, 111, 117, 114, 99, 101, 0
+ };
+ data = staticallyStoredSource;
+ length = 6;
+ break;
+ }
+
+ case SubstitutionGroup:
+ {
+ static const unsigned short staticallyStoredSubstitutionGroup[] =
+ {
+ 115, 117, 98, 115, 116, 105, 116, 117, 116, 105, 111, 110, 71, 114, 111, 117, 112, 0
+ };
+ data = staticallyStoredSubstitutionGroup;
+ length = 17;
+ break;
+ }
+
+ case System:
+ {
+ static const unsigned short staticallyStoredSystem[] =
+ {
+ 115, 121, 115, 116, 101, 109, 0
+ };
+ data = staticallyStoredSystem;
+ length = 6;
+ break;
+ }
+
+ case TargetNamespace:
+ {
+ static const unsigned short staticallyStoredTargetNamespace[] =
+ {
+ 116, 97, 114, 103, 101, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 0
+ };
+ data = staticallyStoredTargetNamespace;
+ length = 15;
+ break;
+ }
+
+ case Test:
+ {
+ static const unsigned short staticallyStoredTest[] =
+ {
+ 116, 101, 115, 116, 0
+ };
+ data = staticallyStoredTest;
+ length = 4;
+ break;
+ }
+
+ case TotalDigits:
+ {
+ static const unsigned short staticallyStoredTotalDigits[] =
+ {
+ 116, 111, 116, 97, 108, 68, 105, 103, 105, 116, 115, 0
+ };
+ data = staticallyStoredTotalDigits;
+ length = 11;
+ break;
+ }
+
+ case Type:
+ {
+ static const unsigned short staticallyStoredType[] =
+ {
+ 116, 121, 112, 101, 0
+ };
+ data = staticallyStoredType;
+ length = 4;
+ break;
+ }
+
+ case Union:
+ {
+ static const unsigned short staticallyStoredUnion[] =
+ {
+ 117, 110, 105, 111, 110, 0
+ };
+ data = staticallyStoredUnion;
+ length = 5;
+ break;
+ }
+
+ case Unique:
+ {
+ static const unsigned short staticallyStoredUnique[] =
+ {
+ 117, 110, 105, 113, 117, 101, 0
+ };
+ data = staticallyStoredUnique;
+ length = 6;
+ break;
+ }
+
+ case Use:
+ {
+ static const unsigned short staticallyStoredUse[] =
+ {
+ 117, 115, 101, 0
+ };
+ data = staticallyStoredUse;
+ length = 3;
+ break;
+ }
+
+ case Value:
+ {
+ static const unsigned short staticallyStoredValue[] =
+ {
+ 118, 97, 108, 117, 101, 0
+ };
+ data = staticallyStoredValue;
+ length = 5;
+ break;
+ }
+
+ case Version:
+ {
+ static const unsigned short staticallyStoredVersion[] =
+ {
+ 118, 101, 114, 115, 105, 111, 110, 0
+ };
+ data = staticallyStoredVersion;
+ length = 7;
+ break;
+ }
+
+ case WhiteSpace:
+ {
+ static const unsigned short staticallyStoredWhiteSpace[] =
+ {
+ 119, 104, 105, 116, 101, 83, 112, 97, 99, 101, 0
+ };
+ data = staticallyStoredWhiteSpace;
+ length = 10;
+ break;
+ }
+
+ case XML_NS_SCHEMA_URI:
+ {
+ static const unsigned short staticallyStoredXML_NS_SCHEMA_URI[] =
+ {
+ 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 49, 47, 88, 77, 76, 83, 99, 104, 101, 109, 97, 0
+ };
+ data = staticallyStoredXML_NS_SCHEMA_URI;
+ length = 32;
+ break;
+ }
+
+ case XPathDefaultNamespace:
+ {
+ static const unsigned short staticallyStoredXPathDefaultNamespace[] =
+ {
+ 120, 112, 97, 116, 104, 68, 101, 102, 97, 117, 108, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 0
+ };
+ data = staticallyStoredXPathDefaultNamespace;
+ length = 21;
+ break;
+ }
+
+ case XmlLanguage:
+ {
+ static const unsigned short staticallyStoredXmlLanguage[] =
+ {
+ 120, 109, 108, 58, 108, 97, 110, 103, 0
+ };
+ data = staticallyStoredXmlLanguage;
+ length = 8;
+ break;
+ }
+
+ case Xpath:
+ {
+ static const unsigned short staticallyStoredXpath[] =
+ {
+ 120, 112, 97, 116, 104, 0
+ };
+ data = staticallyStoredXpath;
+ length = 5;
+ break;
+ }
+
+ default:
+ /* It's either the default token, or an undefined enum
+ * value. We silence a compiler warning, and return the
+ * empty string. */
+ ;
+ }
+
+ union
+ {
+ const unsigned short *data;
+ const QChar *asQChar;
+ } converter;
+ converter.data = data;
+
+ return QString::fromRawData(converter.asQChar, length);
+ }
+
+QT_END_NAMESPACE
+
diff --git a/src/xmlpatterns/schema/qxsdschematoken_p.h b/src/xmlpatterns/schema/qxsdschematoken_p.h
new file mode 100644
index 0000000000..8cb1e76a47
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschematoken_p.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+/* NOTE: This file is AUTO GENERATED by qautomaton2cpp.xsl. */
+
+#ifndef QPatternist_XsdSchemaToken_h
+#define QPatternist_XsdSchemaToken_h
+
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class XsdSchemaToken
+ {
+ public:
+ enum NodeName
+
+ {
+ NoKeyword,
+Abstract,
+All,
+Alternative,
+Annotation,
+Any,
+AnyAttribute,
+Appinfo,
+AppliesToEmpty,
+Assert,
+Assertion,
+Attribute,
+AttributeFormDefault,
+AttributeGroup,
+Base,
+Block,
+BlockDefault,
+Choice,
+Collapse,
+ComplexContent,
+ComplexType,
+Default,
+DefaultAttributes,
+DefaultAttributesApply,
+DefaultOpenContent,
+Documentation,
+Element,
+ElementFormDefault,
+Enumeration,
+Extension,
+Field,
+Final,
+FinalDefault,
+Fixed,
+Form,
+FractionDigits,
+Group,
+Id,
+Import,
+Include,
+ItemType,
+Key,
+Keyref,
+Length,
+List,
+MaxExclusive,
+MaxInclusive,
+MaxLength,
+MaxOccurs,
+MemberTypes,
+MinExclusive,
+MinInclusive,
+MinLength,
+MinOccurs,
+Mixed,
+Mode,
+Name,
+Namespace,
+Nillable,
+NotNamespace,
+NotQName,
+Notation,
+OpenContent,
+Override,
+Pattern,
+Preserve,
+ProcessContents,
+Public,
+Redefine,
+Ref,
+Refer,
+Replace,
+Restriction,
+Schema,
+SchemaLocation,
+Selector,
+Sequence,
+SimpleContent,
+SimpleType,
+Source,
+SubstitutionGroup,
+System,
+TargetNamespace,
+Test,
+TotalDigits,
+Type,
+Union,
+Unique,
+Use,
+Value,
+Version,
+WhiteSpace,
+XML_NS_SCHEMA_URI,
+XPathDefaultNamespace,
+XmlLanguage,
+Xpath
+ };
+
+ static inline NodeName toToken(const QString &value);
+static inline NodeName toToken(const QStringRef &value);
+static NodeName toToken(const QChar *data, int length);
+static QString toString(NodeName token);
+
+
+ private:
+ static inline NodeName classifier2(const QChar *data);
+static inline NodeName classifier3(const QChar *data);
+static inline NodeName classifier4(const QChar *data);
+static inline NodeName classifier5(const QChar *data);
+static inline NodeName classifier6(const QChar *data);
+static inline NodeName classifier7(const QChar *data);
+static inline NodeName classifier8(const QChar *data);
+static inline NodeName classifier9(const QChar *data);
+static inline NodeName classifier10(const QChar *data);
+static inline NodeName classifier11(const QChar *data);
+static inline NodeName classifier12(const QChar *data);
+static inline NodeName classifier13(const QChar *data);
+static inline NodeName classifier14(const QChar *data);
+static inline NodeName classifier15(const QChar *data);
+static inline NodeName classifier17(const QChar *data);
+static inline NodeName classifier18(const QChar *data);
+static inline NodeName classifier20(const QChar *data);
+static inline NodeName classifier21(const QChar *data);
+static inline NodeName classifier22(const QChar *data);
+static inline NodeName classifier32(const QChar *data);
+
+ };
+
+ inline XsdSchemaToken::NodeName XsdSchemaToken::toToken(const QString &value)
+ {
+ return toToken(value.constData(), value.length());
+ }
+
+ inline XsdSchemaToken::NodeName XsdSchemaToken::toToken(const QStringRef &value)
+ {
+ return toToken(value.constData(), value.length());
+ }
+
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdschematypesfactory.cpp b/src/xmlpatterns/schema/qxsdschematypesfactory.cpp
new file mode 100644
index 0000000000..6cac0ff454
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschematypesfactory.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdschematypesfactory_p.h"
+
+#include "qbasictypesfactory_p.h"
+#include "qbuiltintypes_p.h"
+#include "qderivedinteger_p.h"
+#include "qderivedstring_p.h"
+#include "qcommonnamespaces_p.h"
+#include "qxsdschematoken_p.h"
+#include "qxsdsimpletype_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchemaTypesFactory::XsdSchemaTypesFactory(const NamePool::Ptr &namePool)
+ : m_namePool(namePool)
+{
+ m_types.reserve(3);
+
+ const XsdFacet::Ptr whiteSpaceFacet(new XsdFacet());
+ whiteSpaceFacet->setType(XsdFacet::WhiteSpace);
+ whiteSpaceFacet->setFixed(true);
+ whiteSpaceFacet->setValue(DerivedString<TypeString>::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse)));
+
+ const XsdFacet::Ptr minLengthFacet(new XsdFacet());
+ minLengthFacet->setType(XsdFacet::MinimumLength);
+ minLengthFacet->setValue(DerivedInteger<TypeNonNegativeInteger>::fromLexical(namePool, QLatin1String("1")));
+
+ XsdFacet::Hash facets;
+ facets.insert(whiteSpaceFacet->type(), whiteSpaceFacet);
+ facets.insert(minLengthFacet->type(), minLengthFacet);
+
+ {
+ const QXmlName typeName = m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("NMTOKENS"));
+ const XsdSimpleType::Ptr type(new XsdSimpleType());
+ type->setName(typeName);
+ type->setWxsSuperType(BuiltinTypes::xsAnySimpleType);
+ type->setCategory(XsdSimpleType::SimpleTypeList);
+ type->setItemType(BuiltinTypes::xsNMTOKEN);
+ type->setDerivationMethod(XsdSimpleType::DerivationRestriction);
+ type->setFacets(facets);
+ m_types.insert(typeName, type);
+ }
+ {
+ const QXmlName typeName = m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("IDREFS"));
+ const XsdSimpleType::Ptr type(new XsdSimpleType());
+ type->setName(typeName);
+ type->setWxsSuperType(BuiltinTypes::xsAnySimpleType);
+ type->setCategory(XsdSimpleType::SimpleTypeList);
+ type->setItemType(BuiltinTypes::xsIDREF);
+ type->setDerivationMethod(XsdSimpleType::DerivationRestriction);
+ type->setFacets(facets);
+ m_types.insert(typeName, type);
+ }
+ {
+ const QXmlName typeName = m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("ENTITIES"));
+ const XsdSimpleType::Ptr type(new XsdSimpleType());
+ type->setName(typeName);
+ type->setWxsSuperType(BuiltinTypes::xsAnySimpleType);
+ type->setCategory(XsdSimpleType::SimpleTypeList);
+ type->setItemType(BuiltinTypes::xsENTITY);
+ type->setDerivationMethod(XsdSimpleType::DerivationRestriction);
+ type->setFacets(facets);
+ m_types.insert(typeName, type);
+ }
+}
+
+SchemaType::Ptr XsdSchemaTypesFactory::createSchemaType(const QXmlName name) const
+{
+ if (m_types.contains(name)) {
+ return m_types.value(name);
+ } else {
+ if (!m_basicTypesFactory)
+ m_basicTypesFactory = BasicTypesFactory::self(m_namePool);
+
+ return m_basicTypesFactory->createSchemaType(name);
+ }
+}
+
+SchemaType::Hash XsdSchemaTypesFactory::types() const
+{
+ return m_types;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdschematypesfactory_p.h b/src/xmlpatterns/schema/qxsdschematypesfactory_p.h
new file mode 100644
index 0000000000..4fcd5fb9a0
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdschematypesfactory_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSchemaTypesFactory_H
+#define Patternist_XsdSchemaTypesFactory_H
+
+#include <QtCore/QHash>
+#include "qschematypefactory_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+
+ /**
+ * @short Factory for creating schema types for the types defined in XSD.
+ *
+ * @ingroup Patternist_types
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSchemaTypesFactory : public SchemaTypeFactory
+ {
+ public:
+ /**
+ * Creates a new schema type factory.
+ *
+ * @param namePool The name pool all type names belong to.
+ */
+ XsdSchemaTypesFactory(const NamePool::Ptr &namePool);
+
+ /**
+ * Creates a primitive type for @p name. If @p name is not supported,
+ * @c null is returned.
+ *
+ * @note This does not handle user defined types, only builtin types.
+ */
+ virtual SchemaType::Ptr createSchemaType(const QXmlName) const;
+
+ /**
+ * Returns a hash of all available types.
+ */
+ virtual SchemaType::Hash types() const;
+
+ private:
+ /**
+ * A dictonary of all predefined schema types.
+ */
+ SchemaType::Hash m_types;
+
+ NamePool::Ptr m_namePool;
+ mutable SchemaTypeFactory::Ptr m_basicTypesFactory;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdsimpletype.cpp b/src/xmlpatterns/schema/qxsdsimpletype.cpp
new file mode 100644
index 0000000000..2e5b7f52c5
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdsimpletype.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#include "qxsdsimpletype_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+QString XsdSimpleType::displayName(const NamePool::Ptr &np) const
+{
+ return np->displayName(name(np));
+}
+
+void XsdSimpleType::setWxsSuperType(const SchemaType::Ptr &type)
+{
+ m_superType = type;
+}
+
+SchemaType::Ptr XsdSimpleType::wxsSuperType() const
+{
+ return m_superType;
+}
+
+void XsdSimpleType::setContext(const NamedSchemaComponent::Ptr &component)
+{
+ m_context = component;
+}
+
+NamedSchemaComponent::Ptr XsdSimpleType::context() const
+{
+ return m_context;
+}
+
+void XsdSimpleType::setPrimitiveType(const AnySimpleType::Ptr &type)
+{
+ m_primitiveType = type;
+}
+
+AnySimpleType::Ptr XsdSimpleType::primitiveType() const
+{
+ return m_primitiveType;
+}
+
+void XsdSimpleType::setItemType(const AnySimpleType::Ptr &type)
+{
+ m_itemType = type;
+}
+
+AnySimpleType::Ptr XsdSimpleType::itemType() const
+{
+ return m_itemType;
+}
+
+void XsdSimpleType::setMemberTypes(const AnySimpleType::List &types)
+{
+ m_memberTypes = types;
+}
+
+AnySimpleType::List XsdSimpleType::memberTypes() const
+{
+ return m_memberTypes;
+}
+
+void XsdSimpleType::setFacets(const XsdFacet::Hash &facets)
+{
+ m_facets = facets;
+}
+
+XsdFacet::Hash XsdSimpleType::facets() const
+{
+ return m_facets;
+}
+
+void XsdSimpleType::setCategory(TypeCategory category)
+{
+ m_typeCategory = category;
+}
+
+XsdSimpleType::TypeCategory XsdSimpleType::category() const
+{
+ return m_typeCategory;
+}
+
+void XsdSimpleType::setDerivationMethod(DerivationMethod method)
+{
+ m_derivationMethod = method;
+}
+
+XsdSimpleType::DerivationMethod XsdSimpleType::derivationMethod() const
+{
+ return m_derivationMethod;
+}
+
+bool XsdSimpleType::isDefinedBySchema() const
+{
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdsimpletype_p.h b/src/xmlpatterns/schema/qxsdsimpletype_p.h
new file mode 100644
index 0000000000..9ba34b63e6
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdsimpletype_p.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdSimpleType_H
+#define Patternist_XsdSimpleType_H
+
+#include "qanysimpletype_p.h"
+#include "qxsdfacet_p.h"
+#include "qxsduserschematype_p.h"
+
+#include <QtCore/QSet>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD simpleType object.
+ *
+ * This class represents the <em>simpleType</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema-2/#rf-defn">here</a>.
+ *
+ * It contains information from either a top-level simple type declaration (as child of a <em>schema</em> object)
+ * or a local simple type declaration (as descendant of an <em>element</em> or <em>complexType</em> object).
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSSimpleType">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdSimpleType : public XsdUserSchemaType<AnySimpleType>
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdSimpleType> Ptr;
+
+ /**
+ * Returns the display name of the simple type.
+ *
+ * @param namePool The name pool the type name is stored in.
+ */
+ virtual QString displayName(const NamePool::Ptr &namePool) const;
+
+ /**
+ * Sets the base @p type of the simple type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema-2/#defn-basetype">Base Type Definition</a>
+ */
+ void setWxsSuperType(const SchemaType::Ptr &type);
+
+ /**
+ * Returns the base type of the simple type or an empty pointer if no base type is
+ * set.
+ */
+ virtual SchemaType::Ptr wxsSuperType() const;
+
+ /**
+ * Sets the context @p component of the simple type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#std-context">Context Definition</a>
+ */
+ void setContext(const NamedSchemaComponent::Ptr &component);
+
+ /**
+ * Returns the context component of the simple type.
+ */
+ NamedSchemaComponent::Ptr context() const;
+
+ /**
+ * Sets the primitive @p type of the simple type.
+ *
+ * The primitive type is only specified if the category is SimpleTypeAtomic.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema-2/#defn-primitive">Primitive Type Definition</a>
+ */
+ void setPrimitiveType(const AnySimpleType::Ptr &type);
+
+ /**
+ * Returns the primitive type of the simple type or an empty pointer if the category is
+ * not SimpleTypeAtomic.
+ */
+ AnySimpleType::Ptr primitiveType() const;
+
+ /**
+ * Sets the list item @p type of the simple type.
+ *
+ * The list item type is only specified if the category is SimpleTypeList.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema-2/#defn-itemType">Item Type Definition</a>
+ */
+ void setItemType(const AnySimpleType::Ptr &type);
+
+ /**
+ * Returns the list item type of the simple type or an empty pointer if the category is
+ * not SimpleTypeList.
+ */
+ AnySimpleType::Ptr itemType() const;
+
+ /**
+ * Sets the member @p types of the simple type.
+ *
+ * The member types are only specified if the category is SimpleTypeUnion.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema-2/#defn-memberTypes">Member Types Definition</a>
+ */
+ void setMemberTypes(const AnySimpleType::List &types);
+
+ /**
+ * Returns the list member types of the simple type or an empty list if the category is
+ * not SimpleTypeUnion.
+ */
+ AnySimpleType::List memberTypes() const;
+
+ /**
+ * Sets the @p facets of the simple type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema-2/#defn-facets">Facets Definition</a>
+ */
+ void setFacets(const XsdFacet::Hash &facets);
+
+ /**
+ * Returns the facets of the simple type.
+ */
+ XsdFacet::Hash facets() const;
+
+ /**
+ * Sets the @p category (variety) of the simple type.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema-2/#defn-variety">Variety Definition</a>
+ */
+ void setCategory(TypeCategory category);
+
+ /**
+ * Returns the category (variety) of the simple type.
+ */
+ virtual TypeCategory category() const;
+
+ /**
+ * Sets the derivation @p method of the simple type.
+ *
+ * @see DerivationMethod
+ */
+ void setDerivationMethod(DerivationMethod method);
+
+ /**
+ * Returns the derivation method of the simple type.
+ */
+ virtual DerivationMethod derivationMethod() const;
+
+ /**
+ * Always returns @c true.
+ */
+ virtual bool isDefinedBySchema() const;
+
+ private:
+ SchemaType::Ptr m_superType;
+ NamedSchemaComponent::Ptr m_context;
+ AnySimpleType::Ptr m_primitiveType;
+ AnySimpleType::Ptr m_itemType;
+ AnySimpleType::List m_memberTypes;
+ XsdFacet::Hash m_facets;
+ TypeCategory m_typeCategory;
+ DerivationMethod m_derivationMethod;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdstatemachine.cpp b/src/xmlpatterns/schema/qxsdstatemachine.cpp
new file mode 100644
index 0000000000..e40e55b56d
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdstatemachine.cpp
@@ -0,0 +1,433 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * NOTE: This file is included by qxsdstatemachine_p.h
+ * if you need some includes, put them in qxsdstatemachine_p.h (outside of the namespace)
+ */
+
+template <typename TransitionType>
+XsdStateMachine<TransitionType>::XsdStateMachine()
+ : m_counter(50)
+{
+}
+
+template <typename TransitionType>
+XsdStateMachine<TransitionType>::XsdStateMachine(const NamePool::Ptr &namePool)
+ : m_namePool(namePool)
+ , m_counter(50)
+{
+}
+
+template <typename TransitionType>
+typename XsdStateMachine<TransitionType>::StateId XsdStateMachine<TransitionType>::addState(StateType type)
+{
+#ifndef QT_NO_DEBUG
+ // make sure we don't have two start states
+ if (type == StartState) {
+ QHashIterator<StateId, StateType> it(m_states);
+ while (it.hasNext()) {
+ it.next();
+ Q_ASSERT(it.value() != StartState && it.value() != StartEndState);
+ }
+ }
+#endif // QT_NO_DEBUG
+
+ // reserve new state id
+ const StateId id = ++m_counter;
+ m_states.insert(id, type);
+
+ // if it is a start state, we make it to our current state
+ if (type == StartState || type == StartEndState)
+ m_currentState = id;
+
+ return id;
+}
+
+template <typename TransitionType>
+void XsdStateMachine<TransitionType>::addTransition(StateId start, TransitionType transition, StateId end)
+{
+ QHash<TransitionType, QVector<StateId> > &hash = m_transitions[start];
+ QVector<StateId> &states = hash[transition];
+ if (!states.contains(end))
+ states.append(end);
+}
+
+template <typename TransitionType>
+void XsdStateMachine<TransitionType>::addEpsilonTransition(StateId start, StateId end)
+{
+ QVector<StateId> &states = m_epsilonTransitions[start];
+ states.append(end);
+}
+
+template <typename TransitionType>
+void XsdStateMachine<TransitionType>::reset()
+{
+ // reset the machine to the start state
+ QHashIterator<StateId, StateType> it(m_states);
+ while (it.hasNext()) {
+ it.next();
+ if (it.value() == StartState || it.value() == StartEndState) {
+ m_currentState = it.key();
+ return;
+ }
+ }
+
+ Q_ASSERT(false);
+}
+
+template <typename TransitionType>
+void XsdStateMachine<TransitionType>::clear()
+{
+ m_states.clear();
+ m_transitions.clear();
+ m_epsilonTransitions.clear();
+ m_currentState = -1;
+ m_counter = 50;
+}
+
+template <typename TransitionType>
+bool XsdStateMachine<TransitionType>::proceed(TransitionType transition)
+{
+ // check that we are not in an invalid state
+ if (!m_transitions.contains(m_currentState)) {
+ return false;
+ }
+
+ // fetch the transition entry for the current state
+ const QHash<TransitionType, QVector<StateId> > &entry = m_transitions[m_currentState];
+ if (entry.contains(transition)) { // is there an transition for the given input?
+ m_currentState = entry.value(transition).first();
+ m_lastTransition = transition;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+template <typename TransitionType>
+template <typename InputType>
+bool XsdStateMachine<TransitionType>::proceed(InputType input)
+{
+ // check that we are not in an invalid state
+ if (!m_transitions.contains(m_currentState)) {
+ return false;
+ }
+
+ // fetch the transition entry for the current state
+ const QHash<TransitionType, QVector<StateId> > &entry = m_transitions[m_currentState];
+ QHashIterator<TransitionType, QVector<StateId> > it(entry);
+ while (it.hasNext()) {
+ it.next();
+ if (inputEqualsTransition(input, it.key())) {
+ m_currentState = it.value().first();
+ m_lastTransition = it.key();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+template <typename TransitionType>
+template <typename InputType>
+bool XsdStateMachine<TransitionType>::inputEqualsTransition(InputType input, TransitionType transition) const
+{
+ return false;
+}
+
+template <typename TransitionType>
+bool XsdStateMachine<TransitionType>::inEndState() const
+{
+ // check if current state is an end state
+ return (m_states.value(m_currentState) == StartEndState || m_states.value(m_currentState) == EndState);
+}
+
+template <typename TransitionType>
+TransitionType XsdStateMachine<TransitionType>::lastTransition() const
+{
+ return m_lastTransition;
+}
+
+template <typename TransitionType>
+typename XsdStateMachine<TransitionType>::StateId XsdStateMachine<TransitionType>::startState() const
+{
+ QHashIterator<StateId, StateType> it(m_states);
+ while (it.hasNext()) {
+ it.next();
+ if (it.value() == StartState || it.value() == StartEndState)
+ return it.key();
+ }
+
+ Q_ASSERT(false); // should never be reached
+ return -1;
+}
+
+template <typename TransitionType>
+QString XsdStateMachine<TransitionType>::transitionTypeToString(TransitionType type) const
+{
+ Q_UNUSED(type)
+
+ return QString();
+}
+
+template <typename TransitionType>
+bool XsdStateMachine<TransitionType>::outputGraph(QIODevice *device, const QString &graphName) const
+{
+ if (!device->isOpen()) {
+ qWarning("device must be open for writing");
+ return false;
+ }
+
+ QByteArray graph;
+ QTextStream s(&graph);
+
+ QHashIterator<StateId, QHash<TransitionType, QVector<StateId> > > it(m_transitions);
+ QHashIterator<StateId, StateType> it3(m_states);
+
+ s << "digraph " << graphName << " {\n";
+ s << " mindist = 2.0\n";
+
+ // draw edges
+ while (it.hasNext()) {
+ it.next();
+
+ QHashIterator<TransitionType, QVector<StateId> > it2(it.value());
+ while (it2.hasNext()) {
+ it2.next();
+ for (int i = 0; i < it2.value().count(); ++i)
+ s << " " << it.key() << " -> " << it2.value().at(i) << " [label=\"" << transitionTypeToString(it2.key()) << "\"]\n";
+ }
+ }
+
+ QHashIterator<StateId, QVector<StateId> > it4(m_epsilonTransitions);
+ while (it4.hasNext()) {
+ it4.next();
+
+ const QVector<StateId> states = it4.value();
+ for (int i = 0; i < states.count(); ++i)
+ s << " " << it4.key() << " -> " << states.at(i) << " [label=\"&#949;\"]\n";
+ }
+
+ // draw node infos
+ while (it3.hasNext()) {
+ it3.next();
+
+ QString style;
+ if (it3.value() == StartState) {
+ style = QLatin1String("shape=circle, style=filled, color=blue");
+ } else if (it3.value() == StartEndState) {
+ style = QLatin1String("shape=doublecircle, style=filled, color=blue");
+ } else if (it3.value() == InternalState) {
+ style = QLatin1String("shape=circle, style=filled, color=red");
+ } else if (it3.value() == EndState) {
+ style = QLatin1String("shape=doublecircle, style=filled, color=green");
+ }
+
+ s << " " << it3.key() << " [" << style << "]\n";
+ }
+
+ s << "}\n";
+
+ s.flush();
+
+ if (device->write(graph) == -1)
+ return false;
+
+ return true;
+}
+
+
+template <typename TransitionType>
+typename XsdStateMachine<TransitionType>::StateId XsdStateMachine<TransitionType>::dfaStateForNfaState(QSet<StateId> nfaState,
+ QList< QPair<QSet<StateId>, StateId> > &stateTable,
+ XsdStateMachine<TransitionType> &dfa) const
+{
+ // check whether we have the given state in our lookup table
+ // already, in that case simply return it
+ for (int i = 0; i < stateTable.count(); ++i) {
+ if (stateTable.at(i).first == nfaState)
+ return stateTable.at(i).second;
+ }
+
+ // check if the NFA state set contains a Start or End
+ // state, in that case our new DFA state will be a
+ // Start or End state as well
+ StateType type = InternalState;
+ QSetIterator<StateId> it(nfaState);
+ bool hasStartState = false;
+ bool hasEndState = false;
+ while (it.hasNext()) {
+ const StateId state = it.next();
+ if (m_states.value(state) == EndState) {
+ hasEndState = true;
+ } else if (m_states.value(state) == StartState) {
+ hasStartState = true;
+ }
+ }
+ if (hasStartState) {
+ if (hasEndState)
+ type = StartEndState;
+ else
+ type = StartState;
+ } else if (hasEndState) {
+ type = EndState;
+ }
+
+ // create the new DFA state
+ const StateId dfaState = dfa.addState(type);
+
+ // add the new DFA state to the lookup table
+ stateTable.append(qMakePair<QSet<StateId>, StateId>(nfaState, dfaState));
+
+ return dfaState;
+}
+
+
+template <typename TransitionType>
+QSet<typename XsdStateMachine<TransitionType>::StateId> XsdStateMachine<TransitionType>::epsilonClosure(const QSet<StateId> &input) const
+{
+ // every state can reach itself by epsilon transition, so include the input states
+ // in the result as well
+ QSet<StateId> result = input;
+
+ // add the input states to the list of to be processed states
+ QList<StateId> workStates = input.toList();
+ while (!workStates.isEmpty()) { // while there are states to be processed left...
+
+ // dequeue one state from list
+ const StateId state = workStates.takeFirst();
+
+ // get the list of states that can be reached by the epsilon transition
+ // from the current 'state'
+ const QVector<StateId> targetStates = m_epsilonTransitions.value(state);
+ for (int i = 0; i < targetStates.count(); ++i) {
+ // if we have this target state not in our result set yet...
+ if (!result.contains(targetStates.at(i))) {
+ // ... add it to the result set
+ result.insert(targetStates.at(i));
+
+ // add the target state to the list of to be processed states as well,
+ // as we want to have the epsilon transitions not only for the first
+ // level of following states
+ workStates.append(targetStates.at(i));
+ }
+ }
+ }
+
+ return result;
+}
+
+template <typename TransitionType>
+QSet<typename XsdStateMachine<TransitionType>::StateId> XsdStateMachine<TransitionType>::move(const QSet<StateId> &states, TransitionType input) const
+{
+ QSet<StateId> result;
+
+ QSetIterator<StateId> it(states);
+ while (it.hasNext()) { // iterate over all given states
+ const StateId state = it.next();
+
+ // get the transition table for the current state
+ const QHash<TransitionType, QVector<StateId> > transitions = m_transitions.value(state);
+
+ // get the target states for the given input
+ const QVector<StateId> targetStates = transitions.value(input);
+
+ // add all target states to the result
+ for (int i = 0; i < targetStates.size(); ++i)
+ result.insert(targetStates.at(i));
+ }
+
+ return result;
+}
+
+template <typename TransitionType>
+XsdStateMachine<TransitionType> XsdStateMachine<TransitionType>::toDFA() const
+{
+ XsdStateMachine<TransitionType> dfa(m_namePool);
+ dfa.m_counter = 100;
+ QList< QPair< QSet<StateId>, StateId> > table;
+ QList< QSet<StateId> > isMarked;
+
+ // search the start state as the algorithm starts with it...
+ StateId startState = -1;
+ QHashIterator<StateId, StateType> stateTypeIt(m_states);
+ while (stateTypeIt.hasNext()) {
+ stateTypeIt.next();
+ if (stateTypeIt.value() == StartState) {
+ startState = stateTypeIt.key();
+ break;
+ }
+ }
+ Q_ASSERT(startState != -1);
+
+ // our list of state set that still have to be processed
+ QList< QSet<StateId> > workStates;
+
+ // add the start state to the list of to processed state sets
+ workStates.append(epsilonClosure(QSet<StateId>() << startState));
+
+ while (!workStates.isEmpty()) { // as long as there are state sets to process left
+
+ // enqueue set of states
+ const QSet<StateId> states = workStates.takeFirst();
+
+ if (isMarked.contains(states)) // we processed this state set already
+ continue;
+
+ // mark as processed
+ isMarked.append(states);
+
+ // select a list of all inputs that are possible for
+ // the 'states' set
+ QList<TransitionType> input;
+
+ {
+ QSetIterator<StateId> it(states);
+ while (it.hasNext()) {
+ input << m_transitions.value(it.next()).keys();
+ }
+ }
+
+ // get the state in DFA that corresponds to the 'states' set in the NFA
+ const StateId dfaBegin = dfaStateForNfaState(states, table, dfa);
+
+ for (int i = 0; i < input.count(); ++i) { // for each possible input
+ // retrieve the states that can be reached from the 'states' set by the
+ // given input or by epsilon transition
+ const QSet<StateId> followStates = epsilonClosure(move(states, input.at(i)));
+
+ // get the state in DFA that corresponds to the 'followStates' set in the NFA
+ const StateId dfaEnd = dfaStateForNfaState(followStates, table, dfa);
+
+ // adds a new transition to the DFA that corresponds to the transitions between
+ // 'states' and 'followStates' in the NFA
+ dfa.addTransition(dfaBegin, input.at(i), dfaEnd);
+
+ // add the 'followStates' to the list of to be processed state sets
+ workStates.append(followStates);
+ }
+ }
+
+ return dfa;
+}
+
+template <typename TransitionType>
+QHash<typename XsdStateMachine<TransitionType>::StateId, typename XsdStateMachine<TransitionType>::StateType> XsdStateMachine<TransitionType>::states() const
+{
+ return m_states;
+}
+
+template <typename TransitionType>
+QHash<typename XsdStateMachine<TransitionType>::StateId, QHash<TransitionType, QVector<typename XsdStateMachine<TransitionType>::StateId> > > XsdStateMachine<TransitionType>::transitions() const
+{
+ return m_transitions;
+}
diff --git a/src/xmlpatterns/schema/qxsdstatemachine_p.h b/src/xmlpatterns/schema/qxsdstatemachine_p.h
new file mode 100644
index 0000000000..7988335d78
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdstatemachine_p.h
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdStateMachine_H
+#define Patternist_XsdStateMachine_H
+
+#include "qnamepool_p.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QSet>
+#include <QtCore/QTextStream>
+
+class QIODevice;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A state machine used for evaluation.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ template <typename TransitionType>
+ class XsdStateMachine
+ {
+ public:
+ typedef qint32 StateId;
+
+ /**
+ * Describes the type of state.
+ */
+ enum StateType
+ {
+ StartState, ///< The state the machine will start with.
+ StartEndState, ///< The state the machine will start with, can be end state as well.
+ InternalState, ///< Any state that is not start or end state.
+ EndState ///< Any state where the machine is allowed to stop.
+ };
+
+ /**
+ * Creates a new state machine object.
+ */
+ XsdStateMachine();
+
+ /**
+ * Creates a new state machine object.
+ *
+ * The name pool to use for accessing object names.
+ */
+ XsdStateMachine(const NamePool::Ptr &namePool);
+
+ /**
+ * Adds a new state of the given @p type to the state machine.
+ *
+ * @return The id of the new state.
+ */
+ StateId addState(StateType type);
+
+ /**
+ * Adds a new @p transition to the state machine.
+ *
+ * @param start The start state.
+ * @param transition The transition to come from the start to the end state.
+ * @param end The end state.
+ */
+ void addTransition(StateId start, TransitionType transition, StateId end);
+
+ /**
+ * Adds a new epsilon @p transition to the state machine.
+ *
+ * @param start The start state.
+ * @param end The end state.
+ */
+ void addEpsilonTransition(StateId start, StateId end);
+
+ /**
+ * Resets the machine to the start state.
+ */
+ void reset();
+
+ /**
+ * Removes all states and transitions from the state machine.
+ */
+ void clear();
+
+ /**
+ * Continues execution of the machine with the given input @p transition.
+ *
+ * @return @c true if the transition was successfull, @c false otherwise.
+ */
+ bool proceed(TransitionType transition);
+
+ /**
+ * Continues execution of the machine with the given @p input.
+ *
+ * @note To use this method, inputEqualsTransition must be implemented
+ * to find the right transition to use.
+ *
+ * @return @c true if the transition was successfull, @c false otherwise.
+ */
+ template <typename InputType>
+ bool proceed(InputType input);
+
+ /**
+ * Returns whether the given @p input matches the given @p transition.
+ */
+ template <typename InputType>
+ bool inputEqualsTransition(InputType input, TransitionType transition) const;
+
+ /**
+ * Returns whether the machine is in an allowed end state.
+ */
+ bool inEndState() const;
+
+ /**
+ * Returns the last transition that was taken.
+ */
+ TransitionType lastTransition() const;
+
+ /**
+ * Returns the start state of the machine.
+ */
+ StateId startState() const;
+
+ /**
+ * This method should be redefined by template specialization for every
+ * concret TransitionType.
+ */
+ QString transitionTypeToString(TransitionType type) const;
+
+ /**
+ * Outputs the state machine in DOT format to the given
+ * output @p device.
+ */
+ bool outputGraph(QIODevice *device, const QString &graphName) const;
+
+ /**
+ * Returns a DFA that is equal to the NFA of the state machine.
+ */
+ XsdStateMachine<TransitionType> toDFA() const;
+
+ /**
+ * Returns the information of all states of the state machine.
+ */
+ QHash<StateId, StateType> states() const;
+
+ /**
+ * Returns the information of all transitions of the state machine.
+ */
+ QHash<StateId, QHash<TransitionType, QVector<StateId> > > transitions() const;
+
+ private:
+ /**
+ * Returns the DFA state for the given @p nfaStat from the given @p stateTable.
+ * If there is no corresponding DFA state yet, a new one is created.
+ */
+ StateId dfaStateForNfaState(QSet<StateId> nfaState, QList< QPair< QSet<StateId>, StateId> > &stateTable, XsdStateMachine<TransitionType> &dfa) const;
+
+ /**
+ * Returns the set of all states that can be reached from the set of @p input states
+ * by the epsilon transition.
+ */
+ QSet<StateId> epsilonClosure(const QSet<StateId> &input) const;
+
+ /**
+ * Returns the set of all states that can be reached from the set of given @p states
+ * by the given @p input.
+ */
+ QSet<StateId> move(const QSet<StateId> &states, TransitionType input) const;
+
+ NamePool::Ptr m_namePool;
+ QHash<StateId, StateType> m_states;
+ QHash<StateId, QHash<TransitionType, QVector<StateId> > > m_transitions;
+ QHash<StateId, QVector<StateId> > m_epsilonTransitions;
+ StateId m_currentState;
+ qint32 m_counter;
+ TransitionType m_lastTransition;
+ };
+
+ #include "qxsdstatemachine.cpp"
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp b/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp
new file mode 100644
index 0000000000..866e010d1d
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdstatemachinebuilder_p.h"
+
+#include "qxsdelement_p.h"
+#include "qxsdmodelgroup_p.h"
+#include "qxsdschemahelper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+/*
+ * This methods takes a list of objects and returns a list of list
+ * of all combinations the objects can be ordered.
+ *
+ * e.g. input = [ 1, 2, 3 ]
+ * output = [
+ * [ 1, 2, 3 ],
+ * [ 1, 3, 2 ],
+ * [ 2, 1, 3 ],
+ * [ 2, 3, 1 ],
+ * [ 3, 1, 2 ],
+ * [ 3, 2, 1 ]
+ * ]
+ *
+ * The method is used to create all possible combinations for the particles
+ * in an <all> model group.
+ */
+template <typename T>
+QList< QList<T> > allCombinations(const QList<T> &input)
+{
+ if (input.count() == 1)
+ return (QList< QList<T> >() << input);
+
+ QList< QList<T> > result;
+ for (int i = 0; i < input.count(); ++i) {
+ QList<T> subList = input;
+ T value = subList.takeAt(i);
+
+ QList< QList<T> > subLists = allCombinations(subList);
+ for (int j = 0; j < subLists.count(); ++j) {
+ subLists[j].prepend(value);
+ }
+ result << subLists;
+ }
+
+ return result;
+}
+
+XsdStateMachineBuilder::XsdStateMachineBuilder(XsdStateMachine<XsdTerm::Ptr> *machine, const NamePool::Ptr &namePool, Mode mode)
+ : m_stateMachine(machine), m_namePool(namePool), m_mode(mode)
+{
+}
+
+XsdStateMachine<XsdTerm::Ptr>::StateId XsdStateMachineBuilder::reset()
+{
+ Q_ASSERT(m_stateMachine);
+
+ m_stateMachine->clear();
+
+ return m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::EndState);
+}
+
+XsdStateMachine<XsdTerm::Ptr>::StateId XsdStateMachineBuilder::addStartState(XsdStateMachine<XsdTerm::Ptr>::StateId state)
+{
+ const XsdStateMachine<XsdTerm::Ptr>::StateId startState = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::StartState);
+ m_stateMachine->addEpsilonTransition(startState, state);
+
+ return startState;
+}
+
+/*
+ * Create the FSA according to Algorithm Tp(S) from http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html
+ */
+XsdStateMachine<XsdTerm::Ptr>::StateId XsdStateMachineBuilder::buildParticle(const XsdParticle::Ptr &particle, XsdStateMachine<XsdTerm::Ptr>::StateId endState)
+{
+ XsdStateMachine<XsdTerm::Ptr>::StateId currentStartState = endState;
+ XsdStateMachine<XsdTerm::Ptr>::StateId currentEndState = endState;
+
+ // 2
+ if (particle->maximumOccursUnbounded()) {
+ const XsdStateMachine<XsdTerm::Ptr>::StateId t = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::InternalState);
+ const XsdStateMachine<XsdTerm::Ptr>::StateId n = buildTerm(particle->term(), t);
+
+ m_stateMachine->addEpsilonTransition(t, n);
+ m_stateMachine->addEpsilonTransition(n, endState);
+
+ currentEndState = t;
+ currentStartState = t;
+ } else { // 3
+ int count = (particle->maximumOccurs() - particle->minimumOccurs());
+ if (count > 100)
+ count = 100;
+
+ for (int i = 0; i < count; ++i) {
+ currentStartState = buildTerm(particle->term(), currentEndState);
+ m_stateMachine->addEpsilonTransition(currentStartState, endState);
+ currentEndState = currentStartState;
+ }
+ }
+
+ int minOccurs = particle->minimumOccurs();
+ if (minOccurs > 100)
+ minOccurs = 100;
+
+ for (int i = 0; i < minOccurs; ++i) {
+ currentStartState = buildTerm(particle->term(), currentEndState);
+ currentEndState = currentStartState;
+ }
+
+ return currentStartState;
+}
+
+/*
+ * Create the FSA according to Algorithm Tt(S) from http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html
+ */
+XsdStateMachine<XsdTerm::Ptr>::StateId XsdStateMachineBuilder::buildTerm(const XsdTerm::Ptr &term, XsdStateMachine<XsdTerm::Ptr>::StateId endState)
+{
+ if (term->isWildcard()) { // 1
+ const XsdStateMachine<XsdTerm::Ptr>::StateId b = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::InternalState);
+ m_stateMachine->addTransition(b, term, endState);
+ return b;
+ } else if (term->isElement()) { // 2
+ const XsdStateMachine<XsdTerm::Ptr>::StateId b = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::InternalState);
+ m_stateMachine->addTransition(b, term, endState);
+
+ const XsdElement::Ptr element(term);
+ if (m_mode == CheckingMode) {
+ const XsdElement::List substGroups = element->substitutionGroups();
+ for (int i = 0; i < substGroups.count(); ++i)
+ m_stateMachine->addTransition(b, substGroups.at(i), endState);
+ } else if (m_mode == ValidatingMode) {
+ const XsdElement::List substGroups = element->substitutionGroups();
+ for (int i = 0; i < substGroups.count(); ++i) {
+ if (XsdSchemaHelper::substitutionGroupOkTransitive(element, substGroups.at(i), m_namePool))
+ m_stateMachine->addTransition(b, substGroups.at(i), endState);
+ }
+ }
+
+ return b;
+ } else if (term->isModelGroup()) {
+ const XsdModelGroup::Ptr group(term);
+
+ if (group->compositor() == XsdModelGroup::ChoiceCompositor) { // 3
+ const XsdStateMachine<XsdTerm::Ptr>::StateId b = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::InternalState);
+
+ for (int i = 0; i < group->particles().count(); ++i) {
+ const XsdParticle::Ptr particle(group->particles().at(i));
+ if (particle->maximumOccurs() != 0) {
+ const XsdStateMachine<XsdTerm::Ptr>::StateId state = buildParticle(particle, endState);
+ m_stateMachine->addEpsilonTransition(b, state);
+ }
+ }
+
+ return b;
+ } else if (group->compositor() == XsdModelGroup::SequenceCompositor) { // 4
+ XsdStateMachine<XsdTerm::Ptr>::StateId currentStartState = endState;
+ XsdStateMachine<XsdTerm::Ptr>::StateId currentEndState = endState;
+
+ for (int i = (group->particles().count() - 1); i >= 0; --i) { // iterate reverse
+ const XsdParticle::Ptr particle(group->particles().at(i));
+ if (particle->maximumOccurs() != 0) {
+ currentStartState = buildParticle(particle, currentEndState);
+ currentEndState = currentStartState;
+ }
+ }
+
+ return currentStartState;
+ } else if (group->compositor() == XsdModelGroup::AllCompositor) {
+ const XsdStateMachine<XsdTerm::Ptr>::StateId newStartState = m_stateMachine->addState(XsdStateMachine<XsdTerm::Ptr>::InternalState);
+
+ const QList<XsdParticle::List> list = allCombinations(group->particles());
+
+ for (int i = 0; i < list.count(); ++i) {
+ XsdStateMachine<XsdTerm::Ptr>::StateId currentStartState = endState;
+ XsdStateMachine<XsdTerm::Ptr>::StateId currentEndState = endState;
+
+ const XsdParticle::List particles = list.at(i);
+ for (int j = (particles.count() - 1); j >= 0; --j) { // iterate reverse
+ const XsdParticle::Ptr particle(particles.at(j));
+ if (particle->maximumOccurs() != 0) {
+ currentStartState = buildParticle(particle, currentEndState);
+ currentEndState = currentStartState;
+ }
+ }
+ m_stateMachine->addEpsilonTransition(newStartState, currentStartState);
+ }
+
+ if (list.isEmpty())
+ return endState;
+ else
+ return newStartState;
+ }
+ }
+
+ Q_ASSERT(false);
+ return 0;
+}
+
+static void internalParticleLookupMap(const XsdParticle::Ptr &particle, QHash<XsdTerm::Ptr, XsdParticle::Ptr> &hash)
+{
+ hash.insert(particle->term(), particle);
+
+ if (particle->term()->isModelGroup()) {
+ const XsdModelGroup::Ptr group(particle->term());
+ const XsdParticle::List particles = group->particles();
+ for (int i = 0; i < particles.count(); ++i)
+ internalParticleLookupMap(particles.at(i), hash);
+ }
+}
+
+QHash<XsdTerm::Ptr, XsdParticle::Ptr> XsdStateMachineBuilder::particleLookupMap(const XsdParticle::Ptr &particle)
+{
+ QHash<XsdTerm::Ptr, XsdParticle::Ptr> result;
+ internalParticleLookupMap(particle, result);
+
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h b/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h
new file mode 100644
index 0000000000..011153a98d
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdStateMachineBuilder_H
+#define Patternist_XsdStateMachineBuilder_H
+
+#include "qxsdparticle_p.h"
+#include "qxsdstatemachine_p.h"
+#include "qxsdterm_p.h"
+
+#include <QtCore/QExplicitlySharedDataPointer>
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A helper class to build up validation state machines.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdStateMachineBuilder : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdStateMachineBuilder> Ptr;
+
+ enum Mode
+ {
+ CheckingMode,
+ ValidatingMode
+ };
+
+ /**
+ * Creates a new state machine builder.
+ *
+ * @param machine The state machine it should work on.
+ * @param namePool The name pool used by all schema components.
+ * @param mode The mode the machine shall be build for.
+ */
+ XsdStateMachineBuilder(XsdStateMachine<XsdTerm::Ptr> *machine, const NamePool::Ptr &namePool, Mode mode = CheckingMode);
+
+ /**
+ * Resets the state machine.
+ *
+ * @returns The initial end state.
+ */
+ XsdStateMachine<XsdTerm::Ptr>::StateId reset();
+
+ /**
+ * Prepends a start state to the given @p state.
+ * That is needed to allow the conversion of the state machine from a FSA to a DFA.
+ */
+ XsdStateMachine<XsdTerm::Ptr>::StateId addStartState(XsdStateMachine<XsdTerm::Ptr>::StateId state);
+
+ /**
+ * Creates the state machine for the given @p particle that should have the
+ * given @p endState.
+ *
+ * @returns The new start state.
+ */
+ XsdStateMachine<XsdTerm::Ptr>::StateId buildParticle(const XsdParticle::Ptr &particle, XsdStateMachine<XsdTerm::Ptr>::StateId endState);
+
+ /**
+ * Creates the state machine for the given @p term that should have the
+ * given @p endState.
+ *
+ * @returns The new start state.
+ */
+ XsdStateMachine<XsdTerm::Ptr>::StateId buildTerm(const XsdTerm::Ptr &term, XsdStateMachine<XsdTerm::Ptr>::StateId endState);
+
+ /**
+ * Returns a hash that maps each term that appears inside @p particle, to the particle it belongs.
+ *
+ * @note These information are used by XsdParticleChecker to check particle inheritance.
+ */
+ static QHash<XsdTerm::Ptr, XsdParticle::Ptr> particleLookupMap(const XsdParticle::Ptr &particle);
+
+ private:
+ XsdStateMachine<XsdTerm::Ptr> *m_stateMachine;
+ NamePool::Ptr m_namePool;
+ Mode m_mode;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdterm.cpp b/src/xmlpatterns/schema/qxsdterm.cpp
new file mode 100644
index 0000000000..1dbe34b8e6
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdterm.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdterm_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+bool XsdTerm::isElement() const
+{
+ return false;
+}
+
+bool XsdTerm::isModelGroup() const
+{
+ return false;
+}
+
+bool XsdTerm::isWildcard() const
+{
+ return false;
+}
+
+bool XsdTerm::isReference() const
+{
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdterm_p.h b/src/xmlpatterns/schema/qxsdterm_p.h
new file mode 100644
index 0000000000..f45d7919bd
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdterm_p.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdTerm_H
+#define Patternist_XsdTerm_H
+
+#include "qnamedschemacomponent_p.h"
+#include "qxsdannotated_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A base class for all particles of a model group.
+ *
+ * This class is the base class for all particles of a model group
+ * as the <em>element</em>, <em>group</em> or <em>any</em> tag, it is not supposed to
+ * be instantiated directly.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSTerm">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdTerm : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdTerm> Ptr;
+
+ /**
+ * Returns @c true if the term is an element, @c false otherwise.
+ */
+ virtual bool isElement() const;
+
+ /**
+ * Returns @c true if the term is a model group (group tag), @c false otherwise.
+ */
+ virtual bool isModelGroup() const;
+
+ /**
+ * Returns @c true if the term is a wildcard (any tag), @c false otherwise.
+ */
+ virtual bool isWildcard() const;
+
+ /**
+ * Returns @c true if the term is a reference, @c false otherwise.
+ *
+ * @note The reference term is only used internally as helper during type resolving.
+ */
+ virtual bool isReference() const;
+
+ protected:
+ /**
+ * This constructor only exists to ensure this class is subclassed.
+ */
+ inline XsdTerm() {};
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdtypechecker.cpp b/src/xmlpatterns/schema/qxsdtypechecker.cpp
new file mode 100644
index 0000000000..ab971a92d2
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdtypechecker.cpp
@@ -0,0 +1,1308 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdtypechecker_p.h"
+
+#include "qabstractdatetime_p.h"
+#include "qbase64binary_p.h"
+#include "qboolean_p.h"
+#include "qdecimal_p.h"
+#include "qderivedinteger_p.h"
+#include "qduration_p.h"
+#include "qgenericstaticcontext_p.h"
+#include "qhexbinary_p.h"
+#include "qnamespaceresolver_p.h"
+#include "qpatternplatform_p.h"
+#include "qqnamevalue_p.h"
+#include "qvaluefactory_p.h"
+#include "qxmlnamepool.h"
+#include "qxsdschemahelper_p.h"
+#include "qxsdschemamerger_p.h"
+#include "qxsdstatemachine_p.h"
+
+#include "qxsdschemadebugger_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdSchemaSourceLocationReflection::XsdSchemaSourceLocationReflection(const QSourceLocation &location)
+ : m_sourceLocation(location)
+{
+}
+
+const SourceLocationReflection* XsdSchemaSourceLocationReflection::actualReflection() const
+{
+ return this;
+}
+
+QSourceLocation XsdSchemaSourceLocationReflection::sourceLocation() const
+{
+ return m_sourceLocation;
+}
+
+
+static AnySimpleType::Ptr comparableType(const AnySimpleType::Ptr &type)
+{
+ if (!type->isDefinedBySchema()) {
+ return type;
+ } else {
+ const XsdSimpleType::Ptr simpleType(type);
+ if (type->category() == SchemaType::SimpleTypeAtomic) {
+ return simpleType->primitiveType();
+ } else if (type->category() == SchemaType::SimpleTypeList) {
+ return simpleType->itemType();
+ } else if (type->category() == SchemaType::SimpleTypeUnion) {
+ return simpleType->memberTypes().first();
+ }
+ }
+
+ Q_ASSERT(false);
+ return AnySimpleType::Ptr();
+}
+
+static int totalDigitsForSignedLongLong(long long value)
+{
+ QString number = QString::number(value);
+ if (number.startsWith(QLatin1Char('-')))
+ number = number.mid(1);
+
+ return number.length();
+}
+
+static int totalDigitsForUnsignedLongLong(unsigned long long value)
+{
+ const QString number = QString::number(value);
+ return number.length();
+}
+
+static int totalDigitsForDecimal(const QString &lexicalValue)
+{
+ const QLatin1Char zeroChar('0');
+ const int length = lexicalValue.length() - 1;
+
+ // strip leading zeros
+ int pos = 0;
+ while (lexicalValue.at(pos) == zeroChar && (pos != length))
+ pos++;
+
+ QString value = lexicalValue.mid(pos);
+
+ // if contains '.' strip trailing zeros
+ if (value.contains(QLatin1Char('.'))) {
+ pos = value.length() - 1;
+ while (value.at(pos) == zeroChar) {
+ pos--;
+ }
+
+ value = value.left(pos + 1);
+ }
+
+ // check number of digits of remaining string
+ int totalDigits = 0;
+ for (int i = 0; i < value.count(); ++i)
+ if (value.at(i).isDigit())
+ ++totalDigits;
+
+ if (totalDigits == 0)
+ totalDigits = 1;
+
+ return totalDigits;
+}
+
+static int fractionDigitsForDecimal(const QString &lexicalValue)
+{
+ // we use the lexical value here, as the conversion to double might strip
+ // away decimal positions
+
+ QString trimmedValue(lexicalValue.trimmed());
+ const int pos = trimmedValue.indexOf(QLatin1Char('.'));
+ if (pos == -1) // no '.' -> 0 fraction digits
+ return 0;
+ else
+ return (trimmedValue.length() - pos - 1);
+}
+
+XsdTypeChecker::XsdTypeChecker(const XsdSchemaContext::Ptr &context, const QVector<QXmlName> &namespaceBindings, const QSourceLocation &location)
+ : m_context(context)
+ , m_namePool(m_context->namePool())
+ , m_namespaceBindings(namespaceBindings)
+ , m_reflection(new XsdSchemaSourceLocationReflection(location))
+{
+}
+
+XsdTypeChecker::~XsdTypeChecker()
+{
+}
+
+QString XsdTypeChecker::normalizedValue(const QString &value, const XsdFacet::Hash &facets)
+{
+ if (!facets.contains(XsdFacet::WhiteSpace))
+ return value;
+
+ const XsdFacet::Ptr whiteSpaceFacet = facets.value(XsdFacet::WhiteSpace);
+
+ const DerivedString<TypeString>::Ptr facetValue = whiteSpaceFacet->value();
+ const QString stringValue = facetValue->stringValue();
+ if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Preserve))
+ return value;
+ else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Replace)) {
+ QString newValue(value);
+ newValue.replace(QLatin1Char('\t'), QLatin1Char(' '));
+ newValue.replace(QLatin1Char('\n'), QLatin1Char(' '));
+ newValue.replace(QLatin1Char('\r'), QLatin1Char(' '));
+
+ return newValue;
+ } else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Collapse)) {
+ return value.simplified();
+ }
+
+ return value;
+}
+
+XsdFacet::Hash XsdTypeChecker::mergedFacetsForType(const SchemaType::Ptr &type, const XsdSchemaContext::Ptr &context)
+{
+ if (!type)
+ return XsdFacet::Hash();
+
+ const XsdFacet::Hash baseFacets = mergedFacetsForType(type->wxsSuperType(), context);
+ const XsdFacet::Hash facets = context->facetsForType(type);
+
+ XsdFacet::Hash result = baseFacets;
+ XsdFacet::HashIterator it(facets);
+ while (it.hasNext()) {
+ it.next();
+
+ result.insert(it.key(), it.value());
+ }
+
+ return result;
+}
+
+bool XsdTypeChecker::isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType) const
+{
+ if (type->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) {
+ if (boundType)
+ *boundType = type;
+
+ return true;
+ }
+
+ if (!type->isDefinedBySchema()) {
+ // special QName check
+ if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
+ if (!XPathHelper::isQName(normalizedString)) {
+ errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2").arg(formatData(normalizedString)).arg(formatType(m_namePool, type));
+ return false;
+ }
+ }
+
+ const AtomicValue::Ptr value = fromLexical(normalizedString, type, m_context, m_reflection);
+ if (value->hasError()) {
+ errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2").arg(formatData(normalizedString)).arg(formatType(m_namePool, type));
+ return false;
+ }
+
+ if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
+ return false;
+ }
+
+ if (boundType)
+ *boundType = type;
+
+ } else {
+ const XsdSimpleType::Ptr simpleType(type);
+
+ if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) {
+ AnySimpleType::Ptr targetType = simpleType->primitiveType();
+ if (!simpleType->wxsSuperType()->isDefinedBySchema())
+ targetType = simpleType->wxsSuperType();
+
+ const AtomicValue::Ptr value = fromLexical(normalizedString, targetType, m_context, m_reflection);
+ if (value->hasError()) {
+ errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2").arg(formatData(normalizedString)).arg(formatType(m_namePool, targetType));
+ return false;
+ }
+
+ if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) {
+ return false;
+ }
+
+ if (boundType)
+ *boundType = type;
+
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) {
+ QStringList entries = normalizedString.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < entries.count(); ++i) {
+ entries[i] = normalizedValue(entries.at(i), mergedFacetsForType(simpleType->itemType(), m_context));
+ }
+
+ if (!checkConstrainingFacetsList(entries, normalizedString, simpleType->itemType(), mergedFacetsForType(simpleType, m_context), errorMsg)) {
+ return false;
+ }
+
+ for (int i = 0; i < entries.count(); ++i) {
+ if (!isValidString(entries.at(i), simpleType->itemType(), errorMsg)) {
+ return false;
+ }
+ }
+
+ if (boundType)
+ *boundType = simpleType->itemType();
+
+ } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) {
+ if (!checkConstrainingFacetsUnion(normalizedString, normalizedString, simpleType, mergedFacetsForType(simpleType, m_context), errorMsg)) {
+ return false;
+ }
+
+ const AnySimpleType::List memberTypes = simpleType->memberTypes();
+
+ bool foundValidType = false;
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ const XsdFacet::Hash mergedFacets = mergedFacetsForType(memberTypes.at(i), m_context);
+ if (isValidString(normalizedValue(normalizedString, mergedFacets), memberTypes.at(i), errorMsg)) {
+ foundValidType = true;
+
+ if (boundType)
+ *boundType = memberTypes.at(i);
+
+ break;
+ }
+ }
+
+ if (!foundValidType) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const
+{
+ const AnySimpleType::Ptr targetType = comparableType(type);
+
+ // if the type is xs:anySimpleType we just do string comparison...
+ if (targetType->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool))
+ return (value == otherValue);
+
+ if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
+ const QXmlName valueName = convertToQName(value);
+ const QXmlName otherValueName = convertToQName(otherValue);
+
+ if (valueName == otherValueName)
+ return true;
+ }
+
+ if (type->category() == SchemaType::SimpleTypeAtomic) {
+ // ... otherwise we use the casting platform for value comparison
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, value);
+ const DerivedString<TypeString>::Ptr otherValueStr = DerivedString<TypeString>::fromLexical(m_namePool, otherValue);
+
+ return XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, otherValueStr, targetType, m_context, m_reflection);
+ } else if (type->category() == SchemaType::SimpleTypeList) {
+ const QStringList values = value.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ const QStringList otherValues = otherValue.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ if (values.count() != otherValues.count())
+ return false;
+
+ for (int i = 0; i < values.count(); ++i) {
+ if (!valuesAreEqual(values.at(i), otherValues.at(i), XsdSimpleType::Ptr(type)->itemType()))
+ return false;
+ }
+
+ return true;
+ } else if (type->category() == SchemaType::SimpleTypeUnion) {
+ const AnySimpleType::List memberTypes = XsdSimpleType::Ptr(type)->memberTypes();
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ if (valuesAreEqual(value, otherValue, memberTypes.at(i))) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ return false;
+}
+
+bool XsdTypeChecker::checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const
+{
+ const XsdFacet::Hash facets = mergedFacetsForType(type, m_context);
+
+ if (BuiltinTypes::xsString->wxsTypeMatches(type) ||
+ BuiltinTypes::xsUntypedAtomic->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsString, errorMsg);
+ } else if (BuiltinTypes::xsAnyURI->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsAnyURI, errorMsg);
+ } else if (BuiltinTypes::xsNOTATION->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsNotation(value->as<QNameValue>()->qName(), facets, errorMsg);
+ } else if (BuiltinTypes::xsUnsignedByte->wxsTypeMatches(type) ||
+ BuiltinTypes::xsUnsignedInt->wxsTypeMatches(type) ||
+ BuiltinTypes::xsUnsignedLong->wxsTypeMatches(type) ||
+ BuiltinTypes::xsUnsignedShort->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsUnsignedInteger(value->as<Numeric>()->toUnsignedInteger(), lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsInteger->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsSignedInteger(value->as<Numeric>()->toInteger(), lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsFloat->wxsTypeMatches(type) ||
+ BuiltinTypes::xsDouble->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDouble(value->as<Numeric>()->toDouble(), lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsDecimal->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDecimal(value, lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsDateTime->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDateTime, errorMsg);
+ } else if (BuiltinTypes::xsDate->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDate, errorMsg);
+ } else if (BuiltinTypes::xsGYear->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYear, errorMsg);
+ } else if (BuiltinTypes::xsGYearMonth->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYearMonth, errorMsg);
+ } else if (BuiltinTypes::xsGMonth->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonth, errorMsg);
+ } else if (BuiltinTypes::xsGMonthDay->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonthDay, errorMsg);
+ } else if (BuiltinTypes::xsGDay->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGDay, errorMsg);
+ } else if (BuiltinTypes::xsTime->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDateTime(value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsTime, errorMsg);
+ } else if (BuiltinTypes::xsDuration->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsDuration(value, lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsBoolean->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsBoolean(value->as<Boolean>()->value(), lexicalValue, facets, errorMsg);
+ } else if (BuiltinTypes::xsHexBinary->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsBinary(value->as<Base64Binary>()->asByteArray(), facets, BuiltinTypes::xsHexBinary, errorMsg);
+ } else if (BuiltinTypes::xsBase64Binary->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsBinary(value->as<Base64Binary>()->asByteArray(), facets, BuiltinTypes::xsBase64Binary, errorMsg);
+ } else if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
+ return checkConstrainingFacetsQName(value->as<QNameValue>()->qName(), lexicalValue, facets, errorMsg);
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Length);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() != value.length()) {
+ errorMsg = QtXmlPatterns::tr("string content does not match the length facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() > value.length()) {
+ errorMsg = QtXmlPatterns::tr("string content does not match the minLength facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() < value.length()) {
+ errorMsg = QtXmlPatterns::tr("string content does not match the maxLength facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(value)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("string content does not match pattern facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, value);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), type, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("string content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
+ if (facetValue->toInteger() < value) {
+ errorMsg = QtXmlPatterns::tr("signed integer content does not match the maxInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
+ if (facetValue->toInteger() <= value) {
+ errorMsg = QtXmlPatterns::tr("signed integer content does not match the maxExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
+ if (facetValue->toInteger() > value) {
+ errorMsg = QtXmlPatterns::tr("signed integer content does not match the minInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection);
+ if (facetValue->toInteger() >= value) {
+ errorMsg = QtXmlPatterns::tr("signed integer content does not match the minExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, QString::number(value));
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsLong, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("signed integer content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("signed integer content does not match pattern facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::TotalDigits)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
+ const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
+
+ if (totalDigitsForSignedLongLong(value) > facetValue->toInteger()) {
+ errorMsg = QtXmlPatterns::tr("signed integer content does not match in the totalDigits facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
+ if (facetValue->toUnsignedInteger() < value) {
+ errorMsg = QtXmlPatterns::tr("unsigned integer content does not match the maxInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
+ if (facetValue->toUnsignedInteger() <= value) {
+ errorMsg = QtXmlPatterns::tr("unsigned integer content does not match the maxExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
+ if (facetValue->toUnsignedInteger() > value) {
+ errorMsg = QtXmlPatterns::tr("unsigned integer content does not match the minInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection);
+ if (facetValue->toUnsignedInteger() >= value) {
+ errorMsg = QtXmlPatterns::tr("unsigned integer content does not match the minExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, QString::number(value));
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsUnsignedLong, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("unsigned integer content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("unsigned integer content does not match pattern facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::TotalDigits)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
+ const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
+
+ if (totalDigitsForUnsignedLongLong(value) > facetValue->toInteger()) {
+ errorMsg = QtXmlPatterns::tr("unsigned integer content does not match in the totalDigits facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
+ if (facetValue->toDouble() < value) {
+ errorMsg = QtXmlPatterns::tr("double content does not match the maxInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
+ if (facetValue->toDouble() <= value) {
+ errorMsg = QtXmlPatterns::tr("double content does not match the maxExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
+ if (facetValue->toDouble() > value) {
+ errorMsg = QtXmlPatterns::tr("double content does not match the minInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection);
+ if (facetValue->toDouble() >= value) {
+ errorMsg = QtXmlPatterns::tr("double content does not match the minExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(m_namePool, QString::number(value));
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsDouble, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("double content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("double content does not match pattern facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::FractionDigits)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::FractionDigits);
+ const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
+
+ if (fractionDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
+ errorMsg = QtXmlPatterns::tr("decimal content does not match in the fractionDigits facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::TotalDigits)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits);
+ const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value();
+
+ if (totalDigitsForDecimal(lexicalValue) > facetValue->toInteger()) {
+ errorMsg = QtXmlPatterns::tr("decimal content does not match in the totalDigits facet");
+ return false;
+ }
+ }
+
+ return checkConstrainingFacetsDouble(value->as<Decimal>()->toDouble(), lexicalValue, facets, errorMsg);
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() < value) {
+ errorMsg = QtXmlPatterns::tr("date time content does not match the maxInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() <= value) {
+ errorMsg = QtXmlPatterns::tr("date time content does not match the maxExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() > value) {
+ errorMsg = QtXmlPatterns::tr("date time content does not match the minInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() >= value) {
+ errorMsg = QtXmlPatterns::tr("date time content does not match the minExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ if (facetValue->toDateTime() == value) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("date time content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("date time content does not match pattern facet");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsDuration(const AtomicValue::Ptr&, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::MaximumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MaximumInclusive)->value(), AtomicComparator::OperatorLessThan, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ errorMsg = QtXmlPatterns::tr("duration content does not match the maxInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MaximumExclusive)->value(), AtomicComparator::OperatorLessOrEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ errorMsg = QtXmlPatterns::tr("duration content does not match the maxExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumInclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MinimumInclusive)->value(), AtomicComparator::OperatorGreaterThan, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ errorMsg = QtXmlPatterns::tr("duration content does not match the minInclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumExclusive)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MinimumExclusive)->value(), AtomicComparator::OperatorGreaterOrEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ errorMsg = QtXmlPatterns::tr("duration content does not match the minExclusive facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(m_namePool, lexicalValue);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(multiValue.at(j), AtomicComparator::OperatorEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("duration content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("duration content does not match pattern facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsBoolean(bool, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("boolean content does not match pattern facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsBinary(const QByteArray &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Length);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() != value.length()) {
+ errorMsg = QtXmlPatterns::tr("binary content does not match the length facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() > value.length()) {
+ errorMsg = QtXmlPatterns::tr("binary content does not match the minLength facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength);
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value();
+ if (length->toInteger() < value.length()) {
+ errorMsg = QtXmlPatterns::tr("binary content does not match the maxLength facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const Base64Binary::Ptr binary = ValueFactory::fromLexical(multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue(), type, m_context, m_reflection);
+ const QByteArray facetValue = binary->as<Base64Binary>()->asByteArray();
+ if (value == facetValue) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("binary content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ //TODO: implement
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsQName(const QXmlName &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ // always true
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ // always true
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ // always true
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ if (!XPathHelper::isQName(lexicalValue)) {
+ errorMsg = QtXmlPatterns::tr("invalid QName content: %1").arg(formatData(lexicalValue));
+ return false;
+ }
+
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
+
+ if (value == facetValue) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("QName content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("QName content does not match pattern facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ // deprecated by spec
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ // deprecated by spec
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ // deprecated by spec
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QXmlName facetValue = multiValue.at(j)->as<QNameValue>()->qName();
+
+ if (value == facetValue) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("notation content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ //TODO: implement
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Length)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(XsdFacet::Length)->value();
+ if (value->toInteger() != values.count()) {
+ errorMsg = QtXmlPatterns::tr("list content does not match length facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MinimumLength)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(XsdFacet::MinimumLength)->value();
+ if (value->toInteger() > values.count()) {
+ errorMsg = QtXmlPatterns::tr("list content does not match minLength facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::MaximumLength)) {
+ const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(XsdFacet::MaximumLength)->value();
+ if (value->toInteger() < values.count()) {
+ errorMsg = QtXmlPatterns::tr("list content does not match maxLength facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Enumeration)) {
+
+ bool found = false;
+
+ // we have to handle lists with QName derived items differently
+ if (BuiltinTypes::xsQName->wxsTypeMatches(itemType) || BuiltinTypes::xsNOTATION->wxsTypeMatches(itemType)) {
+ // first convert the string values from the instance document to a list of QXmlName
+ QList<QXmlName> instanceValues;
+ for (int i = 0; i < values.count(); ++i) {
+ instanceValues.append(convertToQName(values.at(i)));
+ }
+
+ // fetch the values from the facet and create a list of QXmlNames for each of them
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ for (int i = 0; i < multiValue.count(); ++i) {
+ const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ // create the list of atomic string values
+ QList<QXmlName> facetValues;
+ for (int j = 0; j < facetValueList.count(); ++j) {
+ facetValues.append(convertToQName(facetValueList.at(j)));
+ }
+
+ // check if both lists have the same length
+ if (instanceValues.count() != facetValues.count())
+ continue;
+
+ // check if both lists are equal, that means the contain equal items in the same order
+ bool matchesAll = true;
+ for (int j = 0; j < instanceValues.count(); ++j) {
+ if (instanceValues.at(j) != facetValues.at(j)) {
+ matchesAll = false;
+ break;
+ }
+ }
+
+ if (matchesAll) {
+ found = true;
+ break;
+ }
+ }
+ } else {
+ // first convert the string values from the instance document to atomic values of type string
+ AtomicValue::List instanceValues;
+ for (int i = 0; i < values.count(); ++i) {
+ instanceValues.append(DerivedString<TypeString>::fromLexical(m_namePool, values.at(i)));
+ }
+
+ // fetch the values from the facet and create a list of atomic string values for each of them
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+
+ const AnySimpleType::Ptr targetType = comparableType(itemType);
+
+ const AtomicValue::List multiValue = facet->multiValue();
+ for (int i = 0; i < multiValue.count(); ++i) {
+ const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts);
+
+ // create the list of atomic string values
+ AtomicValue::List facetValues;
+ for (int j = 0; j < facetValueList.count(); ++j) {
+ facetValues.append(DerivedString<TypeString>::fromLexical(m_namePool, facetValueList.at(j)));
+ }
+
+ // check if both lists have the same length
+ if (instanceValues.count() != facetValues.count())
+ continue;
+
+ // check if both lists are equal, that means the contain equal items in the same order
+ bool matchesAll = true;
+ for (int j = 0; j < instanceValues.count(); ++j) {
+ if (!XsdSchemaHelper::constructAndCompare(instanceValues.at(j), AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) {
+ matchesAll = false;
+ break;
+ }
+ }
+
+ if (matchesAll) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("list content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("list content does not match pattern facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+bool XsdTypeChecker::checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const
+{
+ if (facets.contains(XsdFacet::Enumeration)) {
+ const AnySimpleType::List memberTypes = simpleType->memberTypes();
+
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration);
+
+ // convert the instance value into an atomic string value
+ const DerivedString<TypeString>::Ptr valueString = DerivedString<TypeString>::fromLexical(m_namePool, value);
+
+ // collect the facet values into a list of atomic string values
+ const AtomicValue::List facetValues = facet->multiValue();
+
+ // compare the instance value against the facetValues for each member type and
+ // search for a match
+
+ bool found = false;
+ for (int i = 0; i < memberTypes.count(); ++i) {
+ const AnySimpleType::Ptr targetType = comparableType(memberTypes.at(i));
+ for (int j = 0; j < facetValues.count(); ++j) {
+ if (XsdSchemaHelper::constructAndCompare(valueString, AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("union content is not listed in the enumeration facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Pattern)) {
+ const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern);
+ const AtomicValue::List multiValue = facet->multiValue();
+ bool found = false;
+ for (int j = 0; j < multiValue.count(); ++j) {
+ const QString pattern = multiValue.at(j)->as<DerivedString<TypeString> >()->stringValue();
+ const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection);
+ if (exp.exactMatch(lexicalValue)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ errorMsg = QtXmlPatterns::tr("union content does not match pattern facet");
+ return false;
+ }
+ }
+ if (facets.contains(XsdFacet::Assertion)) {
+ //TODO: implement
+ }
+
+ return true;
+}
+
+AtomicValue::Ptr XsdTypeChecker::fromLexical(const QString &value, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const
+{
+ if (type->name(m_namePool) == BuiltinTypes::xsNOTATION->name(m_namePool) || type->name(m_namePool) == BuiltinTypes::xsQName->name(m_namePool)) {
+ if (value.simplified().isEmpty())
+ return ValidationError::createError(QtXmlPatterns::tr("data of type %1 are not allowed to be empty").arg(formatType(m_namePool, BuiltinTypes::xsNOTATION)));
+
+ const QXmlName valueName = convertToQName(value);
+ return QNameValue::fromValue(m_namePool, valueName);
+ } else {
+ return ValueFactory::fromLexical(value, type, context, reflection);
+ }
+}
+
+QXmlName XsdTypeChecker::convertToQName(const QString &name) const
+{
+ const int pos = name.indexOf(QLatin1Char(':'));
+
+ QXmlName::PrefixCode prefixCode = 0;
+ QXmlName::NamespaceCode namespaceCode;
+ QXmlName::LocalNameCode localNameCode;
+ if (pos != -1) {
+ prefixCode = m_context->namePool()->allocatePrefix(name.left(pos));
+ namespaceCode = StandardNamespaces::empty;
+ for (int i = 0; i < m_namespaceBindings.count(); ++i) {
+ if (m_namespaceBindings.at(i).prefix() == prefixCode) {
+ namespaceCode = m_namespaceBindings.at(i).namespaceURI();
+ break;
+ }
+ }
+ localNameCode = m_context->namePool()->allocateLocalName(name.mid(pos + 1));
+ } else {
+ prefixCode = StandardPrefixes::empty;
+ namespaceCode = StandardNamespaces::empty;
+ for (int i = 0; i < m_namespaceBindings.count(); ++i) {
+ if (m_namespaceBindings.at(i).prefix() == prefixCode) {
+ namespaceCode = m_namespaceBindings.at(i).namespaceURI();
+ break;
+ }
+ }
+ localNameCode = m_context->namePool()->allocateLocalName(name);
+ }
+
+ return QXmlName(namespaceCode, localNameCode, prefixCode);
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdtypechecker_p.h b/src/xmlpatterns/schema/qxsdtypechecker_p.h
new file mode 100644
index 0000000000..2af20db9ad
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdtypechecker_p.h
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdTypeChecker_H
+#define Patternist_XsdTypeChecker_H
+
+#include <QtXmlPatterns/QSourceLocation>
+
+#include "qschematype_p.h"
+#include "qsourcelocationreflection_p.h"
+#include "qxsdschemacontext_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QXmlQuery;
+
+namespace QPatternist
+{
+ /**
+ * @short An implementation of SourceLocationReflection that takes a QSourceLocation.
+ *
+ * This is a convenience class which provides a QSourceLocation with a SourceLocationReflection
+ * interface.
+ */
+ class XsdSchemaSourceLocationReflection : public SourceLocationReflection
+ {
+ public:
+ XsdSchemaSourceLocationReflection(const QSourceLocation &location);
+
+ virtual const SourceLocationReflection *actualReflection() const;
+ virtual QSourceLocation sourceLocation() const;
+
+ private:
+ const QSourceLocation m_sourceLocation;
+ };
+
+ /**
+ * @short The class that provides methods for checking a string against a type.
+ *
+ * The class provides functionality for type-aware string handling.
+ */
+ class XsdTypeChecker
+ {
+ public:
+ /**
+ * Creates a new type checker.
+ *
+ * @param context The schema context that is used for error reporting.
+ * @param namespaceBindings The namespace bindings that shall be used to check against xs:QName based types.
+ * @param location The source location that is used for error reporting.
+ */
+ XsdTypeChecker(const XsdSchemaContext::Ptr &context, const QVector<QXmlName> &namespaceBindings, const QSourceLocation &location);
+
+ /**
+ * Destroys the type checker.
+ */
+ ~XsdTypeChecker();
+
+ /**
+ * Returns all facets for the given @p type.
+ *
+ * The list of facets is created by following the type hierarchy from xs:anyType down to the given type
+ * and merging the facets in each step.
+ */
+ static XsdFacet::Hash mergedFacetsForType(const SchemaType::Ptr &type, const XsdSchemaContext::Ptr &context);
+
+ /**
+ * Returns the normalized value for the given @p value.
+ *
+ * The normalized value is the original value with all the white space facets
+ * applied on it.
+ *
+ * @param value The original value.
+ * @param facets The hash of all facets of the values type.
+ */
+ static QString normalizedValue(const QString &value, const XsdFacet::Hash &facets);
+
+ /**
+ * Checks whether the @p normalizedString is valid according the given @p type.
+ *
+ * @param normalizedString The string in normalized form (whitespace facets applied).
+ * @param type The type the string shall be tested against.
+ * @param errorMsg Contains the error message if the normalizedString does not match the type.
+ * @param boundType The type the data was bound to during validation.
+ *
+ * @note The @p boundType only differs from @p type if the type is derived from an based union value.
+ */
+ bool isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType = 0) const;
+
+ /**
+ * Returns whether the given @p value and @p otherValue are of @p type and are equal.
+ */
+ bool valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const;
+
+ private:
+ Q_DISABLE_COPY(XsdTypeChecker)
+
+ /**
+ * Checks the given value against the facets of @p type.
+ */
+ bool checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const;
+ bool checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const;
+ bool checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const;
+ bool checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const;
+ bool checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const;
+ bool checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const;
+ bool checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const;
+ bool checkConstrainingFacetsDuration(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const;
+ bool checkConstrainingFacetsBoolean(bool value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const;
+ bool checkConstrainingFacetsBinary(const QByteArray &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const;
+ bool checkConstrainingFacetsQName(const QXmlName&, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const;
+ bool checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const;
+ bool checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const;
+ bool checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const;
+
+ /**
+ * Creates an atomic value of @p type from the given string @p value.
+ */
+ AtomicValue::Ptr fromLexical(const QString &value, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const;
+
+ /**
+ * Converts a qualified name into a QXmlName according to the namespace
+ * mappings of the current node.
+ */
+ QXmlName convertToQName(const QString &name) const;
+
+ XsdSchemaContext::Ptr m_context;
+ XsdSchema::Ptr m_schema;
+ const NamePool::Ptr m_namePool;
+ QVector<QXmlName> m_namespaceBindings;
+ SourceLocationReflection* m_reflection;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsduserschematype.cpp b/src/xmlpatterns/schema/qxsduserschematype.cpp
new file mode 100644
index 0000000000..b8bf7e73b3
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsduserschematype.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * NOTE: This file is included by qxsduserschematype_p.h
+ * if you need some includes, put them in qxsduserschematype_p.h (outside of the namespace)
+ */
+
+template<typename TSuperClass>
+void XsdUserSchemaType<TSuperClass>::setName(const QXmlName &name)
+{
+ m_name = name;
+}
+
+template<typename TSuperClass>
+QXmlName XsdUserSchemaType<TSuperClass>::name(const NamePool::Ptr&) const
+{
+ return m_name;
+}
+
+template<typename TSuperClass>
+QString XsdUserSchemaType<TSuperClass>::displayName(const NamePool::Ptr &np) const
+{
+ return np->displayName(m_name);
+}
+
+template<typename TSuperClass>
+void XsdUserSchemaType<TSuperClass>::setDerivationConstraints(const SchemaType::DerivationConstraints &constraints)
+{
+ m_derivationConstraints = constraints;
+}
+
+template<typename TSuperClass>
+SchemaType::DerivationConstraints XsdUserSchemaType<TSuperClass>::derivationConstraints() const
+{
+ return m_derivationConstraints;
+}
diff --git a/src/xmlpatterns/schema/qxsduserschematype_p.h b/src/xmlpatterns/schema/qxsduserschematype_p.h
new file mode 100644
index 0000000000..ab70f91a00
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsduserschematype_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdUserSchemaType_H
+#define Patternist_XsdUserSchemaType_H
+
+#include "qnamedschemacomponent_p.h"
+#include "qschematype_p.h"
+#include "qxsdannotated_p.h"
+
+template<typename N, typename M> class QHash;
+template<typename N> class QList;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A base class for all user defined simple and complex types.
+ *
+ * This class was introduced to combine the SchemaType class and the
+ * NamedSchemaComponent class without explicit inheritance.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ template<typename TSuperClass>
+ class XsdUserSchemaType : public TSuperClass, public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdUserSchemaType> Ptr;
+
+ /**
+ * Sets the @p name of the type.
+ */
+ void setName(const QXmlName &name);
+
+ /**
+ * Returns the name of the type.
+ *
+ * @param namePool The pool the name belongs to.
+ */
+ virtual QXmlName name(const NamePool::Ptr &namePool) const;
+
+ /**
+ * Returns the display name of the type.
+ *
+ * @param namePool The pool the name belongs to.
+ */
+ virtual QString displayName(const NamePool::Ptr &namePool) const;
+
+ /**
+ * Sets the derivation @p constraints of the type.
+ */
+ void setDerivationConstraints(const SchemaType::DerivationConstraints &constraints);
+
+ /**
+ * Returns the derivation constraints of the type.
+ */
+ SchemaType::DerivationConstraints derivationConstraints() const;
+
+ private:
+ QXmlName m_name;
+ SchemaType::DerivationConstraints m_derivationConstraints;
+ };
+
+ #include "qxsduserschematype.cpp"
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp
new file mode 100644
index 0000000000..8e1645a9a8
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdvalidatedxmlnodemodel_p.h"
+
+#include <QtCore/QUrl>
+#include <QtCore/QVariant>
+#include <QtCore/QVector>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+XsdValidatedXmlNodeModel::XsdValidatedXmlNodeModel(const QAbstractXmlNodeModel *model)
+ : m_internalModel(const_cast<QAbstractXmlNodeModel*>(model))
+{
+}
+
+XsdValidatedXmlNodeModel::~XsdValidatedXmlNodeModel()
+{
+}
+
+QUrl XsdValidatedXmlNodeModel::baseUri(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->baseUri(index);
+}
+
+QUrl XsdValidatedXmlNodeModel::documentUri(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->documentUri(index);
+}
+
+QXmlNodeModelIndex::NodeKind XsdValidatedXmlNodeModel::kind(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->kind(index);
+}
+
+QXmlNodeModelIndex::DocumentOrder XsdValidatedXmlNodeModel::compareOrder(const QXmlNodeModelIndex &index, const QXmlNodeModelIndex &otherIndex) const
+{
+ return m_internalModel->compareOrder(index, otherIndex);
+}
+
+QXmlNodeModelIndex XsdValidatedXmlNodeModel::root(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->root(index);
+}
+
+QXmlName XsdValidatedXmlNodeModel::name(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->name(index);
+}
+
+QString XsdValidatedXmlNodeModel::stringValue(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->stringValue(index);
+}
+
+QVariant XsdValidatedXmlNodeModel::typedValue(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->typedValue(index);
+}
+
+QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > XsdValidatedXmlNodeModel::iterate(const QXmlNodeModelIndex &index, QXmlNodeModelIndex::Axis axis) const
+{
+ return m_internalModel->iterate(index, axis);
+}
+
+QPatternist::ItemIteratorPtr XsdValidatedXmlNodeModel::sequencedTypedValue(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->sequencedTypedValue(index);
+}
+
+QPatternist::ItemTypePtr XsdValidatedXmlNodeModel::type(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->type(index);
+}
+
+QXmlName::NamespaceCode XsdValidatedXmlNodeModel::namespaceForPrefix(const QXmlNodeModelIndex &index, const QXmlName::PrefixCode prefix) const
+{
+ return m_internalModel->namespaceForPrefix(index, prefix);
+}
+
+bool XsdValidatedXmlNodeModel::isDeepEqual(const QXmlNodeModelIndex &index, const QXmlNodeModelIndex &otherIndex) const
+{
+ return m_internalModel->isDeepEqual(index, otherIndex);
+}
+
+void XsdValidatedXmlNodeModel::sendNamespaces(const QXmlNodeModelIndex &index, QAbstractXmlReceiver *const receiver) const
+{
+ m_internalModel->sendNamespaces(index, receiver);
+}
+
+QVector<QXmlName> XsdValidatedXmlNodeModel::namespaceBindings(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->namespaceBindings(index);
+}
+
+QXmlNodeModelIndex XsdValidatedXmlNodeModel::elementById(const QXmlName &name) const
+{
+ return m_internalModel->elementById(name);
+}
+
+QVector<QXmlNodeModelIndex> XsdValidatedXmlNodeModel::nodesByIdref(const QXmlName &name) const
+{
+ return m_internalModel->nodesByIdref(name);
+}
+
+void XsdValidatedXmlNodeModel::copyNodeTo(const QXmlNodeModelIndex &index, QAbstractXmlReceiver *const receiver, const NodeCopySettings &settings) const
+{
+ return m_internalModel->copyNodeTo(index, receiver, settings);
+}
+
+QXmlNodeModelIndex XsdValidatedXmlNodeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const
+{
+ return m_internalModel->nextFromSimpleAxis(axis, origin);
+}
+
+QVector<QXmlNodeModelIndex> XsdValidatedXmlNodeModel::attributes(const QXmlNodeModelIndex &index) const
+{
+ return m_internalModel->attributes(index);
+}
+
+void XsdValidatedXmlNodeModel::setAssignedElement(const QXmlNodeModelIndex &index, const XsdElement::Ptr &element)
+{
+ m_assignedElements.insert(index, element);
+}
+
+XsdElement::Ptr XsdValidatedXmlNodeModel::assignedElement(const QXmlNodeModelIndex &index) const
+{
+ if (m_assignedElements.contains(index))
+ return m_assignedElements.value(index);
+ else
+ return XsdElement::Ptr();
+}
+
+void XsdValidatedXmlNodeModel::setAssignedAttribute(const QXmlNodeModelIndex &index, const XsdAttribute::Ptr &attribute)
+{
+ m_assignedAttributes.insert(index, attribute);
+}
+
+XsdAttribute::Ptr XsdValidatedXmlNodeModel::assignedAttribute(const QXmlNodeModelIndex &index) const
+{
+ if (m_assignedAttributes.contains(index))
+ return m_assignedAttributes.value(index);
+ else
+ return XsdAttribute::Ptr();
+}
+
+void XsdValidatedXmlNodeModel::setAssignedType(const QXmlNodeModelIndex &index, const SchemaType::Ptr &type)
+{
+ m_assignedTypes.insert(index, type);
+}
+
+SchemaType::Ptr XsdValidatedXmlNodeModel::assignedType(const QXmlNodeModelIndex &index) const
+{
+ if (m_assignedTypes.contains(index))
+ return m_assignedTypes.value(index);
+ else
+ return SchemaType::Ptr();
+}
+
+void XsdValidatedXmlNodeModel::addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding)
+{
+ m_idIdRefBindings[id].insert(binding);
+}
+
+QStringList XsdValidatedXmlNodeModel::idIdRefBindingIds() const
+{
+ return m_idIdRefBindings.keys();
+}
+
+QSet<NamedSchemaComponent::Ptr> XsdValidatedXmlNodeModel::idIdRefBindings(const QString &id) const
+{
+ return m_idIdRefBindings.value(id);
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h
new file mode 100644
index 0000000000..579f41a9f6
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdValidatedXmlNodeModel_H
+#define Patternist_XsdValidatedXmlNodeModel_H
+
+#include "qabstractxmlnodemodel.h"
+
+#include "qabstractxmlforwarditerator_p.h"
+#include "qitem_p.h"
+#include "qschematype_p.h"
+#include "qxsdelement_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short A delegate class that wraps around a QAbstractXmlNodeModel and provides
+ * additional validation specific information.
+ *
+ * This class represents the input XML document enriched with additional type
+ * information that has been assigned during validation.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdValidatedXmlNodeModel : public QAbstractXmlNodeModel
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdValidatedXmlNodeModel> Ptr;
+ typedef QList<Ptr> List;
+
+ /**
+ * Creates a new validated xml node model.
+ */
+ XsdValidatedXmlNodeModel(const QAbstractXmlNodeModel *model);
+
+ /**
+ * Destroys the validated xml node model.
+ */
+ virtual ~XsdValidatedXmlNodeModel();
+
+ virtual QUrl baseUri(const QXmlNodeModelIndex &ni) const;
+ virtual QUrl documentUri(const QXmlNodeModelIndex &ni) const;
+ virtual QXmlNodeModelIndex::NodeKind kind(const QXmlNodeModelIndex &ni) const;
+ virtual QXmlNodeModelIndex::DocumentOrder compareOrder(const QXmlNodeModelIndex &ni1, const QXmlNodeModelIndex &ni2) const;
+ virtual QXmlNodeModelIndex root(const QXmlNodeModelIndex &n) const;
+ virtual QXmlName name(const QXmlNodeModelIndex &ni) const;
+ virtual QString stringValue(const QXmlNodeModelIndex &n) const;
+ virtual QVariant typedValue(const QXmlNodeModelIndex &n) const;
+ virtual QExplicitlySharedDataPointer<QAbstractXmlForwardIterator<QXmlNodeModelIndex> > iterate(const QXmlNodeModelIndex &ni, QXmlNodeModelIndex::Axis axis) const;
+ virtual QPatternist::ItemIteratorPtr sequencedTypedValue(const QXmlNodeModelIndex &ni) const;
+ virtual QPatternist::ItemTypePtr type(const QXmlNodeModelIndex &ni) const;
+ virtual QXmlName::NamespaceCode namespaceForPrefix(const QXmlNodeModelIndex &ni, const QXmlName::PrefixCode prefix) const;
+ virtual bool isDeepEqual(const QXmlNodeModelIndex &ni1, const QXmlNodeModelIndex &ni2) const;
+ virtual void sendNamespaces(const QXmlNodeModelIndex &n, QAbstractXmlReceiver *const receiver) const;
+ virtual QVector<QXmlName> namespaceBindings(const QXmlNodeModelIndex &n) const;
+ virtual QXmlNodeModelIndex elementById(const QXmlName &NCName) const;
+ virtual QVector<QXmlNodeModelIndex> nodesByIdref(const QXmlName &NCName) const;
+ virtual void copyNodeTo(const QXmlNodeModelIndex &node, QAbstractXmlReceiver *const receiver, const NodeCopySettings &) const;
+
+ /**
+ * Sets the @p element that is assigned to the xml node at @p index.
+ */
+ void setAssignedElement(const QXmlNodeModelIndex &index, const XsdElement::Ptr &element);
+
+ /**
+ * Returns the element that is assigned to the xml node at @p index.
+ */
+ XsdElement::Ptr assignedElement(const QXmlNodeModelIndex &index) const;
+
+ /**
+ * Sets the @p attribute that is assigned to the xml node at @p index.
+ */
+ void setAssignedAttribute(const QXmlNodeModelIndex &index, const XsdAttribute::Ptr &attribute);
+
+ /**
+ * Returns the attribute that is assigned to the xml node at @p index.
+ */
+ XsdAttribute::Ptr assignedAttribute(const QXmlNodeModelIndex &index) const;
+
+ /**
+ * Sets the @p type that is assigned to the xml node at @p index.
+ *
+ * @note The type can be a different than the type of the element or
+ * attribute that is assigned to the index, since the instance
+ * document can overwrite it by xsi:type.
+ */
+ void setAssignedType(const QXmlNodeModelIndex &index, const SchemaType::Ptr &type);
+
+ /**
+ * Returns the type that is assigned to the xml node at @p index.
+ */
+ SchemaType::Ptr assignedType(const QXmlNodeModelIndex &index) const;
+
+ /**
+ * Adds the attribute or element @p binding with the given @p id.
+ */
+ void addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding);
+
+ /**
+ * Returns a list of all binding ids.
+ */
+ QStringList idIdRefBindingIds() const;
+
+ /**
+ * Returns the set of bindings with the given @p id.
+ */
+ QSet<NamedSchemaComponent::Ptr> idIdRefBindings(const QString &id) const;
+
+ protected:
+ virtual QXmlNodeModelIndex nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const;
+ virtual QVector<QXmlNodeModelIndex> attributes(const QXmlNodeModelIndex &element) const;
+
+ private:
+ QAbstractXmlNodeModel::Ptr m_internalModel;
+ QHash<QXmlNodeModelIndex, XsdElement::Ptr> m_assignedElements;
+ QHash<QXmlNodeModelIndex, XsdAttribute::Ptr> m_assignedAttributes;
+ QHash<QXmlNodeModelIndex, SchemaType::Ptr> m_assignedTypes;
+ QHash<QString, QSet<NamedSchemaComponent::Ptr> > m_idIdRefBindings;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp b/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp
new file mode 100644
index 0000000000..12fc477b55
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp
@@ -0,0 +1,1245 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdvalidatinginstancereader_p.h"
+
+#include "qabstractdatetime_p.h"
+#include "qacceltreeresourceloader_p.h"
+#include "qbase64binary_p.h"
+#include "qboolean_p.h"
+#include "qderivedinteger_p.h"
+#include "qduration_p.h"
+#include "qgenericstaticcontext_p.h"
+#include "qhexbinary_p.h"
+#include "qnamespaceresolver_p.h"
+#include "qpatternplatform_p.h"
+#include "qqnamevalue_p.h"
+#include "qsourcelocationreflection_p.h"
+#include "qvaluefactory_p.h"
+#include "qxmlnamepool.h"
+#include "qxmlquery_p.h"
+#include "qxmlschema_p.h"
+#include "qxsdschemahelper_p.h"
+#include "qxsdschemamerger_p.h"
+#include "qxsdstatemachine_p.h"
+#include "qxsdstatemachinebuilder_p.h"
+#include "qxsdtypechecker_p.h"
+
+#include "qxsdschemadebugger_p.h"
+
+#include <QtCore/QFile>
+#include <QtXmlPatterns/QXmlQuery>
+#include <QtXmlPatterns/QXmlResultItems>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+namespace QPatternist
+{
+ template <>
+ template <>
+ bool XsdStateMachine<XsdTerm::Ptr>::inputEqualsTransition<QXmlName>(QXmlName name, XsdTerm::Ptr term) const
+ {
+ if (term->isElement()) {
+ return (XsdElement::Ptr(term)->name(m_namePool) == name);
+ } else if (term->isWildcard()) {
+ // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
+ if (name.namespaceURI() == StandardNamespaces::empty) {
+ name.setNamespaceURI(m_namePool->allocateNamespace(XsdWildcard::absentNamespace()));
+ }
+
+ return XsdSchemaHelper::wildcardAllowsExpandedName(name, XsdWildcard::Ptr(term), m_namePool);
+ }
+
+ return false;
+ }
+}
+
+XsdValidatingInstanceReader::XsdValidatingInstanceReader(const XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context)
+ : XsdInstanceReader(model, context)
+ , m_model(const_cast<XsdValidatedXmlNodeModel*>(model))
+ , m_namePool(m_context->namePool())
+ , m_xsiNilName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("nil")))
+ , m_xsiTypeName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("type")))
+ , m_xsiSchemaLocationName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("schemaLocation")))
+ , m_xsiNoNamespaceSchemaLocationName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("noNamespaceSchemaLocation")))
+ , m_documentUri(documentUri)
+{
+ m_idRefsType = m_context->schemaTypeFactory()->createSchemaType(m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("IDREFS")));
+}
+
+void XsdValidatingInstanceReader::addSchema(const XsdSchema::Ptr &schema, const QUrl &locationUrl)
+{
+ if (!m_mergedSchemas.contains(locationUrl)) {
+ m_mergedSchemas.insert(locationUrl, QStringList() << schema->targetNamespace());
+ } else {
+ QStringList &targetNamespaces = m_mergedSchemas[locationUrl];
+ if (targetNamespaces.contains(schema->targetNamespace()))
+ return;
+
+ targetNamespaces.append(schema->targetNamespace());
+ }
+
+ const XsdSchemaMerger merger(m_schema, schema);
+ m_schema = merger.mergedSchema();
+/*
+ XsdSchemaDebugger dbg(m_namePool);
+ dbg.dumpSchema(m_schema);
+*/
+}
+
+bool XsdValidatingInstanceReader::read()
+{
+ while (!atEnd()) {
+ readNext();
+
+ if (isEndElement())
+ return true;
+
+ if (isStartElement()) {
+ const QXmlName elementName = name();
+ const QXmlItem currentItem = item();
+ bool hasStateMachine = false;
+ XsdElement::Ptr processedElement;
+
+ if (!validate(hasStateMachine, processedElement))
+ return false;
+
+ read();
+
+ if (processedElement) { // for wildcard with 'skip' we have no element
+ m_model->setAssignedElement(currentItem.toNodeModelIndex(), processedElement);
+
+ // check identity constraints after all child nodes have been
+ // validated, so that we know there assigned types
+ validateIdentityConstraint(processedElement, currentItem);
+ }
+
+ if (!m_stateMachines.isEmpty() && hasStateMachine) {
+ if (!m_stateMachines.top().inEndState()) {
+ error(QtXmlPatterns::tr("element %1 is missing child element").arg(formatKeyword(m_namePool->displayName(elementName))));
+ return false;
+ }
+ m_stateMachines.pop();
+ }
+ }
+ }
+
+ // final validations
+
+ // check IDREF occurrences
+ const QStringList ids = m_model->idIdRefBindingIds();
+ QSetIterator<QString> it(m_idRefs);
+ while (it.hasNext()) {
+ const QString id = it.next();
+ if (!ids.contains(id)) {
+ error(QtXmlPatterns::tr("there is one IDREF value with no corresponding ID: %1").arg(formatKeyword(id)));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void XsdValidatingInstanceReader::error(const QString &msg) const
+{
+ const_cast<XsdSchemaContext*>(m_context.data())->error(msg, XsdSchemaContext::XSDError, sourceLocation());
+}
+
+bool XsdValidatingInstanceReader::loadSchema(const QString &targetNamespace, const QUrl &location)
+{
+ const AutoPtr<QNetworkReply> reply(AccelTreeResourceLoader::load(location, m_context->networkAccessManager(),
+ m_context, AccelTreeResourceLoader::ContinueOnError));
+ if (!reply)
+ return true;
+
+ // we have to create a separated schema context here, that however shares the type factory
+ XsdSchemaContext::Ptr context(new XsdSchemaContext(m_namePool));
+ context->m_schemaTypeFactory = m_context->m_schemaTypeFactory;
+
+ QXmlSchemaPrivate schema(context);
+ schema.load(reply.data(), location, targetNamespace);
+ if (!schema.isValid()) {
+ error(QtXmlPatterns::tr("loaded schema file is invalid"));
+ return false;
+ }
+
+ addSchema(schema.m_schemaParserContext->schema(), location);
+
+ return true;
+}
+
+bool XsdValidatingInstanceReader::validate(bool &hasStateMachine, XsdElement::Ptr &processedElement)
+{
+ // first check if a custom schema is defined
+ if (hasAttribute(m_xsiSchemaLocationName)) {
+ const QString schemaLocation = attribute(m_xsiSchemaLocationName);
+ const QStringList parts = schemaLocation.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ if ((parts.count()%2) == 1) {
+ error(QtXmlPatterns::tr("%1 contains invalid data").arg(formatKeyword(m_namePool, m_xsiSchemaLocationName)));
+ return false;
+ }
+
+ for (int i = 0; i < parts.count(); i += 2) {
+ const QString identifier = QString::fromLatin1("%1 %2").arg(parts.at(i)).arg(parts.at(i + 1));
+ if (m_processedSchemaLocations.contains(identifier))
+ continue;
+ else
+ m_processedSchemaLocations.insert(identifier);
+
+ // check constraint 4) from http://www.w3.org/TR/xmlschema-1/#schema-loc (only valid for XML Schema 1.0?)
+ if (m_processedNamespaces.contains(parts.at(i))) {
+ error(QtXmlPatterns::tr("xsi:schemaLocation namespace %1 has already appeared earlier in the instance document").arg(formatKeyword(parts.at(i))));
+ return false;
+ }
+
+ QUrl url(parts.at(i + 1));
+ if (url.isRelative()) {
+ Q_ASSERT(m_documentUri.isValid());
+
+ url = m_documentUri.resolved(url);
+ }
+
+ loadSchema(parts.at(i), url);
+ }
+ }
+
+ if (hasAttribute(m_xsiNoNamespaceSchemaLocationName)) {
+ const QString schemaLocation = attribute(m_xsiNoNamespaceSchemaLocationName);
+
+ if (!m_processedSchemaLocations.contains(schemaLocation)) {
+ m_processedSchemaLocations.insert(schemaLocation);
+
+ if (m_processedNamespaces.contains(QString())) {
+ error(QtXmlPatterns::tr("xsi:noNamespaceSchemaLocation cannot appear after the first no-namespace element or attribute"));
+ return false;
+ }
+
+ QUrl url(schemaLocation);
+ if (url.isRelative()) {
+ Q_ASSERT(m_documentUri.isValid());
+
+ url = m_documentUri.resolved(url);
+ }
+
+ loadSchema(QString(), url);
+ }
+ }
+
+ m_processedNamespaces.insert(m_namePool->stringForNamespace(name().namespaceURI()));
+
+ if (!m_schema) {
+ error(QtXmlPatterns::tr("no schema defined for validation"));
+ return false;
+ }
+
+ // check if we are 'inside' a type definition
+ if (m_stateMachines.isEmpty()) {
+ // find out the type of the top-level element
+ XsdElement::Ptr element = elementByName(name());
+ if (!element) {
+ if (!hasAttribute(m_xsiTypeName)) {
+ error(QtXmlPatterns::tr("no definition for element %1 available").arg(formatKeyword(m_namePool, name())));
+ return false;
+ }
+
+ // This instance document has an element with no definition in the schema
+ // but an explicitly given type, that is fine according to the spec.
+ // We will create an element definition manually here and continue the
+ // normal validation process
+ element = XsdElement::Ptr(new XsdElement());
+ element->setName(name());
+ element->setIsAbstract(false);
+ element->setIsNillable(hasAttribute(m_xsiNilName));
+
+ const QString type = qNameAttribute(m_xsiTypeName);
+ const QXmlName typeName = convertToQName(type);
+
+ const SchemaType::Ptr elementType = typeByName(typeName);
+ if (!elementType) {
+ error(QtXmlPatterns::tr("specified type %1 is not known to the schema").arg(formatType(m_namePool, typeName)));
+ return false;
+ }
+ element->setType(elementType);
+ }
+
+ // rememeber the element we process
+ processedElement = element;
+
+ if (!validateElement(element, hasStateMachine)) {
+ return false;
+ }
+
+ } else {
+ if (!m_stateMachines.top().proceed<QXmlName>(name())) {
+ error(QtXmlPatterns::tr("element %1 is not defined in this scope").arg(formatKeyword(m_namePool, name())));
+ return false;
+ }
+
+ const XsdTerm::Ptr term = m_stateMachines.top().lastTransition();
+ if (term->isElement()) {
+ const XsdElement::Ptr element(term);
+
+ // rememeber the element we process
+ processedElement = element;
+
+ if (!validateElement(element, hasStateMachine))
+ return false;
+
+ } else {
+ const XsdWildcard::Ptr wildcard(term);
+ if (wildcard->processContents() != XsdWildcard::Skip) {
+ XsdElement::Ptr elementDeclaration = elementByName(name());
+ if (!elementDeclaration) {
+ if (hasAttribute(m_xsiTypeName)) {
+ // This instance document has an element with no definition in the schema
+ // but an explicitly given type, that is fine according to the spec.
+ // We will create an element definition manually here and continue the
+ // normal validation process
+ elementDeclaration = XsdElement::Ptr(new XsdElement());
+ elementDeclaration->setName(name());
+ elementDeclaration->setIsAbstract(false);
+ elementDeclaration->setIsNillable(hasAttribute(m_xsiNilName));
+
+ const QString type = qNameAttribute(m_xsiTypeName);
+ const QXmlName typeName = convertToQName(type);
+
+ const SchemaType::Ptr elementType = typeByName(typeName);
+ if (!elementType) {
+ error(QtXmlPatterns::tr("specified type %1 is not known to the schema").arg(formatType(m_namePool, typeName)));
+ return false;
+ }
+ elementDeclaration->setType(elementType);
+ }
+ }
+
+ if (!elementDeclaration) {
+ if (wildcard->processContents() == XsdWildcard::Strict) {
+ error(QtXmlPatterns::tr("declaration for element %1 does not exist").arg(formatKeyword(m_namePool->displayName(name()))));
+ return false;
+ } else {
+ // in this case we put a state machine for the xs:anyType on the statemachine stack,
+ // so we accept every content of this element
+
+ createAndPushStateMachine(anyType()->contentType()->particle());
+ hasStateMachine = true;
+ }
+ } else {
+ if (!validateElement(elementDeclaration, hasStateMachine)) {
+ if (wildcard->processContents() == XsdWildcard::Strict) {
+ error(QtXmlPatterns::tr("element %1 contains invalid content").arg(formatKeyword(m_namePool->displayName(name()))));
+ return false;
+ }
+ }
+
+ // rememeber the type of that element node
+ m_model->setAssignedType(item().toNodeModelIndex(), elementDeclaration->type());
+ }
+ } else { // wildcard process contents type is Skip
+ // in this case we put a state machine for the xs:anyType on the statemachine stack,
+ // so we accept every content of this element
+
+ const XsdWildcard::Ptr wildcard(new XsdWildcard());
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ wildcard->setProcessContents(XsdWildcard::Skip);
+
+ const XsdParticle::Ptr outerParticle(new XsdParticle());
+ outerParticle->setMinimumOccurs(1);
+ outerParticle->setMaximumOccurs(1);
+
+ const XsdParticle::Ptr innerParticle(new XsdParticle());
+ innerParticle->setMinimumOccurs(0);
+ innerParticle->setMaximumOccursUnbounded(true);
+ innerParticle->setTerm(wildcard);
+
+ const XsdModelGroup::Ptr outerModelGroup(new XsdModelGroup());
+ outerModelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
+ outerModelGroup->setParticles(XsdParticle::List() << innerParticle);
+ outerParticle->setTerm(outerModelGroup);
+
+ createAndPushStateMachine(outerParticle);
+ hasStateMachine = true;
+ }
+ }
+ }
+
+ return true;
+}
+
+void XsdValidatingInstanceReader::createAndPushStateMachine(const XsdParticle::Ptr &particle)
+{
+ XsdStateMachine<XsdTerm::Ptr> stateMachine(m_namePool);
+
+ XsdStateMachineBuilder builder(&stateMachine, m_namePool, XsdStateMachineBuilder::ValidatingMode);
+ const XsdStateMachine<XsdTerm::Ptr>::StateId endState = builder.reset();
+ const XsdStateMachine<XsdTerm::Ptr>::StateId startState = builder.buildParticle(particle, endState);
+ builder.addStartState(startState);
+
+/*
+ QString fileName = QString("/tmp/foo_%1.dot").arg(m_namePool->displayName(complexType->name(m_namePool)));
+ QString pngFileName = QString("/tmp/foo_%1.png").arg(m_namePool->displayName(complexType->name(m_namePool)));
+ QFile file(fileName);
+ file.open(QIODevice::WriteOnly);
+ stateMachine.outputGraph(&file, "Hello");
+ file.close();
+ ::system(QString("dot -Tpng %1 -o%2").arg(fileName).arg(pngFileName).toLatin1().data());
+*/
+
+ stateMachine = stateMachine.toDFA();
+
+ m_stateMachines.push(stateMachine);
+}
+
+bool XsdValidatingInstanceReader::validateElement(const XsdElement::Ptr &declaration, bool &hasStateMachine)
+{
+ // http://www.w3.org/TR/xmlschema11-1/#d0e10998
+
+ bool isNilled = false;
+
+ // 1 tested already, 'declaration' corresponds D
+
+ // 2
+ if (declaration->isAbstract()) {
+ error(QtXmlPatterns::tr("element %1 is declared as abstract").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+
+ // 3
+ if (!declaration->isNillable()) {
+ if (hasAttribute(m_xsiNilName)) {
+ error(QtXmlPatterns::tr("element %1 is not nillable").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false; // 3.1
+ }
+ } else {
+ if (hasAttribute(m_xsiNilName)) {
+ const QString value = attribute(m_xsiNilName);
+ const Boolean::Ptr nil = Boolean::fromLexical(value);
+ if (nil->hasError()) {
+ error(QtXmlPatterns::tr("attribute %1 contains invalid data: %1").arg(formatKeyword(QLatin1String("nil"))).arg(formatData(value)));
+ return false;
+ }
+
+ // 3.2.3
+ if (nil->as<Boolean>()->value() == true) {
+ // 3.2.3.1
+ if (hasChildElement() || hasChildText()) {
+ error(QtXmlPatterns::tr("element contains content although it is nillable"));
+ return false;
+ }
+
+ // 3.2.3.2
+ if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
+ error(QtXmlPatterns::tr("fixed value constrained not allowed if element is nillable"));
+ return false;
+ }
+ }
+
+ isNilled = nil->as<Boolean>()->value();
+ }
+ }
+
+ SchemaType::Ptr finalElementType = declaration->type();
+
+ // 4
+ if (hasAttribute(m_xsiTypeName)) {
+ const QString type = qNameAttribute(m_xsiTypeName);
+ const QXmlName typeName = convertToQName(type);
+
+ const SchemaType::Ptr elementType = typeByName(typeName);
+ // 4.1
+ if (!elementType) {
+ error(QtXmlPatterns::tr("specified type %1 is not known to the schema").arg(formatType(m_namePool, typeName)));
+ return false;
+ }
+
+ // 4.2
+ SchemaType::DerivationConstraints constraints = 0;
+ if (declaration->disallowedSubstitutions() & NamedSchemaComponent::ExtensionConstraint)
+ constraints |= SchemaType::ExtensionConstraint;
+ if (declaration->disallowedSubstitutions() & NamedSchemaComponent::RestrictionConstraint)
+ constraints |= SchemaType::RestrictionConstraint;
+
+ if (!XsdSchemaHelper::isValidlySubstitutable(elementType, declaration->type(), constraints)) {
+ if (declaration->type()->name(m_namePool) != BuiltinTypes::xsAnyType->name(m_namePool)) { // xs:anyType is a valid substitutable type here
+ error(QtXmlPatterns::tr("specified type %1 is not validly substitutable with element type %2").arg(formatType(m_namePool, elementType)).arg(formatType(m_namePool, declaration->type())));
+ return false;
+ }
+ }
+
+ finalElementType = elementType;
+ }
+
+ if (!validateElementType(declaration, finalElementType, isNilled, hasStateMachine))
+ return false;
+
+ return true;
+}
+
+bool XsdValidatingInstanceReader::validateElementType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#d0e11749
+
+ // 1 checked already
+
+ // 2
+ if (type->isComplexType() && type->isDefinedBySchema()) {
+ if (XsdComplexType::Ptr(type)->isAbstract()) {
+ error(QtXmlPatterns::tr("complex type %1 is not allowed to be abstract").arg(formatType(m_namePool, type)));
+ return false;
+ }
+ }
+
+ // 3
+ if (type->isSimpleType())
+ return validateElementSimpleType(declaration, type, isNilled); // 3.1
+ else
+ return validateElementComplexType(declaration, type, isNilled, hasStateMachine); // 3.2
+}
+
+bool XsdValidatingInstanceReader::validateElementSimpleType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#d0e11749
+
+ // 3.1.1
+ const QSet<QXmlName> allowedAttributes(QSet<QXmlName>() << m_xsiNilName << m_xsiTypeName << m_xsiSchemaLocationName << m_xsiNoNamespaceSchemaLocationName);
+ QSet<QXmlName> elementAttributes = attributeNames();
+ elementAttributes.subtract(allowedAttributes);
+ if (!elementAttributes.isEmpty()) {
+ error(QtXmlPatterns::tr("element %1 contains not allowed attributes").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+
+ // 3.1.2
+ if (hasChildElement()) {
+ error(QtXmlPatterns::tr("element %1 contains not allowed child element").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+
+ // 3.1.3
+ if (!isNilled) {
+ const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(type, m_context);
+
+ QString actualValue;
+ if (hasChildText()) {
+ actualValue = XsdTypeChecker::normalizedValue(text(), facets);
+ } else {
+ if (declaration->valueConstraint())
+ actualValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
+ }
+
+ QString errorMsg;
+ AnySimpleType::Ptr boundType;
+
+ const XsdTypeChecker checker(m_context, namespaceBindings(item().toNodeModelIndex()), sourceLocation());
+ if (!checker.isValidString(actualValue, type, errorMsg, &boundType)) {
+ error(QtXmlPatterns::tr("content of element %1 does not match its type definition: %2").arg(formatKeyword(declaration->displayName(m_namePool))).arg(errorMsg));
+ return false;
+ }
+
+ // additional check
+ if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
+ const QString actualConstraintValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
+ if (!text().isEmpty() && !checker.valuesAreEqual(actualValue, actualConstraintValue, type)) {
+ error(QtXmlPatterns::tr("content of element %1 does not match defined value constraint").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+ }
+ }
+
+ // 4 checked in validateElement already
+
+ // rememeber the type of that element node
+ m_model->setAssignedType(item().toNodeModelIndex(), type);
+
+ const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(type, m_context);
+ const QString actualValue = XsdTypeChecker::normalizedValue(text(), facets);
+
+ if (BuiltinTypes::xsID->wxsTypeMatches(type)) {
+ addIdIdRefBinding(actualValue, declaration);
+ }
+
+ if (m_idRefsType->wxsTypeMatches(type)) {
+ const QStringList idRefs = actualValue.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < idRefs.count(); ++i) {
+ m_idRefs.insert(idRefs.at(i));
+ }
+ } else if (BuiltinTypes::xsIDREF->wxsTypeMatches(type)) {
+ m_idRefs.insert(actualValue);
+ }
+
+ return true;
+}
+
+static bool hasIDAttributeUse(const XsdAttributeUse::List &uses)
+{
+ const int count = uses.count();
+ for (int i = 0; i < count; ++i) {
+ if (BuiltinTypes::xsID->wxsTypeMatches(uses.at(i)->attribute()->type()))
+ return true;
+ }
+
+ return false;
+}
+
+bool XsdValidatingInstanceReader::validateElementComplexType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cvc-complex-type
+
+ // 1
+ if (!isNilled) {
+ XsdComplexType::Ptr complexType;
+
+ if (type->isDefinedBySchema()) {
+ complexType = XsdComplexType::Ptr(type);
+ } else {
+ if (type->name(m_namePool) == BuiltinTypes::xsAnyType->name(m_namePool))
+ complexType = anyType();
+ }
+
+ if (complexType) {
+ // 1.1
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty) {
+ if (hasChildText() || hasChildElement()) {
+ error(QtXmlPatterns::tr("element %1 contains not allowed child content").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+ }
+
+ // 1.2
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) {
+ if (hasChildElement()) {
+ error(QtXmlPatterns::tr("element %1 contains not allowed child element").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+
+ const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(complexType->contentType()->simpleType(), m_context);
+ QString actualValue;
+ if (hasChildText()) {
+ actualValue = XsdTypeChecker::normalizedValue(text(), facets);
+ } else {
+ if (declaration->valueConstraint())
+ actualValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
+ }
+
+ QString errorMsg;
+ AnySimpleType::Ptr boundType;
+ const XsdTypeChecker checker(m_context, namespaceBindings(item().toNodeModelIndex()), sourceLocation());
+ if (!checker.isValidString(actualValue, complexType->contentType()->simpleType(), errorMsg, &boundType)) {
+ error(QtXmlPatterns::tr("content of element %1 does not match its type definition: %2").arg(formatKeyword(declaration->displayName(m_namePool))).arg(errorMsg));
+ return false;
+ }
+
+ // additional check
+ if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
+ if (!checker.valuesAreEqual(actualValue, declaration->valueConstraint()->value(), boundType)) {
+ error(QtXmlPatterns::tr("content of element %1 does not match defined value constraint").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+ }
+ }
+
+ // 1.3
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) {
+ if (!text().simplified().isEmpty()) {
+ error(QtXmlPatterns::tr("element %1 contains not allowed text content").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+ }
+
+ // 1.4
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly ||
+ complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) {
+
+ if (complexType->contentType()->particle()) {
+ createAndPushStateMachine(complexType->contentType()->particle());
+ hasStateMachine = true;
+ }
+
+ // additional check
+ if (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) {
+ if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) {
+ if (hasChildElement()) {
+ error(QtXmlPatterns::tr("element %1 can not contain other elements, as it has a fixed content").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+
+ const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(complexType->contentType()->simpleType(), m_context);
+ QString actualValue;
+ if (hasChildText()) {
+ actualValue = XsdTypeChecker::normalizedValue(text(), facets);
+ } else {
+ if (declaration->valueConstraint())
+ actualValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
+ }
+
+ if (actualValue != declaration->valueConstraint()->value()) {
+ error(QtXmlPatterns::tr("content of element %1 does not match defined value constraint").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (type->isDefinedBySchema()) {
+ const XsdComplexType::Ptr complexType(type);
+
+ // create a lookup hash for faster access
+ QHash<QXmlName, XsdAttributeUse::Ptr> attributeUseHash;
+ {
+ const XsdAttributeUse::List attributeUses = complexType->attributeUses();
+ for (int i = 0; i < attributeUses.count(); ++i)
+ attributeUseHash.insert(attributeUses.at(i)->attribute()->name(m_namePool), attributeUses.at(i));
+ }
+
+ const QSet<QXmlName> attributes(attributeNames());
+
+ // 3
+ QHashIterator<QXmlName, XsdAttributeUse::Ptr> usesIt(attributeUseHash);
+ while (usesIt.hasNext()) {
+ usesIt.next();
+
+ if (usesIt.value()->isRequired()) {
+ if (!attributes.contains(usesIt.key())) {
+ error(QtXmlPatterns::tr("element %1 is missing required attribute %2").arg(formatKeyword(declaration->displayName(m_namePool)))
+ .arg(formatKeyword(m_namePool->displayName(usesIt.key()))));
+ return false;
+ }
+ }
+ }
+
+ bool hasIDAttribute = hasIDAttributeUse(complexType->attributeUses());
+
+ // 2
+ QSetIterator<QXmlName> it(attributes);
+ while (it.hasNext()) {
+ const QXmlName attributeName = it.next();
+
+ // skip builtin attributes
+ if (attributeName == m_xsiNilName ||
+ attributeName == m_xsiTypeName ||
+ attributeName == m_xsiSchemaLocationName ||
+ attributeName == m_xsiNoNamespaceSchemaLocationName)
+ continue;
+
+ // 2.1
+ if (attributeUseHash.contains(attributeName) && (attributeUseHash.value(attributeName)->useType() != XsdAttributeUse::ProhibitedUse)) {
+ if (!validateAttribute(attributeUseHash.value(attributeName), attribute(attributeName)))
+ return false;
+ } else { // 2.2
+ if (complexType->attributeWildcard()) {
+ const XsdWildcard::Ptr wildcard(complexType->attributeWildcard());
+ if (!validateAttributeWildcard(attributeName, wildcard)) {
+ error(QtXmlPatterns::tr("attribute %1 does not match the attribute wildcard").arg(formatKeyword(m_namePool->displayName(attributeName))));
+ return false;
+ }
+
+ if (wildcard->processContents() != XsdWildcard::Skip) {
+ const XsdAttribute::Ptr attributeDeclaration = attributeByName(attributeName);
+
+ if (!attributeDeclaration) {
+ if (wildcard->processContents() == XsdWildcard::Strict) {
+ error(QtXmlPatterns::tr("declaration for attribute %1 does not exist").arg(formatKeyword(m_namePool->displayName(attributeName))));
+ return false;
+ }
+ } else {
+ if (BuiltinTypes::xsID->wxsTypeMatches(attributeDeclaration->type())) {
+ if (hasIDAttribute) {
+ error(QtXmlPatterns::tr("element %1 contains two attributes of type %2")
+ .arg(formatKeyword(declaration->displayName(m_namePool)))
+ .arg(formatKeyword("ID")));
+ return false;
+ }
+
+ hasIDAttribute = true;
+ }
+
+ if (!validateAttribute(attributeDeclaration, attribute(attributeName))) {
+ if (wildcard->processContents() == XsdWildcard::Strict) {
+ error(QtXmlPatterns::tr("attribute %1 contains invalid content").arg(formatKeyword(m_namePool->displayName(attributeName))));
+ return false;
+ }
+ }
+ }
+ }
+ } else {
+ error(QtXmlPatterns::tr("element %1 contains unknown attribute %2").arg(formatKeyword(declaration->displayName(m_namePool)))
+ .arg(formatKeyword(m_namePool->displayName(attributeName))));
+ return false;
+ }
+ }
+ }
+ }
+
+ // 4
+ // so what?...
+
+ // 5
+ // hmm...
+
+ // 6
+ // TODO: check assertions
+
+ // 7
+ // TODO: check type table restrictions
+
+ // rememeber the type of that element node
+ m_model->setAssignedType(item().toNodeModelIndex(), type);
+
+ return true;
+}
+
+bool XsdValidatingInstanceReader::validateAttribute(const XsdAttributeUse::Ptr &declaration, const QString &value)
+{
+ const AnySimpleType::Ptr attributeType = declaration->attribute()->type();
+ const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(attributeType, m_context);
+
+ const QString actualValue = XsdTypeChecker::normalizedValue(value, facets);
+
+ QString errorMsg;
+ AnySimpleType::Ptr boundType;
+
+ const QXmlNodeModelIndex index = attributeItem(declaration->attribute()->name(m_namePool)).toNodeModelIndex();
+
+ const XsdTypeChecker checker(m_context, namespaceBindings(index), sourceLocation());
+ if (!checker.isValidString(actualValue, attributeType, errorMsg, &boundType)) {
+ error(QtXmlPatterns::tr("content of attribute %1 does not match its type definition: %2").arg(formatKeyword(declaration->attribute()->displayName(m_namePool))).arg(errorMsg));
+ return false;
+ }
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#cvc-au
+ if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Fixed) {
+ const QString actualConstraintValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
+ if (!checker.valuesAreEqual(actualValue, actualConstraintValue, attributeType)) {
+ error(QtXmlPatterns::tr("content of attribute %1 does not match defined value constraint").arg(formatKeyword(declaration->attribute()->displayName(m_namePool))));
+ return false;
+ }
+ }
+
+ if (BuiltinTypes::xsID->wxsTypeMatches(declaration->attribute()->type())) {
+ addIdIdRefBinding(actualValue, declaration->attribute());
+ }
+
+ if (m_idRefsType->wxsTypeMatches(declaration->attribute()->type())) {
+ const QStringList idRefs = actualValue.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < idRefs.count(); ++i)
+ m_idRefs.insert(idRefs.at(i));
+ } else if (BuiltinTypes::xsIDREF->wxsTypeMatches(declaration->attribute()->type())) {
+ m_idRefs.insert(actualValue);
+ }
+
+ m_model->setAssignedType(index, declaration->attribute()->type());
+ m_model->setAssignedAttribute(index, declaration->attribute());
+
+ return true;
+}
+
+//TODO: merge that with the method above
+bool XsdValidatingInstanceReader::validateAttribute(const XsdAttribute::Ptr &declaration, const QString &value)
+{
+ const AnySimpleType::Ptr attributeType = declaration->type();
+ const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(attributeType, m_context);
+
+ const QString actualValue = XsdTypeChecker::normalizedValue(value, facets);
+
+ QString errorMsg;
+ AnySimpleType::Ptr boundType;
+
+ const QXmlNodeModelIndex index = attributeItem(declaration->name(m_namePool)).toNodeModelIndex();
+
+ const XsdTypeChecker checker(m_context, namespaceBindings(index), sourceLocation());
+ if (!checker.isValidString(actualValue, attributeType, errorMsg, &boundType)) {
+ error(QtXmlPatterns::tr("content of attribute %1 does not match its type definition: %2").arg(formatKeyword(declaration->displayName(m_namePool))).arg(errorMsg));
+ return false;
+ }
+
+ // @see http://www.w3.org/TR/xmlschema11-1/#cvc-au
+ if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdAttribute::ValueConstraint::Fixed) {
+ const QString actualConstraintValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets);
+ if (!checker.valuesAreEqual(actualValue, actualConstraintValue, attributeType)) {
+ error(QtXmlPatterns::tr("content of attribute %1 does not match defined value constraint").arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+ }
+
+ if (BuiltinTypes::xsID->wxsTypeMatches(declaration->type())) {
+ addIdIdRefBinding(actualValue, declaration);
+ }
+
+ if (m_idRefsType->wxsTypeMatches(declaration->type())) {
+ const QStringList idRefs = actualValue.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < idRefs.count(); ++i)
+ m_idRefs.insert(idRefs.at(i));
+ } else if (BuiltinTypes::xsIDREF->wxsTypeMatches(declaration->type())) {
+ m_idRefs.insert(actualValue);
+ }
+
+ m_model->setAssignedType(index, declaration->type());
+ m_model->setAssignedAttribute(index, declaration);
+
+ return true;
+}
+
+bool XsdValidatingInstanceReader::validateAttributeWildcard(const QXmlName &attributeName, const XsdWildcard::Ptr &wildcard)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#cvc-wildcard
+
+ // wildcards using XsdWildcard::absentNamespace, so we have to fix that here
+ QXmlName name(attributeName);
+ if (name.namespaceURI() == StandardNamespaces::empty) {
+ name.setNamespaceURI(m_namePool->allocateNamespace(XsdWildcard::absentNamespace()));
+ }
+
+ return XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, m_namePool);
+}
+
+bool XsdValidatingInstanceReader::validateIdentityConstraint(const XsdElement::Ptr &element, const QXmlItem &currentItem)
+{
+ const XsdIdentityConstraint::List constraints = element->identityConstraints();
+
+ for (int i = 0; i < constraints.count(); ++i) {
+ const XsdIdentityConstraint::Ptr constraint = constraints.at(i);
+
+ TargetNode::Set targetNodeSet, qualifiedNodeSet;
+ selectNodeSets(element, currentItem, constraint, targetNodeSet, qualifiedNodeSet);
+
+ if (constraint->category() == XsdIdentityConstraint::Unique) {
+ if (!validateUniqueIdentityConstraint(element, constraint, qualifiedNodeSet))
+ return false;
+ } else if (constraint->category() == XsdIdentityConstraint::Key) {
+ if (!validateKeyIdentityConstraint(element, constraint, targetNodeSet, qualifiedNodeSet))
+ return false;
+ }
+ }
+
+ // we do the keyref check in a separated run to make sure that all keys are available
+ for (int i = 0; i < constraints.count(); ++i) {
+ const XsdIdentityConstraint::Ptr constraint = constraints.at(i);
+ if (constraint->category() == XsdIdentityConstraint::KeyReference) {
+ TargetNode::Set targetNodeSet, qualifiedNodeSet;
+ selectNodeSets(element, currentItem, constraint, targetNodeSet, qualifiedNodeSet);
+
+ if (!validateKeyRefIdentityConstraint(element, constraint, qualifiedNodeSet))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool XsdValidatingInstanceReader::validateUniqueIdentityConstraint(const XsdElement::Ptr&, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#d0e32243
+
+ // 4.1
+ const XsdSchemaSourceLocationReflection reflection(sourceLocation());
+
+ QSetIterator<TargetNode> it(qualifiedNodeSet);
+ while (it.hasNext()) {
+ const TargetNode node = it.next();
+ QSetIterator<TargetNode> innerIt(qualifiedNodeSet);
+ while (innerIt.hasNext()) {
+ const TargetNode innerNode = innerIt.next();
+
+ if (node == innerNode) // do not compare with ourself
+ continue;
+
+ if (node.fieldsAreEqual(innerNode, m_namePool, m_context, &reflection)) {
+ error(QtXmlPatterns::tr("non-unique value found for constraint %1").arg(formatKeyword(constraint->displayName(m_namePool))));
+ return false;
+ }
+ }
+ }
+
+ m_idcKeys.insert(constraint->name(m_namePool), qualifiedNodeSet);
+
+ return true;
+}
+
+bool XsdValidatingInstanceReader::validateKeyIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &targetNodeSet, const TargetNode::Set &qualifiedNodeSet)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#d0e32243
+
+ // 4.2
+ const XsdSchemaSourceLocationReflection reflection(sourceLocation());
+
+ // 4.2.1
+ if (targetNodeSet.count() != qualifiedNodeSet.count()) {
+ error(QtXmlPatterns::tr("key constraint %1 contains absent fields").arg(formatKeyword(constraint->displayName(m_namePool))));
+ return false;
+ }
+
+ // 4.2.2
+ if (!validateUniqueIdentityConstraint(element, constraint, qualifiedNodeSet))
+ return false;
+
+ // 4.2.3
+ QSetIterator<TargetNode> it(qualifiedNodeSet);
+ while (it.hasNext()) {
+ const TargetNode node = it.next();
+ const QVector<QXmlItem> fieldItems = node.fieldItems();
+ for (int i = 0; i < fieldItems.count(); ++i) {
+ const QXmlNodeModelIndex index = fieldItems.at(i).toNodeModelIndex();
+ if (m_model->kind(index) == QXmlNodeModelIndex::Element) {
+ const XsdElement::Ptr declaration = m_model->assignedElement(index);
+ if (declaration && declaration->isNillable()) {
+ error(QtXmlPatterns::tr("key constraint %1 contains references nillable element %2")
+ .arg(formatKeyword(constraint->displayName(m_namePool)))
+ .arg(formatKeyword(declaration->displayName(m_namePool))));
+ return false;
+ }
+ }
+ }
+ }
+
+ m_idcKeys.insert(constraint->name(m_namePool), qualifiedNodeSet);
+
+ return true;
+}
+
+bool XsdValidatingInstanceReader::validateKeyRefIdentityConstraint(const XsdElement::Ptr&, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet)
+{
+ // @see http://www.w3.org/TR/xmlschema11-1/#d0e32243
+
+ // 4.3
+ const XsdSchemaSourceLocationReflection reflection(sourceLocation());
+
+ const TargetNode::Set keySet = m_idcKeys.value(constraint->referencedKey()->name(m_namePool));
+
+ QSetIterator<TargetNode> it(qualifiedNodeSet);
+ while (it.hasNext()) {
+ const TargetNode node = it.next();
+
+ bool foundMatching = false;
+
+ QSetIterator<TargetNode> keyIt(keySet);
+ while (keyIt.hasNext()) {
+ const TargetNode keyNode = keyIt.next();
+
+ if (node.fieldsAreEqual(keyNode, m_namePool, m_context, &reflection)) {
+ foundMatching = true;
+ break;
+ }
+ }
+
+ if (!foundMatching) {
+ error(QtXmlPatterns::tr("no referenced value found for key reference %1").arg(formatKeyword(constraint->displayName(m_namePool))));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+QXmlQuery XsdValidatingInstanceReader::createXQuery(const QList<QXmlName> &namespaceBindings, const QXmlItem &contextNode, const QString &queryString) const
+{
+ // create a public name pool from our name pool
+ QXmlNamePool namePool(m_namePool.data());
+
+ // the QXmlQuery shall work with the same name pool as we do
+ QXmlQuery query(namePool);
+
+ // add additional namespace bindings
+ QXmlQueryPrivate *queryPrivate = query.d;
+
+ for (int i = 0; i < namespaceBindings.count(); ++i) {
+ if (!namespaceBindings.at(i).prefix() == StandardPrefixes::empty)
+ queryPrivate->addAdditionalNamespaceBinding(namespaceBindings.at(i));
+ }
+
+ // set the context node for that query and the query string
+ query.setFocus(contextNode);
+ query.setQuery(queryString, m_documentUri);
+
+ return query;
+}
+
+bool XsdValidatingInstanceReader::selectNodeSets(const XsdElement::Ptr&, const QXmlItem &currentItem, const XsdIdentityConstraint::Ptr &constraint, TargetNode::Set &targetNodeSet, TargetNode::Set &qualifiedNodeSet)
+{
+ // at first select all target nodes
+ const XsdXPathExpression::Ptr selector = constraint->selector();
+ const XsdXPathExpression::List fields = constraint->fields();
+
+ QXmlQuery query = createXQuery(selector->namespaceBindings(), currentItem, selector->expression());
+
+ QXmlResultItems resultItems;
+ query.evaluateTo(&resultItems);
+
+ // now we iterate over all target nodes and select the fields for each node
+ QXmlItem item(resultItems.next());
+ while (!item.isNull()) {
+
+ TargetNode targetNode(item);
+
+ for (int i = 0; i < fields.count(); ++i) {
+ const XsdXPathExpression::Ptr field = fields.at(i);
+ QXmlQuery fieldQuery = createXQuery(field->namespaceBindings(), item, field->expression());
+
+ QXmlResultItems fieldResultItems;
+ fieldQuery.evaluateTo(&fieldResultItems);
+
+ // copy result into vetor for better testing...
+ QVector<QXmlItem> fieldVector;
+ QXmlItem fieldItem(fieldResultItems.next());
+ while (!fieldItem.isNull()) {
+ fieldVector.append(fieldItem);
+ fieldItem = fieldResultItems.next();
+ }
+
+ if (fieldVector.count() > 1) {
+ error(QtXmlPatterns::tr("more than one value found for field %1").arg(formatData(field->expression())));
+ return false;
+ }
+
+ if (fieldVector.count() == 1) {
+ fieldItem = fieldVector.first();
+
+ const QXmlNodeModelIndex index = fieldItem.toNodeModelIndex();
+ const SchemaType::Ptr type = m_model->assignedType(index);
+
+ bool typeOk = true;
+ if (type->isComplexType()) {
+ if (type->isDefinedBySchema()) {
+ if (XsdComplexType::Ptr(type)->contentType()->variety() != XsdComplexType::ContentType::Simple)
+ typeOk = false;
+ } else {
+ typeOk = false;
+ }
+ }
+ if (!typeOk) {
+ error(QtXmlPatterns::tr("field %1 has no simple type").arg(formatData(field->expression())));
+ return false;
+ }
+
+ SchemaType::Ptr targetType = type;
+ QString value = m_model->stringValue(fieldItem.toNodeModelIndex());
+
+ if (type->isDefinedBySchema()) {
+ if (type->isSimpleType())
+ targetType = XsdSimpleType::Ptr(type)->primitiveType();
+ else
+ targetType = XsdComplexType::Ptr(type)->contentType()->simpleType();
+ } else {
+ if (BuiltinTypes::xsAnySimpleType->name(m_namePool) == type->name(m_namePool)) {
+ targetType = BuiltinTypes::xsString;
+ value = QLatin1String("___anySimpleType_value");
+ }
+ }
+
+ // if it is xs:QName derived type, we normalize the name content
+ // and do a string comparison
+ if (BuiltinTypes::xsQName->wxsTypeMatches(type)) {
+ targetType = BuiltinTypes::xsString;
+
+ const QXmlName qName = convertToQName(value.trimmed());
+ value = QString::fromLatin1("%1:%2").arg(m_namePool->stringForNamespace(qName.namespaceURI())).arg(m_namePool->stringForLocalName(qName.localName()));
+ }
+
+ targetNode.addField(fieldItem, value, targetType);
+ } else {
+ // we add an empty entry here, that makes comparison easier later on
+ targetNode.addField(QXmlItem(), QString(), SchemaType::Ptr());
+ }
+ }
+
+ targetNodeSet.insert(targetNode);
+
+ item = resultItems.next();
+ }
+
+ // copy all items from target node set to qualified node set, that have no empty fields
+ QSetIterator<TargetNode> it(targetNodeSet);
+ while (it.hasNext()) {
+ const TargetNode node = it.next();
+ if (node.emptyFieldsCount() == 0)
+ qualifiedNodeSet.insert(node);
+ }
+
+ return true;
+}
+
+XsdElement::Ptr XsdValidatingInstanceReader::elementByName(const QXmlName &name) const
+{
+ return m_schema->element(name);
+}
+
+XsdAttribute::Ptr XsdValidatingInstanceReader::attributeByName(const QXmlName &name) const
+{
+ return m_schema->attribute(name);
+}
+
+SchemaType::Ptr XsdValidatingInstanceReader::typeByName(const QXmlName &name) const
+{
+ const SchemaType::Ptr type = m_schema->type(name);
+ if (type)
+ return type;
+
+ return m_context->schemaTypeFactory()->createSchemaType(name);
+}
+
+void XsdValidatingInstanceReader::addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding)
+{
+ if (!m_model->idIdRefBindings(id).isEmpty()) {
+ error(QtXmlPatterns::tr("ID value '%1' is not unique").arg(formatKeyword(id)));
+ return;
+ }
+
+ m_model->addIdIdRefBinding(id, binding);
+}
+
+QString XsdValidatingInstanceReader::qNameAttribute(const QXmlName &attributeName)
+{
+ const QString value = attribute(attributeName).simplified();
+ if (!XPathHelper::isQName(value)) {
+ error(QtXmlPatterns::tr("'%1' attribute contains invalid QName content: %2").arg(m_namePool->displayName(attributeName)).arg(formatData(value)));
+ return QString();
+ } else {
+ return value;
+ }
+}
+
+XsdComplexType::Ptr XsdValidatingInstanceReader::anyType()
+{
+ if (m_anyType)
+ return m_anyType;
+
+ const XsdWildcard::Ptr wildcard(new XsdWildcard());
+ wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any);
+ wildcard->setProcessContents(XsdWildcard::Lax);
+
+ const XsdParticle::Ptr outerParticle(new XsdParticle());
+ outerParticle->setMinimumOccurs(1);
+ outerParticle->setMaximumOccurs(1);
+
+ const XsdParticle::Ptr innerParticle(new XsdParticle());
+ innerParticle->setMinimumOccurs(0);
+ innerParticle->setMaximumOccursUnbounded(true);
+ innerParticle->setTerm(wildcard);
+
+ const XsdModelGroup::Ptr outerModelGroup(new XsdModelGroup());
+ outerModelGroup->setCompositor(XsdModelGroup::SequenceCompositor);
+ outerModelGroup->setParticles(XsdParticle::List() << innerParticle);
+ outerParticle->setTerm(outerModelGroup);
+
+ m_anyType = XsdComplexType::Ptr(new XsdComplexType());
+ m_anyType->setName(BuiltinTypes::xsAnyType->name(m_namePool));
+ m_anyType->setDerivationMethod(XsdComplexType::DerivationRestriction);
+ m_anyType->contentType()->setVariety(XsdComplexType::ContentType::Mixed);
+ m_anyType->contentType()->setParticle(outerParticle);
+ m_anyType->setAttributeWildcard(wildcard);
+ m_anyType->setIsAbstract(false);
+
+ return m_anyType;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h b/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h
new file mode 100644
index 0000000000..799ab44c28
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdValidatingInstanceReader_H
+#define Patternist_XsdValidatingInstanceReader_H
+
+#include "qxsdidchelper_p.h"
+#include "qxsdinstancereader_p.h"
+#include "qxsdstatemachine_p.h"
+#include "qxsdvalidatedxmlnodemodel_p.h"
+
+#include <QtCore/QStack>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QXmlQuery;
+
+namespace QPatternist
+{
+ /**
+ * @short The validating schema instance reader.
+ *
+ * This class reads in a xml instance document from a QAbstractXmlNodeModel and
+ * validates it against a given xml schema.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdValidatingInstanceReader : public XsdInstanceReader
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdValidatingInstanceReader> Ptr;
+
+ /**
+ * Creates a new validating instance reader that reads the data from
+ * the given @p model.
+ *
+ * @param model The model the data shall be read from.
+ * @param documentUri The uri of the document the model is from.
+ * @param context The context that is used to report errors etc.
+ */
+ XsdValidatingInstanceReader(const XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context);
+
+ /**
+ * Adds a new @p schema to the pool of schemas that shall be used
+ * for validation.
+ * The schema is located at the given @p url.
+ */
+ void addSchema(const XsdSchema::Ptr &schema, const QUrl &url);
+
+ /**
+ * Reads and validates the instance document.
+ */
+ bool read();
+
+ private:
+ /**
+ * Loads a schema with the given @p targetNamespace from the given @p location
+ * and adds it to the pool of schemas that are used for validation.
+ *
+ * This method is used to load schemas defined in the xsi:schemaLocation or
+ * xsi:noNamespaceSchemaLocation attributes in the instance document.
+ */
+ bool loadSchema(const QString &targetNamespace, const QUrl &location);
+
+ /**
+ * Reports an error via the report context.
+ */
+ void error(const QString &msg) const;
+
+ /**
+ * Validates the current element tag of the instance document.
+ *
+ * @param hasStateMachine Used to remember whether this element represents the start tag
+ * of a complex type and therefor pushes a new state machine on the stack.
+ * @param element Used to remember which element has been validated in this step.
+ */
+ bool validate(bool &hasStateMachine, XsdElement::Ptr &element);
+
+ /**
+ * Validates the current tag of the instance document against the given element @p declaration.
+ *
+ * @param declaration The element declaration to validate against.
+ * @param hasStateMachine Used to remember whether this element represents the start tag
+ * of a complex type and therefor pushes a new state machine on the stack.
+ */
+ bool validateElement(const XsdElement::Ptr &declaration, bool &hasStateMachine);
+
+ /**
+ * Validates the current tag of the instance document against the given @p type of the element @p declaration.
+ *
+ * @param declaration The element declaration to validate against.
+ * @param type The type to validate against.
+ * @param isNilled Defines whether the element is nilled by the instance document.
+ * @param hasStateMachine Used to remember whether this element represents the start tag
+ * of a complex type and therefor pushes a new state machine on the stack.
+ *
+ * @note The @p type can differ from the element @p declaration type if the instance document has defined
+ * it via xsi:type attribute.
+ */
+ bool validateElementType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine);
+
+ /**
+ * Validates the current tag of the instance document against the given simple @p type of the element @p declaration.
+ *
+ * @param declaration The element declaration to validate against.
+ * @param type The type to validate against.
+ * @param isNilled Defines whether the element is nilled by the instance document.
+ *
+ * @note The @p type can differ from the element @p declaration type if the instance document has defined
+ * it via xsi:type attribute.
+ */
+ bool validateElementSimpleType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled);
+
+ /**
+ * Validates the current tag of the instance document against the given complex @p type of the element @p declaration.
+ *
+ * @param declaration The element declaration to validate against.
+ * @param type The type to validate against.
+ * @param isNilled Defines whether the element is nilled by the instance document.
+ * @param hasStateMachine Used to remember whether this element represents the start tag
+ * of a complex type and therefor pushes a new state machine on the stack.
+ *
+ * @note The @p type can differ from the element @p declaration type if the instance document has defined
+ * it via xsi:type attribute.
+ */
+ bool validateElementComplexType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine);
+
+ /**
+ * Validates the given @p value against the attribute use @p declaration.
+ */
+ bool validateAttribute(const XsdAttributeUse::Ptr &declaration, const QString &value);
+
+ /**
+ * Validates the given @p value against the attribute @p declaration.
+ */
+ bool validateAttribute(const XsdAttribute::Ptr &declaration, const QString &value);
+
+ /**
+ * Validates the given @p attributeName against the @p wildcard.
+ */
+ bool validateAttributeWildcard(const QXmlName &attributeName, const XsdWildcard::Ptr &wildcard);
+
+ /**
+ * Validates the identity constraints of an @p element.
+ */
+ bool validateIdentityConstraint(const XsdElement::Ptr &element, const QXmlItem &currentItem);
+
+ /**
+ * Validates the <em>unique</em> identity @p constraint of the @p element.
+ */
+ bool validateUniqueIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet);
+
+ /**
+ * Validates the <em>key</em> identity @p constraint of the @p element.
+ */
+ bool validateKeyIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &targetNodeSet, const TargetNode::Set &qualifiedNodeSet);
+
+ /**
+ * Validates the <em>keyref</em> identity @p constraint of the @p element.
+ */
+ bool validateKeyRefIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet);
+
+ /**
+ * Selects two sets of nodes that match the given identity @p constraint.
+ *
+ * @param element The element the identity constraint belongs to.
+ * @param currentItem The current element that will be used as focus for the XQuery.
+ * @param constraint The constraint (selector and fields) that describe the two sets.
+ * @param targetNodeSet The target node set as defined by the schema specification.
+ * @param qualifiedNodeSet The qualified node set as defined by the schema specification.
+ */
+ bool selectNodeSets(const XsdElement::Ptr &element, const QXmlItem &currentItem, const XsdIdentityConstraint::Ptr &constraint, TargetNode::Set &targetNodeSet, TargetNode::Set &qualifiedNodeSet);
+
+ /**
+ * Creates an QXmlQuery object with the defined @p namespaceBindings that has the @p contextNode as focus
+ * and will execute @p query.
+ */
+ QXmlQuery createXQuery(const QList<QXmlName> &namespaceBindings, const QXmlItem &contextNode, const QString &query) const;
+
+ /**
+ * Returns the element declaration with the given @p name from the pool of all schemas.
+ */
+ XsdElement::Ptr elementByName(const QXmlName &name) const;
+
+ /**
+ * Returns the attribute declaration with the given @p name from the pool of all schemas.
+ */
+ XsdAttribute::Ptr attributeByName(const QXmlName &name) const;
+
+ /**
+ * Returns the type declaration with the given @p name from the pool of all schemas.
+ */
+ SchemaType::Ptr typeByName(const QXmlName &name) const;
+
+ /**
+ * Adds the ID/IDREF binding to the validated model and checks for duplicates.
+ */
+ void addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding);
+
+ /**
+ * Helper method that reads an attribute of type xs:QName and does
+ * syntax checking.
+ */
+ QString qNameAttribute(const QXmlName &attributeName);
+
+ /**
+ * Returns the xs:anyType that is used to build up the state machine.
+ * We need that as the BuiltinTypes::xsAnyType is not a XsdComplexType.
+ */
+ XsdComplexType::Ptr anyType();
+
+ /**
+ * Helper method that creates a state machine for the given @p particle
+ * and pushes it on the state machine stack.
+ */
+ void createAndPushStateMachine(const XsdParticle::Ptr &particle);
+
+ typedef QHash<QUrl, QStringList> MergedSchemas;
+ typedef QHashIterator<QUrl, QStringList> MergedSchemasIterator;
+
+ XsdValidatedXmlNodeModel::Ptr m_model;
+ MergedSchemas m_mergedSchemas;
+ XsdSchema::Ptr m_schema;
+ const NamePool::Ptr m_namePool;
+ const QXmlName m_xsiNilName;
+ const QXmlName m_xsiTypeName;
+ const QXmlName m_xsiSchemaLocationName;
+ const QXmlName m_xsiNoNamespaceSchemaLocationName;
+
+ QStack<XsdStateMachine<XsdTerm::Ptr> > m_stateMachines;
+ QUrl m_documentUri;
+ XsdComplexType::Ptr m_anyType;
+ QSet<QString> m_processedNamespaces;
+ QSet<QString> m_processedSchemaLocations;
+ QSet<QString> m_idRefs;
+ QHash<QXmlName, TargetNode::Set> m_idcKeys;
+ SchemaType::Ptr m_idRefsType;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdwildcard.cpp b/src/xmlpatterns/schema/qxsdwildcard.cpp
new file mode 100644
index 0000000000..6efb99635a
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdwildcard.cpp
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdwildcard_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+QString XsdWildcard::absentNamespace()
+{
+ return QLatin1String("__ns_absent");
+}
+
+void XsdWildcard::NamespaceConstraint::setVariety(Variety variety)
+{
+ m_variety = variety;
+}
+
+XsdWildcard::NamespaceConstraint::Variety XsdWildcard::NamespaceConstraint::variety() const
+{
+ return m_variety;
+}
+
+void XsdWildcard::NamespaceConstraint::setNamespaces(const QSet<QString> &namespaces)
+{
+ m_namespaces = namespaces;
+}
+
+QSet<QString> XsdWildcard::NamespaceConstraint::namespaces() const
+{
+ return m_namespaces;
+}
+
+void XsdWildcard::NamespaceConstraint::setDisallowedNames(const QSet<QString> &names)
+{
+ m_disallowedNames = names;
+}
+
+QSet<QString> XsdWildcard::NamespaceConstraint::disallowedNames() const
+{
+ return m_disallowedNames;
+}
+
+XsdWildcard::XsdWildcard()
+ : m_namespaceConstraint(new NamespaceConstraint())
+ , m_processContents(Strict)
+{
+ m_namespaceConstraint->setVariety(NamespaceConstraint::Any);
+}
+
+bool XsdWildcard::isWildcard() const
+{
+ return true;
+}
+
+void XsdWildcard::setNamespaceConstraint(const NamespaceConstraint::Ptr &namespaceConstraint)
+{
+ m_namespaceConstraint = namespaceConstraint;
+}
+
+XsdWildcard::NamespaceConstraint::Ptr XsdWildcard::namespaceConstraint() const
+{
+ return m_namespaceConstraint;
+}
+
+void XsdWildcard::setProcessContents(ProcessContents contents)
+{
+ m_processContents = contents;
+}
+
+XsdWildcard::ProcessContents XsdWildcard::processContents() const
+{
+ return m_processContents;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdwildcard_p.h b/src/xmlpatterns/schema/qxsdwildcard_p.h
new file mode 100644
index 0000000000..8fbecb322f
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdwildcard_p.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdWildcard_H
+#define Patternist_XsdWildcard_H
+
+#include "qxsdterm_p.h"
+
+#include <QtCore/QSet>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD wildcard object.
+ *
+ * This class represents the <em>wildcard</em> object of a XML schema as described
+ * <a href="http://www.w3.org/TR/xmlschema11-1/#Wildcards">here</a>.
+ *
+ * It contains information from either an <em>any</em> object or an <em>anyAttribute</em> object.
+ *
+ * @see <a href="http://www.w3.org/Submission/2004/SUBM-xmlschema-api-20040309/xml-schema-api.html#Interface-XSWildcard">XML Schema API reference</a>
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ */
+ class XsdWildcard : public XsdTerm
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdWildcard> Ptr;
+
+ /**
+ * Defines the absent namespace that is used in wildcards.
+ */
+ static QString absentNamespace();
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#w-namespace_constraint">namespace constraint</a> of the wildcard.
+ */
+ class NamespaceConstraint : public QSharedData
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<NamespaceConstraint> Ptr;
+
+ /**
+ * Describes the variety of the namespace constraint.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#nc-variety">Variety Definition</a>
+ */
+ enum Variety
+ {
+ Any, ///< Any namespace is allowed.
+ Enumeration, ///< Namespaces in the namespaces set are allowed.
+ Not ///< Namespaces in the namespaces set are not allowed.
+ };
+
+ /**
+ * Sets the @p variety of the namespace constraint.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#nc-variety">Variety Definition</a>
+ */
+ void setVariety(Variety variety);
+
+ /**
+ * Returns the variety of the namespace constraint.
+ */
+ Variety variety() const;
+
+ /**
+ * Sets the set of @p namespaces of the namespace constraint.
+ */
+ void setNamespaces(const QSet<QString> &namespaces);
+
+ /**
+ * Returns the set of namespaces of the namespace constraint.
+ */
+ QSet<QString> namespaces() const;
+
+ /**
+ * Sets the set of disallowed @p names of the namespace constraint.
+ */
+ void setDisallowedNames(const QSet<QString> &names);
+
+ /**
+ * Returns the set of disallowed names of the namespace constraint.
+ */
+ QSet<QString> disallowedNames() const;
+
+ private:
+ Variety m_variety;
+ QSet<QString> m_namespaces;
+ QSet<QString> m_disallowedNames;
+ };
+
+ /**
+ * Describes the <a href="http://www.w3.org/TR/xmlschema11-1/#w-process_contents">type of content processing</a> of the wildcard.
+ */
+ enum ProcessContents
+ {
+ Strict, ///< There must be a top-level declaration for the item available, or the item must have an xsi:type, and the item must be valid as appropriate.
+ Lax, ///< If the item has a uniquely determined declaration available, it must be valid with respect to that definition.
+ Skip ///< No constraints at all: the item must simply be well-formed XML.
+ };
+
+ /**
+ * Creates a new wildcard object.
+ */
+ XsdWildcard();
+
+ /**
+ * Returns always @c true, used to avoid dynamic casts.
+ */
+ virtual bool isWildcard() const;
+
+ /**
+ * Sets the namespace @p constraint of the wildcard.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#w-namespace_constraint">Namespace Constraint Definition</a>
+ */
+ void setNamespaceConstraint(const NamespaceConstraint::Ptr &constraint);
+
+ /**
+ * Returns the namespace constraint of the wildcard.
+ */
+ NamespaceConstraint::Ptr namespaceConstraint() const;
+
+ /**
+ * Sets the process @p contents of the wildcard.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#w-process_contents">Process Contents Definition</a>
+ */
+ void setProcessContents(ProcessContents contents);
+
+ /**
+ * Returns the process contents of the wildcard.
+ */
+ ProcessContents processContents() const;
+
+ private:
+ NamespaceConstraint::Ptr m_namespaceConstraint;
+ ProcessContents m_processContents;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/qxsdxpathexpression.cpp b/src/xmlpatterns/schema/qxsdxpathexpression.cpp
new file mode 100644
index 0000000000..ba9d0a4941
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdxpathexpression.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qxsdxpathexpression_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QPatternist;
+
+void XsdXPathExpression::setNamespaceBindings(const QList<QXmlName> &set)
+{
+ m_namespaceBindings = set;
+}
+
+QList<QXmlName> XsdXPathExpression::namespaceBindings() const
+{
+ return m_namespaceBindings;
+}
+
+void XsdXPathExpression::setDefaultNamespace(const AnyURI::Ptr &defaultNs)
+{
+ m_defaultNamespace = defaultNs;
+}
+
+AnyURI::Ptr XsdXPathExpression::defaultNamespace() const
+{
+ return m_defaultNamespace;
+}
+
+void XsdXPathExpression::setBaseURI(const AnyURI::Ptr &uri)
+{
+ m_baseURI = uri;
+}
+
+AnyURI::Ptr XsdXPathExpression::baseURI() const
+{
+ return m_baseURI;
+}
+
+void XsdXPathExpression::setExpression(const QString &expression)
+{
+ m_expression = expression;
+}
+
+QString XsdXPathExpression::expression() const
+{
+ return m_expression;
+}
+
+QT_END_NAMESPACE
diff --git a/src/xmlpatterns/schema/qxsdxpathexpression_p.h b/src/xmlpatterns/schema/qxsdxpathexpression_p.h
new file mode 100644
index 0000000000..e57f7b7f83
--- /dev/null
+++ b/src/xmlpatterns/schema/qxsdxpathexpression_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+
+#ifndef Patternist_XsdXPathExpression_H
+#define Patternist_XsdXPathExpression_H
+
+#include "qanyuri_p.h"
+#include "qnamedschemacomponent_p.h"
+#include "qxsdannotated_p.h"
+
+#include <QtCore/QList>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QPatternist
+{
+ /**
+ * @short Represents a XSD assertion object.
+ *
+ * @ingroup Patternist_schema
+ * @author Tobias Koenig <tobias.koenig@trolltech.com>
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#x">XPathExpression Definition</a>
+ */
+ class XsdXPathExpression : public NamedSchemaComponent, public XsdAnnotated
+ {
+ public:
+ typedef QExplicitlySharedDataPointer<XsdXPathExpression> Ptr;
+ typedef QList<XsdXPathExpression::Ptr> List;
+
+ /**
+ * Sets the list of namespace @p bindings of the XPath expression.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#x-namespace_bindings">Namespace Bindings Definition</a>
+ *
+ * @note We can't use a QSet<QXmlName> here, as the hash method does not take the prefix
+ * in account, so we loose entries.
+ */
+ void setNamespaceBindings(const QList<QXmlName> &bindings);
+
+ /**
+ * Returns the list of namespace bindings of the XPath expression.
+ */
+ QList<QXmlName> namespaceBindings() const;
+
+ /**
+ * Sets the default namespace of the XPath expression.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#x-default_namespace">Default Namespace Definition</a>
+ */
+ void setDefaultNamespace(const AnyURI::Ptr &defaultNamespace);
+
+ /**
+ * Returns the default namespace of the XPath expression.
+ */
+ AnyURI::Ptr defaultNamespace() const;
+
+ /**
+ * Sets the base @p uri of the XPath expression.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#x-base_URI">Base URI Definition</a>
+ */
+ void setBaseURI(const AnyURI::Ptr &uri);
+
+ /**
+ * Returns the base uri of the XPath expression.
+ */
+ AnyURI::Ptr baseURI() const;
+
+ /**
+ * Sets the @p expression string of the XPath expression.
+ *
+ * @see <a href="http://www.w3.org/TR/xmlschema11-1/#x-expression">Expression Definition</a>
+ */
+ void setExpression(const QString &expression);
+
+ /**
+ * Returns the expression string of the XPath expression.
+ */
+ QString expression() const;
+
+ private:
+ QList<QXmlName> m_namespaceBindings;
+ AnyURI::Ptr m_defaultNamespace;
+ AnyURI::Ptr m_baseURI;
+ QString m_expression;
+ };
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/xmlpatterns/schema/schema.pri b/src/xmlpatterns/schema/schema.pri
new file mode 100644
index 0000000000..b00d64b2c7
--- /dev/null
+++ b/src/xmlpatterns/schema/schema.pri
@@ -0,0 +1,93 @@
+HEADERS += $$PWD/qnamespacesupport_p.h \
+ $$PWD/qxsdalternative_p.h \
+ $$PWD/qxsdannotated_p.h \
+ $$PWD/qxsdannotation_p.h \
+ $$PWD/qxsdapplicationinformation_p.h \
+ $$PWD/qxsdassertion_p.h \
+ $$PWD/qxsdattribute_p.h \
+ $$PWD/qxsdattributereference_p.h \
+ $$PWD/qxsdattributeterm_p.h \
+ $$PWD/qxsdattributeuse_p.h \
+ $$PWD/qxsdattributegroup_p.h \
+ $$PWD/qxsdcomplextype_p.h \
+ $$PWD/qxsddocumentation_p.h \
+ $$PWD/qxsdelement_p.h \
+ $$PWD/qxsdfacet_p.h \
+ $$PWD/qxsdidcache_p.h \
+ $$PWD/qxsdidchelper_p.h \
+ $$PWD/qxsdidentityconstraint_p.h \
+ $$PWD/qxsdinstancereader_p.h \
+ $$PWD/qxsdmodelgroup_p.h \
+ $$PWD/qxsdnotation_p.h \
+ $$PWD/qxsdparticle_p.h \
+ $$PWD/qxsdparticlechecker_p.h \
+ $$PWD/qxsdreference_p.h \
+ $$PWD/qxsdsimpletype_p.h \
+ $$PWD/qxsdschema_p.h \
+ $$PWD/qxsdschemachecker_p.h \
+ $$PWD/qxsdschemacontext_p.h \
+ $$PWD/qxsdschemadebugger_p.h \
+ $$PWD/qxsdschemahelper_p.h \
+ $$PWD/qxsdschemamerger_p.h \
+ $$PWD/qxsdschemaparser_p.h \
+ $$PWD/qxsdschemaparsercontext_p.h \
+ $$PWD/qxsdschemaresolver_p.h \
+ $$PWD/qxsdschematoken_p.h \
+ $$PWD/qxsdschematypesfactory_p.h \
+ $$PWD/qxsdstatemachine_p.h \
+ $$PWD/qxsdstatemachinebuilder_p.h \
+ $$PWD/qxsdterm_p.h \
+ $$PWD/qxsdtypechecker_p.h \
+ $$PWD/qxsduserschematype_p.h \
+ $$PWD/qxsdvalidatedxmlnodemodel_p.h \
+ $$PWD/qxsdvalidatinginstancereader_p.h \
+ $$PWD/qxsdwildcard_p.h \
+ $$PWD/qxsdxpathexpression_p.h
+
+SOURCES += $$PWD/qnamespacesupport.cpp \
+ $$PWD/qxsdalternative.cpp \
+ $$PWD/qxsdannotated.cpp \
+ $$PWD/qxsdannotation.cpp \
+ $$PWD/qxsdapplicationinformation.cpp \
+ $$PWD/qxsdassertion.cpp \
+ $$PWD/qxsdattribute.cpp \
+ $$PWD/qxsdattributereference.cpp \
+ $$PWD/qxsdattributeterm.cpp \
+ $$PWD/qxsdattributeuse.cpp \
+ $$PWD/qxsdattributegroup.cpp \
+ $$PWD/qxsdcomplextype.cpp \
+ $$PWD/qxsddocumentation.cpp \
+ $$PWD/qxsdelement.cpp \
+ $$PWD/qxsdfacet.cpp \
+ $$PWD/qxsdidcache.cpp \
+ $$PWD/qxsdidchelper.cpp \
+ $$PWD/qxsdidentityconstraint.cpp \
+ $$PWD/qxsdinstancereader.cpp \
+ $$PWD/qxsdmodelgroup.cpp \
+ $$PWD/qxsdnotation.cpp \
+ $$PWD/qxsdparticle.cpp \
+ $$PWD/qxsdparticlechecker.cpp \
+ $$PWD/qxsdreference.cpp \
+ $$PWD/qxsdsimpletype.cpp \
+ $$PWD/qxsdschema.cpp \
+ $$PWD/qxsdschemachecker.cpp \
+ $$PWD/qxsdschemachecker_setup.cpp \
+ $$PWD/qxsdschemacontext.cpp \
+ $$PWD/qxsdschemadebugger.cpp \
+ $$PWD/qxsdschemahelper.cpp \
+ $$PWD/qxsdschemamerger.cpp \
+ $$PWD/qxsdschemaparser.cpp \
+ $$PWD/qxsdschemaparser_setup.cpp \
+ $$PWD/qxsdschemaparsercontext.cpp \
+ $$PWD/qxsdschemaresolver.cpp \
+ $$PWD/qxsdschematoken.cpp \
+ $$PWD/qxsdschematypesfactory.cpp \
+ $$PWD/qxsdstatemachinebuilder.cpp \
+ $$PWD/qxsdterm.cpp \
+ $$PWD/qxsdtypechecker.cpp \
+ $$PWD/qxsdwildcard.cpp \
+ $$PWD/qxsdvalidatedxmlnodemodel.cpp \
+ $$PWD/qxsdvalidatinginstancereader.cpp \
+ $$PWD/qxsdxpathexpression.cpp
+
+RESOURCES += $$PWD/builtinschemas.qrc
diff --git a/src/xmlpatterns/schema/schemas/xml.xsd b/src/xmlpatterns/schema/schemas/xml.xsd
new file mode 100644
index 0000000000..eeb9db5609
--- /dev/null
+++ b/src/xmlpatterns/schema/schemas/xml.xsd
@@ -0,0 +1,145 @@
+<?xml version='1.0'?>
+<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:xs="http://www.w3.org/2001/XMLSchema" xml:lang="en">
+
+ <xs:annotation>
+ <xs:documentation>
+ See http://www.w3.org/XML/1998/namespace.html and
+ http://www.w3.org/TR/REC-xml for information about this namespace.
+
+ This schema document describes the XML namespace, in a form
+ suitable for import by other schema documents.
+
+ Note that local names in this namespace are intended to be defined
+ only by the World Wide Web Consortium or its subgroups. The
+ following names are currently defined in this namespace and should
+ not be used with conflicting semantics by any Working Group,
+ specification, or document instance:
+
+ base (as an attribute name): denotes an attribute whose value
+ provides a URI to be used as the base for interpreting any
+ relative URIs in the scope of the element on which it
+ appears; its value is inherited. This name is reserved
+ by virtue of its definition in the XML Base specification.
+
+ id (as an attribute name): denotes an attribute whose value
+ should be interpreted as if declared to be of type ID.
+ This name is reserved by virtue of its definition in the
+ xml:id specification.
+
+ lang (as an attribute name): denotes an attribute whose value
+ is a language code for the natural language of the content of
+ any element; its value is inherited. This name is reserved
+ by virtue of its definition in the XML specification.
+
+ space (as an attribute name): denotes an attribute whose
+ value is a keyword indicating what whitespace processing
+ discipline is intended for the content of the element; its
+ value is inherited. This name is reserved by virtue of its
+ definition in the XML specification.
+
+ Father (in any context at all): denotes Jon Bosak, the chair of
+ the original XML Working Group. This name is reserved by
+ the following decision of the W3C XML Plenary and
+ XML Coordination groups:
+
+ In appreciation for his vision, leadership and dedication
+ the W3C XML Plenary on this 10th day of February, 2000
+ reserves for Jon Bosak in perpetuity the XML name
+ xml:Father
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>This schema defines attributes and an attribute group
+ suitable for use by
+ schemas wishing to allow xml:base, xml:lang, xml:space or xml:id
+ attributes on elements they define.
+
+ To enable this, such a schema must import this schema
+ for the XML namespace, e.g. as follows:
+ &lt;schema . . .>
+ . . .
+ &lt;import namespace="http://www.w3.org/XML/1998/namespace"
+ schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+ Subsequently, qualified reference to any of the attributes
+ or the group defined below will have the desired effect, e.g.
+
+ &lt;type . . .>
+ . . .
+ &lt;attributeGroup ref="xml:specialAttrs"/>
+
+ will define a type which will schema-validate an instance
+ element with any of those attributes</xs:documentation>
+ </xs:annotation>
+
+ <xs:annotation>
+ <xs:documentation>In keeping with the XML Schema WG's standard versioning
+ policy, this schema document will persist at
+ http://www.w3.org/2007/08/xml.xsd.
+ At the date of issue it can also be found at
+ http://www.w3.org/2001/xml.xsd.
+ The schema document at that URI may however change in the future,
+ in order to remain compatible with the latest version of XML Schema
+ itself, or with the XML namespace itself. In other words, if the XML
+ Schema or XML namespaces change, the version of this document at
+ http://www.w3.org/2001/xml.xsd will change
+ accordingly; the version at
+ http://www.w3.org/2007/08/xml.xsd will not change.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:attribute name="lang">
+ <xs:annotation>
+ <xs:documentation>Attempting to install the relevant ISO 2- and 3-letter
+ codes as the enumerated possible values is probably never
+ going to be a realistic possibility. See
+ RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry
+ at http://www.iana.org/assignments/lang-tag-apps.htm for
+ further information.
+
+ The union allows for the 'un-declaration' of xml:lang with
+ the empty string.</xs:documentation>
+ </xs:annotation>
+ <xs:simpleType>
+ <xs:union memberTypes="xs:language">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value=""/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:union>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="space">
+ <xs:simpleType>
+ <xs:restriction base="xs:NCName">
+ <xs:enumeration value="default"/>
+ <xs:enumeration value="preserve"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+
+ <xs:attribute name="base" type="xs:anyURI">
+ <xs:annotation>
+ <xs:documentation>See http://www.w3.org/TR/xmlbase/ for
+ information about this attribute.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ <xs:attribute name="id" type="xs:ID">
+ <xs:annotation>
+ <xs:documentation>See http://www.w3.org/TR/xml-id/ for
+ information about this attribute.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ <xs:attributeGroup name="specialAttrs">
+ <xs:attribute ref="xml:base"/>
+ <xs:attribute ref="xml:lang"/>
+ <xs:attribute ref="xml:space"/>
+ <xs:attribute ref="xml:id"/>
+ </xs:attributeGroup>
+
+</xs:schema>
diff --git a/src/xmlpatterns/schema/tokens.xml b/src/xmlpatterns/schema/tokens.xml
new file mode 100644
index 0000000000..7ec97525a3
--- /dev/null
+++ b/src/xmlpatterns/schema/tokens.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<tokenAutomaton scope="public"
+ className="XsdSchemaToken"
+ headerFile="qxsdschematoken_p.h"
+ sourceFile="qxsdschematoken.cpp"
+ defaultToken="NoKeyword"
+ tokenEnum="NodeName"
+ hasToString="true"
+ includeGuardName="QPatternist_XsdSchemaToken_h">
+ <tokens>
+ <token>abstract</token>
+ <token>all</token>
+ <token>alternative</token>
+ <token>annotation</token>
+ <token>any</token>
+ <token>anyAttribute</token>
+ <token>appinfo</token>
+ <token>appliesToEmpty</token>
+ <token>assert</token>
+ <token>assertion</token>
+ <token>attribute</token>
+ <token>attributeFormDefault</token>
+ <token>attributeGroup</token>
+ <token>base</token>
+ <token>block</token>
+ <token>blockDefault</token>
+ <token>choice</token>
+ <token>collapse</token>
+ <token>complexContent</token>
+ <token>complexType</token>
+ <token>default</token>
+ <token>defaultAttributes</token>
+ <token>defaultAttributesApply</token>
+ <token>defaultOpenContent</token>
+ <token>documentation</token>
+ <token>element</token>
+ <token>elementFormDefault</token>
+ <token>enumeration</token>
+ <token>extension</token>
+ <token>field</token>
+ <token>final</token>
+ <token>finalDefault</token>
+ <token>fixed</token>
+ <token>form</token>
+ <token>fractionDigits</token>
+ <token>group</token>
+ <token>id</token>
+ <token>import</token>
+ <token>include</token>
+ <token>itemType</token>
+ <token>key</token>
+ <token>keyref</token>
+ <token>length</token>
+ <token>list</token>
+ <token>maxExclusive</token>
+ <token>maxInclusive</token>
+ <token>maxLength</token>
+ <token>maxOccurs</token>
+ <token>memberTypes</token>
+ <token>minExclusive</token>
+ <token>minInclusive</token>
+ <token>minLength</token>
+ <token>minOccurs</token>
+ <token>mixed</token>
+ <token>mode</token>
+ <token>name</token>
+ <token>namespace</token>
+ <token>nillable</token>
+ <token>notation</token>
+ <token>notNamespace</token>
+ <token>notQName</token>
+ <token>openContent</token>
+ <token>override</token>
+ <token>preserve</token>
+ <token>pattern</token>
+ <token>processContents</token>
+ <token>public</token>
+ <token>redefine</token>
+ <token>ref</token>
+ <token>refer</token>
+ <token>replace</token>
+ <token>restriction</token>
+ <token>schema</token>
+ <token>schemaLocation</token>
+ <token>selector</token>
+ <token>sequence</token>
+ <token>simpleContent</token>
+ <token>simpleType</token>
+ <token>source</token>
+ <token>substitutionGroup</token>
+ <token>system</token>
+ <token>targetNamespace</token>
+ <token>test</token>
+ <token>totalDigits</token>
+ <token>type</token>
+ <token>union</token>
+ <token>unique</token>
+ <token>use</token>
+ <token>value</token>
+ <token>version</token>
+ <token>whiteSpace</token>
+ <token>xpath</token>
+ <token name="XPathDefaultNamespace">xpathDefaultNamespace</token>
+ <token name="XmlLanguage">xml:lang</token>
+ <token name="XML_NS_SCHEMA_URI">http://www.w3.org/2001/XMLSchema</token>
+ </tokens>
+
+ <boilerplate>
+
+ <prolog>/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+</prolog>
+
+ </boilerplate>
+
+</tokenAutomaton>