summaryrefslogtreecommitdiffstats
path: root/dist/changes-1.39-19980611
diff options
context:
space:
mode:
authorNorwegian Rock Cat <qt-info@nokia.com>2009-07-08 15:21:51 (GMT)
committerNorwegian Rock Cat <qt-info@nokia.com>2009-07-09 17:01:26 (GMT)
commit5c11a5a38bcc68c17da8fe59e8db03d43ea55ac1 (patch)
tree3b87cc860a08393c42aaf6d0adde692d2da3ce4b /dist/changes-1.39-19980611
parent020ed5b7caaba5cf877cdb9ebaa575db1d15b7f0 (diff)
downloadQt-5c11a5a38bcc68c17da8fe59e8db03d43ea55ac1.zip
Qt-5c11a5a38bcc68c17da8fe59e8db03d43ea55ac1.tar.gz
Qt-5c11a5a38bcc68c17da8fe59e8db03d43ea55ac1.tar.bz2
Ensure that when we hide QToolBar in unified, unified follows.
Basically if you would hide a toolbar in the unified toolbar, you would still see a little bit of area at the top instead of having everything flush with the titlebar. This change basically unsures that the unified toolbar makes a decision to hide itself if all the toolbars inside it are hidden. It makes the behavior of clicking on the toolbar button behave more or less correctly since we are going to show the unified toolbar whether we want to or not. This all will get the toolbar button switch event to be dispatched in Cocoa as well. Also add an optimization for checking if we need to change the geometry. If we don't have any items the other toolbar areas, we can skip the set geometry call, which wrecks havoc with things in Cocoa. We still don't solve the case of someone who has hidden the items with the toolbar button then goes full-screen, then goes back out. I'm not motivated to solve it as is because we need to keep track of the hides we do on the button press vs. other hides from the user and still people can workaround it easy enough by handling window state change and doing what is recommended in the docs. Task-number: 208439 Rev-by: Denis
Diffstat (limited to 'dist/changes-1.39-19980611')
0 files changed, 0 insertions, 0 deletions
src/xmlpatterns/schema/qxsdattributeterm_p.h | 66 + src/xmlpatterns/schema/qxsdattributeuse.cpp | 106 + src/xmlpatterns/schema/qxsdattributeuse_p.h | 194 + src/xmlpatterns/schema/qxsdcomplextype.cpp | 201 + src/xmlpatterns/schema/qxsdcomplextype_p.h | 374 ++ src/xmlpatterns/schema/qxsddocumentation.cpp | 56 + src/xmlpatterns/schema/qxsddocumentation_p.h | 107 + src/xmlpatterns/schema/qxsdelement.cpp | 214 + src/xmlpatterns/schema/qxsdelement_p.h | 373 ++ src/xmlpatterns/schema/qxsdfacet.cpp | 94 + src/xmlpatterns/schema/qxsdfacet_p.h | 183 + src/xmlpatterns/schema/qxsdidcache.cpp | 36 + src/xmlpatterns/schema/qxsdidcache_p.h | 69 + src/xmlpatterns/schema/qxsdidchelper.cpp | 107 + src/xmlpatterns/schema/qxsdidchelper_p.h | 156 + src/xmlpatterns/schema/qxsdidentityconstraint.cpp | 63 + src/xmlpatterns/schema/qxsdidentityconstraint_p.h | 143 + src/xmlpatterns/schema/qxsdinstancereader.cpp | 166 + src/xmlpatterns/schema/qxsdinstancereader_p.h | 159 + src/xmlpatterns/schema/qxsdmodelgroup.cpp | 48 + src/xmlpatterns/schema/qxsdmodelgroup_p.h | 109 + src/xmlpatterns/schema/qxsdnotation.cpp | 38 + src/xmlpatterns/schema/qxsdnotation_p.h | 89 + src/xmlpatterns/schema/qxsdparticle.cpp | 65 + src/xmlpatterns/schema/qxsdparticle_p.h | 124 + src/xmlpatterns/schema/qxsdparticlechecker.cpp | 510 ++ src/xmlpatterns/schema/qxsdparticlechecker_p.h | 69 + src/xmlpatterns/schema/qxsdreference.cpp | 53 + src/xmlpatterns/schema/qxsdreference_p.h | 115 + src/xmlpatterns/schema/qxsdschema.cpp | 242 + src/xmlpatterns/schema/qxsdschema_p.h | 271 + src/xmlpatterns/schema/qxsdschemachecker.cpp | 2031 +++++++ .../schema/qxsdschemachecker_helper.cpp | 276 + src/xmlpatterns/schema/qxsdschemachecker_p.h | 254 + src/xmlpatterns/schema/qxsdschemachecker_setup.cpp | 287 + src/xmlpatterns/schema/qxsdschemacontext.cpp | 498 ++ src/xmlpatterns/schema/qxsdschemacontext_p.h | 157 + src/xmlpatterns/schema/qxsdschemadebugger.cpp | 196 + src/xmlpatterns/schema/qxsdschemadebugger_p.h | 97 + src/xmlpatterns/schema/qxsdschemahelper.cpp | 791 +++ src/xmlpatterns/schema/qxsdschemahelper_p.h | 156 + src/xmlpatterns/schema/qxsdschemamerger.cpp | 127 + src/xmlpatterns/schema/qxsdschemamerger_p.h | 69 + src/xmlpatterns/schema/qxsdschemaparser.cpp | 6012 ++++++++++++++++++++ src/xmlpatterns/schema/qxsdschemaparser_p.h | 691 +++ src/xmlpatterns/schema/qxsdschemaparser_setup.cpp | 1070 ++++ src/xmlpatterns/schema/qxsdschemaparsercontext.cpp | 573 ++ src/xmlpatterns/schema/qxsdschemaparsercontext_p.h | 201 + src/xmlpatterns/schema/qxsdschemaresolver.cpp | 1706 ++++++ src/xmlpatterns/schema/qxsdschemaresolver_p.h | 548 ++ src/xmlpatterns/schema/qxsdschematoken.cpp | 2951 ++++++++++ src/xmlpatterns/schema/qxsdschematoken_p.h | 168 + src/xmlpatterns/schema/qxsdschematypesfactory.cpp | 96 + src/xmlpatterns/schema/qxsdschematypesfactory_p.h | 79 + src/xmlpatterns/schema/qxsdsimpletype.cpp | 118 + src/xmlpatterns/schema/qxsdsimpletype_p.h | 189 + src/xmlpatterns/schema/qxsdstatemachine.cpp | 433 ++ src/xmlpatterns/schema/qxsdstatemachine_p.h | 209 + src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp | 230 + src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h | 111 + src/xmlpatterns/schema/qxsdterm.cpp | 38 + src/xmlpatterns/schema/qxsdterm_p.h | 84 + src/xmlpatterns/schema/qxsdtypechecker.cpp | 1308 +++++ src/xmlpatterns/schema/qxsdtypechecker_p.h | 159 + src/xmlpatterns/schema/qxsduserschematype.cpp | 45 + src/xmlpatterns/schema/qxsduserschematype_p.h | 94 + .../schema/qxsdvalidatedxmlnodemodel.cpp | 185 + .../schema/qxsdvalidatedxmlnodemodel_p.h | 149 + .../schema/qxsdvalidatinginstancereader.cpp | 1245 ++++ .../schema/qxsdvalidatinginstancereader_p.h | 266 + src/xmlpatterns/schema/qxsdwildcard.cpp | 85 + src/xmlpatterns/schema/qxsdwildcard_p.h | 169 + src/xmlpatterns/schema/qxsdxpathexpression.cpp | 58 + src/xmlpatterns/schema/qxsdxpathexpression_p.h | 113 + src/xmlpatterns/schema/schema.pri | 93 + src/xmlpatterns/schema/schemas/xml.xsd | 145 + src/xmlpatterns/schema/tokens.xml | 125 + src/xmlpatterns/type/qanysimpletype.cpp | 10 + src/xmlpatterns/type/qanysimpletype_p.h | 12 + src/xmlpatterns/type/qanytype.cpp | 12 +- src/xmlpatterns/type/qanytype_p.h | 10 + src/xmlpatterns/type/qnamedschemacomponent.cpp | 41 + src/xmlpatterns/type/qnamedschemacomponent_p.h | 97 + src/xmlpatterns/type/qprimitives_p.h | 13 + src/xmlpatterns/type/qschematype.cpp | 5 + src/xmlpatterns/type/qschematype_p.h | 30 +- src/xmlpatterns/type/type.pri | 2 + src/xmlpatterns/utils/qpatternistlocale_p.h | 10 + src/xmlpatterns/xmlpatterns.pro | 2 + tests/auto/auto.pro | 5 + .../tst_qabstractxmlnodemodel.cpp | 8 + tests/auto/qxmlquery/tst_qxmlquery.cpp | 158 + tests/auto/qxmlschema/.gitignore | 1 + tests/auto/qxmlschema/qxmlschema.pro | 4 + tests/auto/qxmlschema/tst_qxmlschema.cpp | 231 + tests/auto/qxmlschemavalidator/.gitignore | 1 + .../qxmlschemavalidator/qxmlschemavalidator.pro | 4 + .../tst_qxmlschemavalidator.cpp | 308 + tests/auto/runQtXmlPatternsTests.sh | 2 + tests/auto/xmlpatterns.pri | 14 + .../test/tst_xmlpatternsdiagnosticsts.cpp | 2 +- tests/auto/xmlpatternsschema/.gitignore | 1 + .../xmlpatternsschema/tst_xmlpatternsschema.cpp | 988 ++++ tests/auto/xmlpatternsschema/xmlpatternsschema.pro | 6 + tests/auto/xmlpatternsschemats/.gitignore | 4 + tests/auto/xmlpatternsschemats/Baseline.xml | 2 + .../auto/xmlpatternsschemats/TESTSUITE/.gitignore | 3 + .../xmlpatternsschemats/TESTSUITE/unifyCatalog.xsl | 21 + .../xmlpatternsschemats/TESTSUITE/updateSuite.sh | 20 + .../tst_xmlpatternsschemats.cpp | 44 + .../xmlpatternsschemats/xmlpatternsschemats.pro | 23 + tests/auto/xmlpatternsvalidator/files/instance.xml | 3 + .../xmlpatternsvalidator/files/invalid_schema.xsd | 12 + .../files/other_valid_schema.xsd | 12 + .../files/sa_invalid_instance.xml | 3 + .../files/sa_valid_instance.xml | 3 + .../xmlpatternsvalidator/files/valid_schema.xsd | 12 + .../tst_xmlpatternsvalidator.cpp | 174 + .../xmlpatternsvalidator/xmlpatternsvalidator.pro | 5 + tests/auto/xmlpatternsview/view/MainWindow.cpp | 32 +- tests/auto/xmlpatternsview/view/MainWindow.h | 6 +- tests/auto/xmlpatternsview/view/ui_MainWindow.ui | 9 + tests/auto/xmlpatternsxqts/lib/TestBaseLine.cpp | 7 + tests/auto/xmlpatternsxqts/lib/TestBaseLine.h | 9 +- tests/auto/xmlpatternsxqts/lib/TestGroup.cpp | 6 +- tests/auto/xmlpatternsxqts/lib/TestSuite.cpp | 26 +- tests/auto/xmlpatternsxqts/lib/TestSuite.h | 14 +- tests/auto/xmlpatternsxqts/lib/TreeModel.cpp | 9 +- tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.cpp | 346 ++ tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.h | 130 + .../xmlpatternsxqts/lib/XSDTestSuiteHandler.cpp | 881 +++ .../auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.h | 90 + tests/auto/xmlpatternsxqts/lib/lib.pro | 4 + tests/auto/xmlpatternsxqts/test/tst_suitetest.cpp | 15 +- tests/auto/xmlpatternsxqts/test/tst_suitetest.h | 14 +- .../xmlpatternsxqts/test/tst_xmlpatternsxqts.cpp | 2 +- .../auto/xmlpatternsxslts/tst_xmlpatternsxslts.cpp | 2 +- tools/tools.pro | 2 +- tools/xmlpatternsvalidator/main.cpp | 96 + tools/xmlpatternsvalidator/main.h | 46 + .../xmlpatternsvalidator/xmlpatternsvalidator.pro | 19 + 273 files changed, 39053 insertions(+), 595 deletions(-) create mode 100644 examples/xmlpatterns/schema/main.cpp create mode 100644 examples/xmlpatterns/schema/mainwindow.cpp create mode 100644 examples/xmlpatterns/schema/mainwindow.h create mode 100644 examples/xmlpatterns/schema/schema.pro create mode 100644 examples/xmlpatterns/schema/schema.qrc create mode 100644 examples/xmlpatterns/schema/schema.ui create mode 100644 src/xmlpatterns/api/qabstractxmlpullprovider.cpp create mode 100644 src/xmlpatterns/api/qabstractxmlpullprovider_p.h create mode 100644 src/xmlpatterns/api/qpullbridge.cpp create mode 100644 src/xmlpatterns/api/qpullbridge_p.h create mode 100644 src/xmlpatterns/api/qxmlschema.cpp create mode 100644 src/xmlpatterns/api/qxmlschema.h create mode 100644 src/xmlpatterns/api/qxmlschema_p.cpp create mode 100644 src/xmlpatterns/api/qxmlschema_p.h create mode 100644 src/xmlpatterns/api/qxmlschemavalidator.cpp create mode 100644 src/xmlpatterns/api/qxmlschemavalidator.h create mode 100644 src/xmlpatterns/api/qxmlschemavalidator_p.h create mode 100644 src/xmlpatterns/data/qcomparisonfactory.cpp create mode 100644 src/xmlpatterns/data/qcomparisonfactory_p.h create mode 100644 src/xmlpatterns/data/qvaluefactory.cpp create mode 100644 src/xmlpatterns/data/qvaluefactory_p.h create mode 100644 src/xmlpatterns/schema/.gitignore create mode 100644 src/xmlpatterns/schema/builtinschemas.qrc create mode 100644 src/xmlpatterns/schema/doc/All_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Alternative_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Annotation_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/AnyAttribute_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Any_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Assert_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Choice_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ComplexContentExtension_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ComplexContentRestriction_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ComplexContent_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/DefaultOpenContent_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/EnumerationFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Field_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/FractionDigitsFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/GlobalAttribute_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/GlobalComplexType_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/GlobalElement_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/GlobalSimpleType_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Import_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Include_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/KeyRef_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Key_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LengthFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/List_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalAll_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalAttribute_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalChoice_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalComplexType_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalElement_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalSequence_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalSimpleType_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MaxExclusiveFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MaxInclusiveFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MaxLengthFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MinExclusiveFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MinInclusiveFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MinLengthFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/NamedAttributeGroup_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/NamedGroup_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Notation_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Override_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/PatternFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Redefine_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ReferredAttributeGroup_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ReferredGroup_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Schema_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Selector_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Sequence_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/SimpleContentExtension_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/SimpleContentRestriction_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/SimpleContent_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/SimpleRestriction_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/TotalDigitsFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Union_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Unique_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/WhiteSpaceFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/legend.dot create mode 100644 src/xmlpatterns/schema/qnamespacesupport.cpp create mode 100644 src/xmlpatterns/schema/qnamespacesupport_p.h create mode 100644 src/xmlpatterns/schema/qxsdalternative.cpp create mode 100644 src/xmlpatterns/schema/qxsdalternative_p.h create mode 100644 src/xmlpatterns/schema/qxsdannotated.cpp create mode 100644 src/xmlpatterns/schema/qxsdannotated_p.h create mode 100644 src/xmlpatterns/schema/qxsdannotation.cpp create mode 100644 src/xmlpatterns/schema/qxsdannotation_p.h create mode 100644 src/xmlpatterns/schema/qxsdapplicationinformation.cpp create mode 100644 src/xmlpatterns/schema/qxsdapplicationinformation_p.h create mode 100644 src/xmlpatterns/schema/qxsdassertion.cpp create mode 100644 src/xmlpatterns/schema/qxsdassertion_p.h create mode 100644 src/xmlpatterns/schema/qxsdattribute.cpp create mode 100644 src/xmlpatterns/schema/qxsdattribute_p.h create mode 100644 src/xmlpatterns/schema/qxsdattributegroup.cpp create mode 100644 src/xmlpatterns/schema/qxsdattributegroup_p.h create mode 100644 src/xmlpatterns/schema/qxsdattributereference.cpp create mode 100644 src/xmlpatterns/schema/qxsdattributereference_p.h create mode 100644 src/xmlpatterns/schema/qxsdattributeterm.cpp create mode 100644 src/xmlpatterns/schema/qxsdattributeterm_p.h create mode 100644 src/xmlpatterns/schema/qxsdattributeuse.cpp create mode 100644 src/xmlpatterns/schema/qxsdattributeuse_p.h create mode 100644 src/xmlpatterns/schema/qxsdcomplextype.cpp create mode 100644 src/xmlpatterns/schema/qxsdcomplextype_p.h create mode 100644 src/xmlpatterns/schema/qxsddocumentation.cpp create mode 100644 src/xmlpatterns/schema/qxsddocumentation_p.h create mode 100644 src/xmlpatterns/schema/qxsdelement.cpp create mode 100644 src/xmlpatterns/schema/qxsdelement_p.h create mode 100644 src/xmlpatterns/schema/qxsdfacet.cpp create mode 100644 src/xmlpatterns/schema/qxsdfacet_p.h create mode 100644 src/xmlpatterns/schema/qxsdidcache.cpp create mode 100644 src/xmlpatterns/schema/qxsdidcache_p.h create mode 100644 src/xmlpatterns/schema/qxsdidchelper.cpp create mode 100644 src/xmlpatterns/schema/qxsdidchelper_p.h create mode 100644 src/xmlpatterns/schema/qxsdidentityconstraint.cpp create mode 100644 src/xmlpatterns/schema/qxsdidentityconstraint_p.h create mode 100644 src/xmlpatterns/schema/qxsdinstancereader.cpp create mode 100644 src/xmlpatterns/schema/qxsdinstancereader_p.h create mode 100644 src/xmlpatterns/schema/qxsdmodelgroup.cpp create mode 100644 src/xmlpatterns/schema/qxsdmodelgroup_p.h create mode 100644 src/xmlpatterns/schema/qxsdnotation.cpp create mode 100644 src/xmlpatterns/schema/qxsdnotation_p.h create mode 100644 src/xmlpatterns/schema/qxsdparticle.cpp create mode 100644 src/xmlpatterns/schema/qxsdparticle_p.h create mode 100644 src/xmlpatterns/schema/qxsdparticlechecker.cpp create mode 100644 src/xmlpatterns/schema/qxsdparticlechecker_p.h create mode 100644 src/xmlpatterns/schema/qxsdreference.cpp create mode 100644 src/xmlpatterns/schema/qxsdreference_p.h create mode 100644 src/xmlpatterns/schema/qxsdschema.cpp create mode 100644 src/xmlpatterns/schema/qxsdschema_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemachecker.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemachecker_helper.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemachecker_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemachecker_setup.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemacontext.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemacontext_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemadebugger.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemadebugger_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemahelper.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemahelper_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemamerger.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemamerger_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemaparser.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemaparser_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemaparser_setup.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemaparsercontext.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemaparsercontext_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemaresolver.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemaresolver_p.h create mode 100644 src/xmlpatterns/schema/qxsdschematoken.cpp create mode 100644 src/xmlpatterns/schema/qxsdschematoken_p.h create mode 100644 src/xmlpatterns/schema/qxsdschematypesfactory.cpp create mode 100644 src/xmlpatterns/schema/qxsdschematypesfactory_p.h create mode 100644 src/xmlpatterns/schema/qxsdsimpletype.cpp create mode 100644 src/xmlpatterns/schema/qxsdsimpletype_p.h create mode 100644 src/xmlpatterns/schema/qxsdstatemachine.cpp create mode 100644 src/xmlpatterns/schema/qxsdstatemachine_p.h create mode 100644 src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp create mode 100644 src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h create mode 100644 src/xmlpatterns/schema/qxsdterm.cpp create mode 100644 src/xmlpatterns/schema/qxsdterm_p.h create mode 100644 src/xmlpatterns/schema/qxsdtypechecker.cpp create mode 100644 src/xmlpatterns/schema/qxsdtypechecker_p.h create mode 100644 src/xmlpatterns/schema/qxsduserschematype.cpp create mode 100644 src/xmlpatterns/schema/qxsduserschematype_p.h create mode 100644 src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp create mode 100644 src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h create mode 100644 src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp create mode 100644 src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h create mode 100644 src/xmlpatterns/schema/qxsdwildcard.cpp create mode 100644 src/xmlpatterns/schema/qxsdwildcard_p.h create mode 100644 src/xmlpatterns/schema/qxsdxpathexpression.cpp create mode 100644 src/xmlpatterns/schema/qxsdxpathexpression_p.h create mode 100644 src/xmlpatterns/schema/schema.pri create mode 100644 src/xmlpatterns/schema/schemas/xml.xsd create mode 100644 src/xmlpatterns/schema/tokens.xml create mode 100644 src/xmlpatterns/type/qnamedschemacomponent.cpp create mode 100644 src/xmlpatterns/type/qnamedschemacomponent_p.h create mode 100644 tests/auto/qxmlschema/.gitignore create mode 100644 tests/auto/qxmlschema/qxmlschema.pro create mode 100644 tests/auto/qxmlschema/tst_qxmlschema.cpp create mode 100644 tests/auto/qxmlschemavalidator/.gitignore create mode 100644 tests/auto/qxmlschemavalidator/qxmlschemavalidator.pro create mode 100644 tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp create mode 100644 tests/auto/xmlpatternsschema/.gitignore create mode 100644 tests/auto/xmlpatternsschema/tst_xmlpatternsschema.cpp create mode 100644 tests/auto/xmlpatternsschema/xmlpatternsschema.pro create mode 100644 tests/auto/xmlpatternsschemats/.gitignore create mode 100644 tests/auto/xmlpatternsschemats/Baseline.xml create mode 100644 tests/auto/xmlpatternsschemats/TESTSUITE/.gitignore create mode 100644 tests/auto/xmlpatternsschemats/TESTSUITE/unifyCatalog.xsl create mode 100755 tests/auto/xmlpatternsschemats/TESTSUITE/updateSuite.sh create mode 100644 tests/auto/xmlpatternsschemats/tst_xmlpatternsschemats.cpp create mode 100644 tests/auto/xmlpatternsschemats/xmlpatternsschemats.pro create mode 100644 tests/auto/xmlpatternsvalidator/files/instance.xml create mode 100644 tests/auto/xmlpatternsvalidator/files/invalid_schema.xsd create mode 100644 tests/auto/xmlpatternsvalidator/files/other_valid_schema.xsd create mode 100644 tests/auto/xmlpatternsvalidator/files/sa_invalid_instance.xml create mode 100644 tests/auto/xmlpatternsvalidator/files/sa_valid_instance.xml create mode 100644 tests/auto/xmlpatternsvalidator/files/valid_schema.xsd create mode 100644 tests/auto/xmlpatternsvalidator/tst_xmlpatternsvalidator.cpp create mode 100644 tests/auto/xmlpatternsvalidator/xmlpatternsvalidator.pro create mode 100644 tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.cpp create mode 100644 tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.h create mode 100644 tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.cpp create mode 100644 tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.h create mode 100644 tools/xmlpatternsvalidator/main.cpp create mode 100644 tools/xmlpatternsvalidator/main.h create mode 100644 tools/xmlpatternsvalidator/xmlpatternsvalidator.pro diff --git a/examples/tools/regexp/regexpdialog.cpp b/examples/tools/regexp/regexpdialog.cpp index 8fe7383..52805c1 100644 --- a/examples/tools/regexp/regexpdialog.cpp +++ b/examples/tools/regexp/regexpdialog.cpp @@ -69,6 +69,7 @@ RegExpDialog::RegExpDialog(QWidget *parent) syntaxComboBox->addItem(tr("Regular expression v2"), QRegExp::RegExp2); syntaxComboBox->addItem(tr("Wildcard"), QRegExp::Wildcard); syntaxComboBox->addItem(tr("Fixed string"), QRegExp::FixedString); + syntaxComboBox->addItem(tr("W3C Xml Schema 1.1"), QRegExp::W3CXmlSchema11); syntaxLabel = new QLabel(tr("&Pattern Syntax:")); syntaxLabel->setBuddy(syntaxComboBox); diff --git a/examples/xmlpatterns/schema/main.cpp b/examples/xmlpatterns/schema/main.cpp new file mode 100644 index 0000000..9537a87 --- /dev/null +++ b/examples/xmlpatterns/schema/main.cpp @@ -0,0 +1,24 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 +#include "mainwindow.h" + +//! [0] +int main(int argc, char* argv[]) +{ + Q_INIT_RESOURCE(schema); + QApplication app(argc, argv); + MainWindow* const window = new MainWindow; + window->show(); + return app.exec(); +} +//! [0] diff --git a/examples/xmlpatterns/schema/mainwindow.cpp b/examples/xmlpatterns/schema/mainwindow.cpp new file mode 100644 index 0000000..807a65b --- /dev/null +++ b/examples/xmlpatterns/schema/mainwindow.cpp @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 +#include + +#include "mainwindow.h" +#include "xmlsyntaxhighlighter.h" + +class MessageHandler : public QAbstractMessageHandler +{ + public: + MessageHandler() + : QAbstractMessageHandler(0) + { + } + + QString statusMessage() const + { + return m_description; + } + + int line() const + { + return m_sourceLocation.line(); + } + + int column() const + { + return m_sourceLocation.column(); + } + + protected: + virtual void handleMessage(QtMsgType type, const QString &description, const QUrl &identifier, const QSourceLocation &sourceLocation) + { + Q_UNUSED(type); + Q_UNUSED(identifier); + + m_messageType = type; + m_description = description; + m_sourceLocation = sourceLocation; + } + + private: + QtMsgType m_messageType; + QString m_description; + QSourceLocation m_sourceLocation; +}; + +MainWindow::MainWindow() +{ + setupUi(this); + + new XmlSyntaxHighlighter(schemaView->document()); + new XmlSyntaxHighlighter(instanceEdit->document()); + + schemaSelection->addItem(tr("Contact Schema")); + schemaSelection->addItem(tr("Recipe Schema")); + schemaSelection->addItem(tr("Order Schema")); + + instanceSelection->addItem(tr("Valid Contact Instance")); + instanceSelection->addItem(tr("Invalid Contact Instance")); + + connect(schemaSelection, SIGNAL(currentIndexChanged(int)), SLOT(schemaSelected(int))); + connect(instanceSelection, SIGNAL(currentIndexChanged(int)), SLOT(instanceSelected(int))); + connect(validateButton, SIGNAL(clicked()), SLOT(validate())); + connect(instanceEdit, SIGNAL(textChanged()), SLOT(textChanged())); + + validationStatus->setAlignment(Qt::AlignCenter | Qt::AlignVCenter); + + schemaSelected(0); + instanceSelected(0); +} + +void MainWindow::schemaSelected(int index) +{ + instanceSelection->clear(); + if (index == 0) { + instanceSelection->addItem(tr("Valid Contact Instance")); + instanceSelection->addItem(tr("Invalid Contact Instance")); + } else if (index == 1) { + instanceSelection->addItem(tr("Valid Recipe Instance")); + instanceSelection->addItem(tr("Invalid Recipe Instance")); + } else if (index == 2) { + instanceSelection->addItem(tr("Valid Order Instance")); + instanceSelection->addItem(tr("Invalid Order Instance")); + } + textChanged(); + + QFile schemaFile(QString(":/schema_%1.xsd").arg(index)); + schemaFile.open(QIODevice::ReadOnly); + const QString schemaText(QString::fromLatin1(schemaFile.readAll())); + schemaView->setPlainText(schemaText); + + validate(); +} + +void MainWindow::instanceSelected(int index) +{ + QFile instanceFile(QString(":/instance_%1.xml").arg((2*schemaSelection->currentIndex()) + index)); + instanceFile.open(QIODevice::ReadOnly); + const QString instanceText(QString::fromLatin1(instanceFile.readAll())); + instanceEdit->setPlainText(instanceText); + + validate(); +} + +void MainWindow::validate() +{ + const QByteArray schemaData = schemaView->toPlainText().toLatin1(); + const QByteArray instanceData = instanceEdit->toPlainText().toLatin1(); + + MessageHandler messageHandler; + + QXmlSchema schema; + schema.setMessageHandler(&messageHandler); + + schema.load(schemaData, QUrl("http://dummySchemaUrl/")); + + bool errorOccurred = false; + if (!schema.isValid()) { + errorOccurred = true; + } else { + QXmlSchemaValidator validator(schema); + if (!validator.validate(instanceData, QUrl("http://dummyInstanceUrl"))) + errorOccurred = true; + } + + if (errorOccurred) { + validationStatus->setText(messageHandler.statusMessage()); + moveCursor(messageHandler.line(), messageHandler.column()); + } else { + validationStatus->setText(tr("validation successful")); + } + + QString styleSheet = QString("QLabel {background: %1; padding: 3px}").arg(errorOccurred ? QColor(Qt::red).lighter(160).name() : QColor(Qt::green).lighter(160).name()); + validationStatus->setStyleSheet(styleSheet); +} + +void MainWindow::textChanged() +{ + instanceEdit->setExtraSelections(QList()); +} + +void MainWindow::moveCursor(int line, int column) +{ + instanceEdit->moveCursor(QTextCursor::Start); + for (int i = 1; i < line; ++i) + instanceEdit->moveCursor(QTextCursor::Down); + + for (int i = 1; i < column; ++i) + instanceEdit->moveCursor(QTextCursor::Right); + + QList extraSelections; + QTextEdit::ExtraSelection selection; + + const QColor lineColor = QColor(Qt::red).lighter(160); + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = instanceEdit->textCursor(); + selection.cursor.clearSelection(); + extraSelections.append(selection); + + instanceEdit->setExtraSelections(extraSelections); + + instanceEdit->setFocus(); +} diff --git a/examples/xmlpatterns/schema/mainwindow.h b/examples/xmlpatterns/schema/mainwindow.h new file mode 100644 index 0000000..e5dc2df --- /dev/null +++ b/examples/xmlpatterns/schema/mainwindow.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +#include "ui_schema.h" + +//! [0] +class MainWindow : public QMainWindow, + private Ui::SchemaMainWindow +{ + Q_OBJECT + + public: + MainWindow(); + + private Q_SLOTS: + void schemaSelected(int index); + void instanceSelected(int index); + void validate(); + void textChanged(); + + private: + void moveCursor(int line, int column); +}; +//! [0] +#endif diff --git a/examples/xmlpatterns/schema/schema.pro b/examples/xmlpatterns/schema/schema.pro new file mode 100644 index 0000000..af32e0a --- /dev/null +++ b/examples/xmlpatterns/schema/schema.pro @@ -0,0 +1,11 @@ +QT += xmlpatterns +FORMS += schema.ui +HEADERS = mainwindow.h ../shared/xmlsyntaxhighlighter.h +RESOURCES = schema.qrc +SOURCES = main.cpp mainwindow.cpp ../shared/xmlsyntaxhighlighter.cpp +INCLUDEPATH += ../shared/ + +target.path = $$[QT_INSTALL_EXAMPLES]/xmlpatterns/schema +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.xq *.html files +sources.path = $$[QT_INSTALL_EXAMPLES]/xmlpatterns/schema +INSTALLS += target sources diff --git a/examples/xmlpatterns/schema/schema.qrc b/examples/xmlpatterns/schema/schema.qrc new file mode 100644 index 0000000..eb7ddfd --- /dev/null +++ b/examples/xmlpatterns/schema/schema.qrc @@ -0,0 +1,13 @@ + + + files/contact.xsd + files/recipe.xsd + files/order.xsd + files/valid_contact.xml + files/invalid_contact.xml + files/valid_recipe.xml + files/invalid_recipe.xml + files/valid_order.xml + files/invalid_order.xml + + diff --git a/examples/xmlpatterns/schema/schema.ui b/examples/xmlpatterns/schema/schema.ui new file mode 100644 index 0000000..af7020a --- /dev/null +++ b/examples/xmlpatterns/schema/schema.ui @@ -0,0 +1,71 @@ + + + SchemaMainWindow + + + + 0 + 0 + 417 + 594 + + + + MainWindow + + + + + + + XML Schema Document: + + + + + + + + + + + + + XML Instance Document: + + + + + + + + + + + + + Status: + + + + + + + not validated + + + + + + + Validate + + + + + + + + + + diff --git a/examples/xmlpatterns/xmlpatterns.pro b/examples/xmlpatterns/xmlpatterns.pro index 1a57005..3ff3e35 100644 --- a/examples/xmlpatterns/xmlpatterns.pro +++ b/examples/xmlpatterns/xmlpatterns.pro @@ -2,7 +2,8 @@ TEMPLATE = subdirs SUBDIRS = recipes \ trafficinfo \ xquery \ - filetree + filetree \ + schema # This example depends on QtWebkit as well. contains(QT_CONFIG, webkit):SUBDIRS += qobjectxmlmodel diff --git a/src/xmlpatterns/Doxyfile b/src/xmlpatterns/Doxyfile index 60a6c77..83f7062 100644 --- a/src/xmlpatterns/Doxyfile +++ b/src/xmlpatterns/Doxyfile @@ -1157,7 +1157,7 @@ DOT_PATH = # contain dot files that are included in the documentation (see the # \dotfile command). -DOTFILE_DIRS = +DOTFILE_DIRS = schema/doc/ # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. diff --git a/src/xmlpatterns/acceltree/qacceltree.cpp b/src/xmlpatterns/acceltree/qacceltree.cpp index 60e6e27..061021a 100644 --- a/src/xmlpatterns/acceltree/qacceltree.cpp +++ b/src/xmlpatterns/acceltree/qacceltree.cpp @@ -42,6 +42,7 @@ #include #include "qabstractxmlreceiver.h" +#include "qabstractxmlnodemodel_p.h" #include "qacceliterators_p.h" #include "qacceltree_p.h" #include "qatomicstring_p.h" @@ -55,6 +56,37 @@ QT_BEGIN_NAMESPACE using namespace QPatternist; +namespace QPatternist { + + class AccelTreePrivate : public QAbstractXmlNodeModelPrivate + { + public: + AccelTreePrivate(AccelTree *accelTree) + : m_accelTree(accelTree) + { + } + + virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const + { + return m_accelTree->sourceLocation(index); + } + + private: + AccelTree *m_accelTree; + }; +} + +AccelTree::AccelTree(const QUrl &docURI, const QUrl &bURI) + : QAbstractXmlNodeModel(new AccelTreePrivate(this)) + , m_documentURI(docURI) + , m_baseURI(bURI) +{ + /* Pre-allocate at least a little bit. */ + // TODO. Do it according to what an average 4 KB doc contains. + basicData.reserve(100); + data.reserve(30); +} + void AccelTree::printStats(const NamePool::Ptr &np) const { Q_ASSERT(np); @@ -674,6 +706,17 @@ void AccelTree::copyNodeTo(const QXmlNodeModelIndex &node, } +QSourceLocation AccelTree::sourceLocation(const QXmlNodeModelIndex &index) const +{ + const PreNumber key = toPreNumber(index); + if (sourcePositions.contains(key)) { + const QPair position = sourcePositions.value(key); + return QSourceLocation(m_documentURI, position.first, position.second); + } else { + return QSourceLocation(); + } +} + void AccelTree::copyChildren(const QXmlNodeModelIndex &node, QAbstractXmlReceiver *const receiver, const NodeCopySettings &settings) const diff --git a/src/xmlpatterns/acceltree/qacceltree_p.h b/src/xmlpatterns/acceltree/qacceltree_p.h index 10320ba..4c0d844 100644 --- a/src/xmlpatterns/acceltree/qacceltree_p.h +++ b/src/xmlpatterns/acceltree/qacceltree_p.h @@ -91,6 +91,7 @@ namespace QPatternist */ class AccelTree : public QAbstractXmlNodeModel { + friend class AccelTreePrivate; public: using QAbstractXmlNodeModel::createIndex; @@ -99,15 +100,7 @@ namespace QPatternist typedef PreNumber PostNumber; typedef qint8 Depth; - inline AccelTree(const QUrl &docURI, - const QUrl &bURI) : m_documentURI(docURI), - m_baseURI(bURI) - { - /* Pre-allocate at least a little bit. */ - // TODO. Do it according to what an average 4 KB doc contains. - basicData.reserve(100); - data.reserve(30); - } + AccelTree(const QUrl &docURI, const QUrl &bURI); /** * @short Houses data for a node, and that all node kinds have. @@ -280,6 +273,7 @@ namespace QPatternist QHash data; QVector basicData; + QHash > sourcePositions; inline QUrl documentUri() const { @@ -381,6 +375,11 @@ namespace QPatternist private: /** + * Returns the source location for the object with the given @p index. + */ + QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const; + + /** * Copies the children of @p node to @p receiver. */ inline void copyChildren(const QXmlNodeModelIndex &node, diff --git a/src/xmlpatterns/acceltree/qacceltreebuilder.cpp b/src/xmlpatterns/acceltree/qacceltreebuilder.cpp index 5b16cc3..ddc118c 100644 --- a/src/xmlpatterns/acceltree/qacceltreebuilder.cpp +++ b/src/xmlpatterns/acceltree/qacceltreebuilder.cpp @@ -49,15 +49,17 @@ template AccelTreeBuilder::AccelTreeBuilder(const QUrl &docURI, const QUrl &baseURI, const NamePool::Ptr &np, - ReportContext *const context) : m_preNumber(-1) - , m_isPreviousAtomic(false) - , m_hasCharacters(false) - , m_isCharactersCompressed(false) - , m_namePool(np) - , m_document(new AccelTree(docURI, baseURI)) - , m_skippedDocumentNodes(0) - , m_documentURI(docURI) - , m_context(context) + ReportContext *const context, + Features features) : m_preNumber(-1) + , m_isPreviousAtomic(false) + , m_hasCharacters(false) + , m_isCharactersCompressed(false) + , m_namePool(np) + , m_document(new AccelTree(docURI, baseURI)) + , m_skippedDocumentNodes(0) + , m_documentURI(docURI) + , m_context(context) + , m_features(features) { Q_ASSERT(m_namePool); @@ -126,9 +128,18 @@ void AccelTreeBuilder::item(const Item &it) template void AccelTreeBuilder::startElement(const QXmlName &name) { + startElement(name, 1, 1); +} + +template +void AccelTreeBuilder::startElement(const QXmlName &name, qint64 line, qint64 column) +{ startStructure(); - m_document->basicData.append(AccelTree::BasicNodeData(currentDepth(), currentParent(), QXmlNodeModelIndex::Element, -1, name)); + AccelTree::BasicNodeData data(currentDepth(), currentParent(), QXmlNodeModelIndex::Element, -1, name); + m_document->basicData.append(data); + if (m_features & SourceLocationsFeature) + m_document->sourcePositions.insert(m_document->maximumPreNumber(), qMakePair(line, column)); ++m_preNumber; m_ancestors.push(m_preNumber); diff --git a/src/xmlpatterns/acceltree/qacceltreebuilder_p.h b/src/xmlpatterns/acceltree/qacceltreebuilder_p.h index 653eb85..91e8d68 100644 --- a/src/xmlpatterns/acceltree/qacceltreebuilder_p.h +++ b/src/xmlpatterns/acceltree/qacceltreebuilder_p.h @@ -90,15 +90,27 @@ namespace QPatternist typedef QExplicitlySharedDataPointer Ptr; /** + * Describes the memory relevant features the builder shall support. + */ + enum Feature + { + NoneFeature, ///< No special features are enabled. + SourceLocationsFeature = 1 ///< The accel tree builder will store source locations for each start element. + }; + Q_DECLARE_FLAGS(Features, Feature) + + /** * @param context may be @c null. */ AccelTreeBuilder(const QUrl &docURI, const QUrl &baseURI, const NamePool::Ptr &np, - ReportContext *const context); + ReportContext *const context, + Features features = NoneFeature); virtual void startDocument(); virtual void endDocument(); virtual void startElement(const QXmlName &name); + void startElement(const QXmlName &name, qint64 line, qint64 column); virtual void endElement(); virtual void attribute(const QXmlName &name, const QStringRef &value); virtual void characters(const QStringRef &ch); @@ -175,8 +187,13 @@ namespace QPatternist * a member. */ ReportContext *const m_context; + + Features m_features; }; + Q_DECLARE_OPERATORS_FOR_FLAGS(AccelTreeBuilder::Features) + Q_DECLARE_OPERATORS_FOR_FLAGS(AccelTreeBuilder::Features) + #include "qacceltreebuilder.cpp" } diff --git a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp index 4a5c219..7c3d2c0 100644 --- a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp +++ b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp @@ -46,7 +46,6 @@ #include -#include "qacceltreebuilder_p.h" #include "qatomicstring_p.h" #include "qautoptr_p.h" #include "qcommonsequencetypes_p.h" @@ -57,14 +56,12 @@ QT_BEGIN_NAMESPACE using namespace QPatternist; -static inline uint qHash(const QUrl &uri) -{ - return qHash(uri.toString()); -} - AccelTreeResourceLoader::AccelTreeResourceLoader(const NamePool::Ptr &np, - const NetworkAccessDelegator::Ptr &manager) : m_namePool(np) - , m_networkAccessDelegator(manager) + const NetworkAccessDelegator::Ptr &manager, + AccelTreeBuilder::Features features) + : m_namePool(np) + , m_networkAccessDelegator(manager) + , m_features(features) { Q_ASSERT(m_namePool); Q_ASSERT(m_networkAccessDelegator); @@ -74,7 +71,7 @@ bool AccelTreeResourceLoader::retrieveDocument(const QUrl &uri, const ReportContext::Ptr &context) { Q_ASSERT(uri.isValid()); - AccelTreeBuilder builder(uri, uri, m_namePool, context.data()); + AccelTreeBuilder builder(uri, uri, m_namePool, context.data(), m_features); const AutoPtr reply(load(uri, m_networkAccessDelegator, context)); @@ -88,18 +85,35 @@ bool AccelTreeResourceLoader::retrieveDocument(const QUrl &uri, return success; } +bool AccelTreeResourceLoader::retrieveDocument(QIODevice *source, const QUrl &documentUri, const ReportContext::Ptr &context) +{ + Q_ASSERT(source); + Q_ASSERT(source->isReadable()); + Q_ASSERT(documentUri.isValid()); + + AccelTreeBuilder builder(documentUri, documentUri, m_namePool, context.data(), m_features); + + bool success = false; + success = streamToReceiver(source, &builder, m_namePool, context, documentUri); + + m_loadedDocuments.insert(documentUri, builder.builtDocument()); + + return success; +} + QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri, const NetworkAccessDelegator::Ptr &networkDelegator, - const ReportContext::Ptr &context) + const ReportContext::Ptr &context, ErrorHandling errorHandling) { return load(uri, networkDelegator->managerFor(uri), - context); + context, errorHandling); } QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri, QNetworkAccessManager *const networkManager, - const ReportContext::Ptr &context) + const ReportContext::Ptr &context, ErrorHandling errorHandling) + { Q_ASSERT(networkManager); Q_ASSERT(uri.isValid()); @@ -120,7 +134,7 @@ QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri, const QSourceLocation location(uri); - if(context) + if(context && (errorHandling == FailOnError)) context->error(errorMessage, ReportContext::FODC0002, location); return 0; @@ -130,7 +144,7 @@ QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri, } bool AccelTreeResourceLoader::streamToReceiver(QIODevice *const dev, - QAbstractXmlReceiver *const receiver, + AccelTreeBuilder *const receiver, const NamePool::Ptr &np, const ReportContext::Ptr &context, const QUrl &uri) @@ -154,7 +168,7 @@ bool AccelTreeResourceLoader::streamToReceiver(QIODevice *const dev, { /* Send the name. */ receiver->startElement(np->allocateQName(reader.namespaceUri().toString(), reader.name().toString(), - reader.prefix().toString())); + reader.prefix().toString()), reader.lineNumber(), reader.columnNumber()); /* Send namespace declarations. */ const QXmlStreamNamespaceDeclarations &nss = reader.namespaceDeclarations(); @@ -263,6 +277,22 @@ Item AccelTreeResourceLoader::openDocument(const QUrl &uri, } } +Item AccelTreeResourceLoader::openDocument(QIODevice *source, const QUrl &documentUri, + const ReportContext::Ptr &context) +{ + const AccelTree::Ptr doc(m_loadedDocuments.value(documentUri)); + + if(doc) + return doc->root(QXmlNodeModelIndex()); /* Pass in dummy object. We know AccelTree doesn't use it. */ + else + { + if(retrieveDocument(source, documentUri, context)) + return m_loadedDocuments.value(documentUri)->root(QXmlNodeModelIndex()); /* Pass in dummy object. We know AccelTree doesn't use it. */ + else + return Item(); + } +} + SequenceType::Ptr AccelTreeResourceLoader::announceDocument(const QUrl &uri, const Usage) { // TODO deal with the usage thingy diff --git a/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h b/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h index 863fd65..56f547a 100644 --- a/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h +++ b/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h @@ -52,12 +52,12 @@ #ifndef Patternist_AccelTreeResourceLoader_H #define Patternist_AccelTreeResourceLoader_H -#include #include #include #include "qabstractxmlreceiver.h" #include "qacceltree_p.h" +#include "qacceltreebuilder_p.h" #include "qdeviceresourceloader_p.h" #include "qnamepool_p.h" #include "qnetworkaccessdelegator_p.h" @@ -115,13 +115,25 @@ namespace QPatternist { public: /** + * Describes the behaviour of the resource loader in case of an + * error. + */ + enum ErrorHandling + { + FailOnError, ///< The resource loader will report the error via the report context. + ContinueOnError ///< The resource loader will report no error and return an empty QNetworkReply. + }; + + /** * AccelTreeResourceLoader does not own @p context. */ AccelTreeResourceLoader(const NamePool::Ptr &np, - const NetworkAccessDelegator::Ptr &networkDelegator); + const NetworkAccessDelegator::Ptr &networkDelegator, AccelTreeBuilder::Features = AccelTreeBuilder::NoneFeature); virtual Item openDocument(const QUrl &uri, const ReportContext::Ptr &context); + virtual Item openDocument(QIODevice *source, const QUrl &documentUri, + const ReportContext::Ptr &context); virtual SequenceType::Ptr announceDocument(const QUrl &uri, const Usage usageHint); virtual bool isDocumentAvailable(const QUrl &uri); @@ -133,7 +145,6 @@ namespace QPatternist const ReportContext::Ptr &context, const SourceLocationReflection *const where); - /** * @short Helper function that do NetworkAccessDelegator::get(), but * does it blocked. @@ -149,14 +160,14 @@ namespace QPatternist */ static QNetworkReply *load(const QUrl &uri, QNetworkAccessManager *const networkManager, - const ReportContext::Ptr &context); + const ReportContext::Ptr &context, ErrorHandling handling = FailOnError); /** * @overload */ static QNetworkReply *load(const QUrl &uri, const NetworkAccessDelegator::Ptr &networkDelegator, - const ReportContext::Ptr &context); + const ReportContext::Ptr &context, ErrorHandling handling = FailOnError); /** * @short Returns the URIs this AccelTreeResourceLoader has loaded @@ -165,14 +176,17 @@ namespace QPatternist virtual QSet deviceURIs() const; virtual void clear(const QUrl &uri); + private: static bool streamToReceiver(QIODevice *const dev, - QAbstractXmlReceiver *const receiver, + AccelTreeBuilder *const receiver, const NamePool::Ptr &np, const ReportContext::Ptr &context, const QUrl &uri); bool retrieveDocument(const QUrl &uri, const ReportContext::Ptr &context); + bool retrieveDocument(QIODevice *source, const QUrl &documentUri, + const ReportContext::Ptr &context); /** * If @p context is @c null, no error reporting should be done. */ @@ -185,6 +199,7 @@ namespace QPatternist const NamePool::Ptr m_namePool; const NetworkAccessDelegator::Ptr m_networkAccessDelegator; QHash, QString> m_unparsedTexts; + AccelTreeBuilder::Features m_features; }; } diff --git a/src/xmlpatterns/api/api.pri b/src/xmlpatterns/api/api.pri index a0298f2..9fcc2f5 100644 --- a/src/xmlpatterns/api/api.pri +++ b/src/xmlpatterns/api/api.pri @@ -3,11 +3,13 @@ HEADERS += $$PWD/qabstractxmlforwarditerator_p.h \ $$PWD/qabstracturiresolver.h \ $$PWD/qabstractxmlnodemodel.h \ $$PWD/qabstractxmlnodemodel_p.h \ + $$PWD/qabstractxmlpullprovider_p.h \ $$PWD/qabstractxmlreceiver.h \ $$PWD/qabstractxmlreceiver_p.h \ $$PWD/qdeviceresourceloader_p.h \ $$PWD/qiodevicedelegate_p.h \ $$PWD/qnetworkaccessdelegator_p.h \ + $$PWD/qpullbridge_p.h \ $$PWD/qresourcedelegator_p.h \ $$PWD/qsimplexmlnodemodel.h \ $$PWD/qsourcelocation.h \ @@ -20,6 +22,10 @@ HEADERS += $$PWD/qabstractxmlforwarditerator_p.h \ $$PWD/qxmlquery_p.h \ $$PWD/qxmlresultitems.h \ $$PWD/qxmlresultitems_p.h \ + $$PWD/qxmlschema.h \ + $$PWD/qxmlschema_p.h \ + $$PWD/qxmlschemavalidator.h \ + $$PWD/qxmlschemavalidator_p.h \ $$PWD/qxmlserializer.h \ $$PWD/qxmlserializer_p.h \ $$PWD/../../../tools/xmlpatterns/qcoloringmessagehandler_p.h \ @@ -29,9 +35,11 @@ SOURCES += $$PWD/qvariableloader.cpp \ $$PWD/qabstractmessagehandler.cpp \ $$PWD/qabstracturiresolver.cpp \ $$PWD/qabstractxmlnodemodel.cpp \ + $$PWD/qabstractxmlpullprovider.cpp \ $$PWD/qabstractxmlreceiver.cpp \ $$PWD/qiodevicedelegate.cpp \ $$PWD/qnetworkaccessdelegator.cpp \ + $$PWD/qpullbridge.cpp \ $$PWD/qresourcedelegator.cpp \ $$PWD/qsimplexmlnodemodel.cpp \ $$PWD/qsourcelocation.cpp \ @@ -41,6 +49,9 @@ SOURCES += $$PWD/qvariableloader.cpp \ $$PWD/qxmlnamepool.cpp \ $$PWD/qxmlquery.cpp \ $$PWD/qxmlresultitems.cpp \ + $$PWD/qxmlschema.cpp \ + $$PWD/qxmlschema_p.cpp \ + $$PWD/qxmlschemavalidator.cpp \ $$PWD/qxmlserializer.cpp \ $$PWD/../../../tools/xmlpatterns/qcoloringmessagehandler.cpp \ $$PWD/../../../tools/xmlpatterns/qcoloroutput.cpp diff --git a/src/xmlpatterns/api/qabstractxmlnodemodel.cpp b/src/xmlpatterns/api/qabstractxmlnodemodel.cpp index 0caa8c4..f535ec8 100644 --- a/src/xmlpatterns/api/qabstractxmlnodemodel.cpp +++ b/src/xmlpatterns/api/qabstractxmlnodemodel.cpp @@ -1666,4 +1666,20 @@ void QAbstractXmlNodeModel::copyNodeTo(const QXmlNodeModelIndex &node, "This function is not expected to be called."); } +/*! + Returns the source location for the object with the given \a index + or a default constructed QSourceLocation in case no location + information is available. + + \since TODO + */ +QSourceLocation QAbstractXmlNodeModel::sourceLocation(const QXmlNodeModelIndex &index) const +{ + // TODO: make this method virtual in Qt5 to allow source location support in custom models + if (d_ptr) + return d_ptr->sourceLocation(index); + else + return QSourceLocation(); +} + QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qabstractxmlnodemodel.h b/src/xmlpatterns/api/qabstractxmlnodemodel.h index 6c9574c..1d860a3 100644 --- a/src/xmlpatterns/api/qabstractxmlnodemodel.h +++ b/src/xmlpatterns/api/qabstractxmlnodemodel.h @@ -56,6 +56,7 @@ QT_MODULE(XmlPatterns) class QAbstractXmlNodeModel; class QAbstractXmlNodeModelPrivate; class QAbstractXmlReceiver; +class QSourceLocation; class QUrl; class QXmlName; class QXmlNodeModelIndex; @@ -69,6 +70,7 @@ namespace QPatternist class DynamicContext; class Item; class ItemType; + class XsdValidatedXmlNodeModel; template class ItemMappingIterator; template class SequenceMappingIterator; typedef QExplicitlySharedDataPointer ItemTypePtr; @@ -315,6 +317,8 @@ public: QAbstractXmlReceiver *const receiver, const NodeCopySettings &) const; + QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const; + protected: virtual QXmlNodeModelIndex nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const = 0; @@ -343,6 +347,7 @@ protected: private: friend class QPatternist::ItemMappingIterator >; friend class QPatternist::SequenceMappingIterator; + friend class QPatternist::XsdValidatedXmlNodeModel; inline QExplicitlySharedDataPointer > mapToSequence(const QXmlNodeModelIndex &ni, const QExplicitlySharedDataPointer &) const; diff --git a/src/xmlpatterns/api/qabstractxmlnodemodel_p.h b/src/xmlpatterns/api/qabstractxmlnodemodel_p.h index 16ce613..0ab1b26 100644 --- a/src/xmlpatterns/api/qabstractxmlnodemodel_p.h +++ b/src/xmlpatterns/api/qabstractxmlnodemodel_p.h @@ -52,6 +52,9 @@ #ifndef QABSTRACTXMLNODEMODEL_P_H #define QABSTRACTXMLNODEMODEL_P_H +#include "qabstractxmlnodemodel.h" +#include "qsourcelocation.h" + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -62,6 +65,13 @@ public: virtual ~QAbstractXmlNodeModelPrivate() { } + + virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const + { + Q_UNUSED(index); + + return QSourceLocation(); + } }; QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qabstractxmlpullprovider.cpp b/src/xmlpatterns/api/qabstractxmlpullprovider.cpp new file mode 100644 index 0000000..a80604b --- /dev/null +++ b/src/xmlpatterns/api/qabstractxmlpullprovider.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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 + +#include "qxmlname.h" +#include "qnamepool_p.h" +#include "qabstractxmlpullprovider_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +// TODO have example where query selects, and the events for the result are indented + +/*! + \internal + \class AbstractXmlPullProvider + \brief The AbstractXmlPullProvider class provides a pull-based stream interface for the XPath Data Model. + \reentrant + \ingroup xml-tools + + AbstractXmlPullProvider allows a stream of items from the XPath Data Model -- essentially XML -- + to be iterated over. The subclass of AbstractXmlPullProvider provides the events, and the + user calling next() and so on, consumes them. AbstractXmlPullProvider can be considered + a forward-only, non-reversible iterator. + + Note that the content the events describes, are not necessarily a well-formed XML document, but + rather an instance of the XPath Data model, to be specific. For instance, maybe a pull provider + returns two atomic values, followed by an element tree, and at the end two document nodes. + + If you are subclassing AbstractXmlPullProvider, be careful to correctly implement + the behaviors, as described for the individual members and events. + + \sa AbstractXmlPullProvider::Event + */ + +/*! + \enum AbstractXmlPullProvider::Event + \value StartOfInput The value AbstractXmlPullProvider::current() returns before the first call to next(). + \value AtomicValue an atomic value such as an \c xs:integer, \c xs:hexBinary, or \c xs:dateTime. Atomic values + can only be top level items. + \value StartDocument Signals the start of a document node. Note that a AbstractXmlPullProvider can provide + a sequence of document nodes. + \value EndDocument Signals the end of a document node. StartDocument and EndDocument are always balanced + and always top-level events. For instance, StartDocument can never appear after any StartElement + events that hasn't been balanced by the corresponding amount of EndElement events. + \value StartElement Signals an element start tag. + \value EndElement Signals the end of an element. StartElement and EndElement events are always balanced. + \value Text Signals a text node. Adjacent text nodes cannot occur. + \value ProcessingInstruction A processing instruction. Its name is returned from name(), and its value in stringValue(). + \value Comment a comment node. Its value can be retrieved with stingValue(). + \value Attribute Signals an attribute node. Attribute events can only appear after Namespace events, or + if no such are sent, after the StartElement. In addition they must appear sequentially, + and each name must be unique. The ordering of attribute events is undefined and insignificant. + \value Namespace Signals a namespace binding. They occur very infrequently and are not needed for attributes + and elements. Namespace events can only appear after the StartElement event. The + ordering of namespace events is undefined and insignificant. + \value EndOfInput When next() is called after the last event, EndOfInput is returned. + + \sa AbstractXmlPullProvider::current() + */ + +/*! + Constucts a AbstractXmlPullProvider instance. + */ +AbstractXmlPullProvider::AbstractXmlPullProvider() +{ +} + +/*! + Destructs this AbstractXmlPullProvider. + */ +AbstractXmlPullProvider::~AbstractXmlPullProvider() +{ +} + +/*! + \fn Event AbstractXmlPullProvider::next() = 0; + Advances this AbstractXmlPullProvider, and returns the new event. + + \sa current() + */ + +/*! + \fn Event AbstractXmlPullProvider::current() const = 0; + Returns the event that next() returned the last time it was called. It doesn't + alter this AbstractXmlPullProvider. + + current() may not modify this AbstractXmlPullProvider's state. Subsequent calls to current() + must return the same value. + + \sa AbstractXmlPullProvider::Event + */ + +/*! + \fn QName AbstractXmlPullProvider::name() const = 0; + If the current event is StartElement, + EndElement, ProcessingInstruction, Attribute, or Namespace, the node's name is returned. + + If the current event is ProcessingInstruction, + the processing instruction target is in in the local name. + + If the current event is Namespace, the name's namespace URI is the namespace, and + the local name is the prefix the name is binding to. + + In all other cases, an invalid QName is returned. + */ + +/*! + \fn QVariant AbstractXmlPullProvider::atomicValue() const = 0; + + If current() event is AtomicValue, the atomic value is returned as a QVariant. + In all other cases, this function returns a null QVariant. + */ + +/*! + \fn QString AbstractXmlPullProvider::stringValue() const = 0; + + If current() is Text, the text node's value is returned. + + If the current() event is Comment, its value is returned. The subclasser guarantees + it does not contain the string "-->". + + If the current() event is ProcessingInstruction, its data is returned. The subclasser + guarantees the data does not contain the string "?>". + + In other cases, it returns a default constructed string. + */ + +/*! + \fn QHash AbstractXmlPullProvider::attributes() = 0; + + If the current() is Element, the attributes of the element are returned, + an empty list of attributes otherwise. + */ + +QT_END_NAMESPACE + diff --git a/src/xmlpatterns/api/qabstractxmlpullprovider_p.h b/src/xmlpatterns/api/qabstractxmlpullprovider_p.h new file mode 100644 index 0000000..d05e649 --- /dev/null +++ b/src/xmlpatterns/api/qabstractxmlpullprovider_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** 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 QABSTRACTXMLPULLPROVIDER_H +#define QABSTRACTXMLPULLPROVIDER_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlItem; +class QXmlName; +class QString; +class QVariant; +template class QHash; + +namespace QPatternist +{ + class AbstractXmlPullProviderPrivate; + + class AbstractXmlPullProvider + { + public: + AbstractXmlPullProvider(); + virtual ~AbstractXmlPullProvider(); + + enum Event + { + StartOfInput = 1, + AtomicValue = 1 << 1, + StartDocument = 1 << 2, + EndDocument = 1 << 3, + StartElement = 1 << 4, + EndElement = 1 << 5, + Text = 1 << 6, + ProcessingInstruction = 1 << 7, + Comment = 1 << 8, + Attribute = 1 << 9, + Namespace = 1 << 10, + EndOfInput = 1 << 11 + }; + + virtual Event next() = 0; + virtual Event current() const = 0; + virtual QXmlName name() const = 0; + virtual QVariant atomicValue() const = 0; + virtual QString stringValue() const = 0; + + virtual QHash attributes() = 0; + virtual QHash attributeItems() = 0; + + /* *** The functions below are internal. */ + private: + Q_DISABLE_COPY(AbstractXmlPullProvider) + AbstractXmlPullProviderPrivate *d; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qpullbridge.cpp b/src/xmlpatterns/api/qpullbridge.cpp new file mode 100644 index 0000000..f347339 --- /dev/null +++ b/src/xmlpatterns/api/qpullbridge.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** 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 + +#include "qabstractxmlnodemodel_p.h" +#include "qitemmappingiterator_p.h" +#include "qitem_p.h" +#include "qxmlname.h" +#include "qxmlquery_p.h" + +#include "qpullbridge_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +/*! + \brief Bridges a QPatternist::SequenceIterator to QAbstractXmlPullProvider. + \class QPatternist::PullBridge + \internal + \reentrant + \ingroup xml-tools + + The approach of this class is rather straight forward since QPatternist::SequenceIterator + and QAbstractXmlPullProvider are conceptually similar. While QPatternist::SequenceIterator only + delivers top level items(since it's not an event stream, it's a list of items), PullBridge + needs to recursively iterate the children of nodes too, which is achieved through the + stack m_iterators. + */ + +AbstractXmlPullProvider::Event PullBridge::next() +{ + m_index = m_iterators.top().second->next(); + + if(!m_index.isNull()) + { + Item item(m_index); + + if(item && item.isAtomicValue()) + m_current = AtomicValue; + else + { + Q_ASSERT(item.isNode()); + + switch(m_index.kind()) + { + case QXmlNodeModelIndex::Attribute: + { + m_current = Attribute; + break; + } + case QXmlNodeModelIndex::Comment: + { + m_current = Comment; + break; + } + case QXmlNodeModelIndex::Element: + { + m_iterators.push(qMakePair(StartElement, m_index.iterate(QXmlNodeModelIndex::AxisChild))); + m_current = StartElement; + break; + } + case QXmlNodeModelIndex::Document: + { + m_iterators.push(qMakePair(StartDocument, m_index.iterate(QXmlNodeModelIndex::AxisChild))); + m_current = StartDocument; + break; + } + case QXmlNodeModelIndex::Namespace: + { + m_current = Namespace; + break; + } + case QXmlNodeModelIndex::ProcessingInstruction: + { + m_current = ProcessingInstruction; + break; + } + case QXmlNodeModelIndex::Text: + { + m_current = Text; + break; + } + } + } + } + else + { + if(m_iterators.isEmpty()) + m_current = EndOfInput; + else + { + switch(m_iterators.top().first) + { + case StartOfInput: + { + m_current = EndOfInput; + break; + } + case StartElement: + { + m_current = EndElement; + m_iterators.pop(); + break; + } + case StartDocument: + { + m_current = EndDocument; + m_iterators.pop(); + break; + } + default: + { + Q_ASSERT_X(false, Q_FUNC_INFO, + "Invalid value."); + m_current = EndOfInput; + } + } + } + + } + + return m_current; +} + +AbstractXmlPullProvider::Event PullBridge::current() const +{ + return m_current; +} + +QXmlNodeModelIndex PullBridge::index() const +{ + return m_index; +} + +QSourceLocation PullBridge::sourceLocation() const +{ + return m_index.model()->sourceLocation(m_index); +} + +QXmlName PullBridge::name() const +{ + return m_index.name(); +} + +QVariant PullBridge::atomicValue() const +{ + return QVariant(); +} + +QString PullBridge::stringValue() const +{ + return QString(); +} + +QHash PullBridge::attributes() +{ + Q_ASSERT(m_current == StartElement); + + QHash attributes; + + QXmlNodeModelIndex::Iterator::Ptr it = m_index.iterate(QXmlNodeModelIndex::AxisAttribute); + QXmlNodeModelIndex index = it->next(); + while (!index.isNull()) { + const Item attribute(index); + attributes.insert(index.name(), index.stringValue()); + + index = it->next(); + } + + return attributes; +} + +QHash PullBridge::attributeItems() +{ + Q_ASSERT(m_current == StartElement); + + QHash attributes; + + QXmlNodeModelIndex::Iterator::Ptr it = m_index.iterate(QXmlNodeModelIndex::AxisAttribute); + QXmlNodeModelIndex index = it->next(); + while (!index.isNull()) { + const Item attribute(index); + attributes.insert(index.name(), QXmlItem(index)); + + index = it->next(); + } + + return attributes; +} + +QT_END_NAMESPACE + diff --git a/src/xmlpatterns/api/qpullbridge_p.h b/src/xmlpatterns/api/qpullbridge_p.h new file mode 100644 index 0000000..823d27b --- /dev/null +++ b/src/xmlpatterns/api/qpullbridge_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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_PULLBRIDGE_P_H +#define PATTERNIST_PULLBRIDGE_P_H + +#include +#include + +#include "qabstractxmlforwarditerator_p.h" +#include "qabstractxmlpullprovider_p.h" +#include "qitem_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class PullBridge : public AbstractXmlPullProvider + { + public: + inline PullBridge(const QXmlNodeModelIndex::Iterator::Ptr &it) : m_current(StartOfInput) + { + Q_ASSERT(it); + m_iterators.push(qMakePair(StartOfInput, it)); + } + + virtual Event next(); + virtual Event current() const; + virtual QXmlName name() const; + /** + * Returns always an empty QVariant. + */ + virtual QVariant atomicValue() const; + virtual QString stringValue() const; + virtual QHash attributes(); + virtual QHash attributeItems(); + + QXmlNodeModelIndex index() const; + QSourceLocation sourceLocation() const; + + private: + typedef QStack > IteratorStack; + IteratorStack m_iterators; + QXmlNodeModelIndex m_index; + Event m_current; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qresourcedelegator.cpp b/src/xmlpatterns/api/qresourcedelegator.cpp index 9d43419..fceef30 100644 --- a/src/xmlpatterns/api/qresourcedelegator.cpp +++ b/src/xmlpatterns/api/qresourcedelegator.cpp @@ -45,14 +45,6 @@ QT_BEGIN_NAMESPACE using namespace QPatternist; -/** - * Duplicated in qacceltreeresourceloader.cpp. - */ -static inline uint qHash(const QUrl &uri) -{ - return qHash(uri.toString()); -} - bool ResourceDelegator::isUnparsedTextAvailable(const QUrl &uri, const QString &encoding) { diff --git a/src/xmlpatterns/api/qxmlnamepool.cpp b/src/xmlpatterns/api/qxmlnamepool.cpp index 2337f8d..11274ab 100644 --- a/src/xmlpatterns/api/qxmlnamepool.cpp +++ b/src/xmlpatterns/api/qxmlnamepool.cpp @@ -96,6 +96,10 @@ QXmlNamePool::~QXmlNamePool() { } +QXmlNamePool::QXmlNamePool(QPatternist::NamePool *namePool) : d(QExplicitlySharedDataPointer(namePool)) +{ +} + /*! Assigns the \a other name pool to this one. */ diff --git a/src/xmlpatterns/api/qxmlnamepool.h b/src/xmlpatterns/api/qxmlnamepool.h index 3c1e112..87856ee 100644 --- a/src/xmlpatterns/api/qxmlnamepool.h +++ b/src/xmlpatterns/api/qxmlnamepool.h @@ -54,6 +54,8 @@ QT_MODULE(XmlPatterns) namespace QPatternist { class NamePool; + class XsdSchemaParser; + class XsdValidatingInstanceReader; } namespace QPatternistSDK @@ -73,10 +75,15 @@ public: QXmlNamePool &operator=(const QXmlNamePool &other); private: + QXmlNamePool(QPatternist::NamePool *namePool); friend class QXmlQueryPrivate; friend class QXmlQuery; + friend class QXmlSchemaPrivate; + friend class QXmlSchemaValidatorPrivate; friend class QXmlSerializerPrivate; friend class QXmlName; + friend class QPatternist::XsdSchemaParser; + friend class QPatternist::XsdValidatingInstanceReader; friend class QPatternistSDK::Global; QExplicitlySharedDataPointer d; }; diff --git a/src/xmlpatterns/api/qxmlquery.cpp b/src/xmlpatterns/api/qxmlquery.cpp index 5f9d87d..423da3e 100644 --- a/src/xmlpatterns/api/qxmlquery.cpp +++ b/src/xmlpatterns/api/qxmlquery.cpp @@ -231,6 +231,18 @@ QT_BEGIN_NAMESPACE \value XQuery10 XQuery 1.0. \value XSLT20 XSLT 2.0 + \omitvalue XmlSchema11IdentityConstraintSelector The selector, the restricted + XPath pattern found in W3C XML Schema 1.1 for uniqueness + contraints. Apart from restricting the syntax, the type check stage + for the expression assumes a sequence of nodes to be the focus. + \omitvalue XmlSchema11IdentityConstraintField The field, the restricted + XPath pattern found in W3C XML Schema 1.1 for uniqueness + contraints. Apart from restricting the syntax, the type check stage + for the expression assumes a sequence of nodes to be the focus. + \omitvalue XPath20 Signifies XPath 2.0. Has no effect in the public API, it's + used internally. As With XmlSchema11IdentityConstraintSelector and + XmlSchema11IdentityConstraintField, the type check stage + for the expression assumes a sequence of nodes to be the focus. \sa setQuery() */ diff --git a/src/xmlpatterns/api/qxmlquery.h b/src/xmlpatterns/api/qxmlquery.h index 138819c..c9f949e 100644 --- a/src/xmlpatterns/api/qxmlquery.h +++ b/src/xmlpatterns/api/qxmlquery.h @@ -71,6 +71,8 @@ namespace QPatternistSDK namespace QPatternist { + class XsdSchemaParser; + class XsdValidatingInstanceReader; class VariableLoader; }; @@ -79,8 +81,11 @@ class Q_XMLPATTERNS_EXPORT QXmlQuery public: enum QueryLanguage { - XQuery10 = 1, - XSLT20 = 2 + XQuery10 = 1, + XSLT20 = 2, + XmlSchema11IdentityConstraintSelector = 1024, + XmlSchema11IdentityConstraintField = 2048, + XPath20 = 4096 }; QXmlQuery(); @@ -135,6 +140,8 @@ private: friend class QXmlName; friend class QXmlSerializer; friend class QPatternistSDK::TestCase; + friend class QPatternist::XsdSchemaParser; + friend class QPatternist::XsdValidatingInstanceReader; friend class QPatternist::VariableLoader; template friend bool setFocusHelper(QXmlQuery *const queryInstance, const TInputType &focusValue); diff --git a/src/xmlpatterns/api/qxmlquery_p.h b/src/xmlpatterns/api/qxmlquery_p.h index c8ed441..7f58f97 100644 --- a/src/xmlpatterns/api/qxmlquery_p.h +++ b/src/xmlpatterns/api/qxmlquery_p.h @@ -142,13 +142,10 @@ public: if(!m_functionFactory) { - if(queryLanguage == QXmlQuery::XQuery10) - m_functionFactory = QPatternist::FunctionFactoryCollection::xpath20Factory(namePool.d); - else - { - Q_ASSERT(queryLanguage == QXmlQuery::XSLT20); + if(queryLanguage == QXmlQuery::XSLT20) m_functionFactory = QPatternist::FunctionFactoryCollection::xslt20Factory(namePool.d); - } + else + m_functionFactory = QPatternist::FunctionFactoryCollection::xpath20Factory(namePool.d); } const QPatternist::GenericStaticContext::Ptr genericStaticContext(new QPatternist::GenericStaticContext(namePool.d, @@ -164,6 +161,14 @@ public: if(!contextItem.isNull()) m_staticContext = QPatternist::StaticContext::Ptr(new QPatternist::StaticFocusContext(QPatternist::AtomicValue::qtToXDMType(contextItem), m_staticContext)); + else if( queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintField + || queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintSelector + || queryLanguage == QXmlQuery::XPath20) + m_staticContext = QPatternist::StaticContext::Ptr(new QPatternist::StaticFocusContext(QPatternist::BuiltinTypes::node, m_staticContext)); + + for (int i = 0; i < m_additionalNamespaceBindings.count(); ++i) { + m_staticContext->namespaceBindings()->addBinding(m_additionalNamespaceBindings.at(i)); + } return m_staticContext; } @@ -278,6 +283,11 @@ public: return m_expr; } + inline void addAdditionalNamespaceBinding(const QXmlName &binding) + { + m_additionalNamespaceBindings.append(binding); + } + QXmlNamePool namePool; QPointer messageHandler; /** @@ -321,6 +331,8 @@ public: QPatternist::SequenceType::Ptr m_requiredType; QPatternist::FunctionFactory::Ptr m_functionFactory; QPatternist::NetworkAccessDelegator::Ptr m_networkAccessDelegator; + + QList m_additionalNamespaceBindings; }; QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qxmlschema.cpp b/src/xmlpatterns/api/qxmlschema.cpp new file mode 100644 index 0000000..55b96cd --- /dev/null +++ b/src/xmlpatterns/api/qxmlschema.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** 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 "qxmlschema.h" +#include "qxmlschema_p.h" + +#include +#include + +/*! + \class QXmlSchema + + \brief The QXmlSchema class provides loading and validation of a W3C XML Schema. + + \reentrant + \since 4.X + \ingroup xml-tools + + The QXmlSchema class loads, compiles and validates W3C XML Schema files + that can be used further for validation of XML instance documents via + \l{QXmlSchemaValidator}. +*/ + +/*! + Constructs an invalid, empty schema that cannot be used until + setSchema() is called. + */ +QXmlSchema::QXmlSchema() + : d(new QXmlSchemaPrivate(QXmlNamePool())) +{ +} + +/*! + Constructs a QXmlSchema that is a copy of \a other. The new + instance will share resources with the existing schema + to the extent possible. + */ +QXmlSchema::QXmlSchema(const QXmlSchema &other) + : d(other.d) +{ +} + +/*! + Destroys this QXmlSchema. + */ +QXmlSchema::~QXmlSchema() +{ +} + +/*! + Sets this QXmlSchema to a schema loaded from the \a source + URI. + */ +void QXmlSchema::load(const QUrl &source) +{ + d->load(source, QString()); +} + +/*! + Sets this QXmlSchema to a schema read from the \a source + device. The device must have been opened with at least + QIODevice::ReadOnly. + + \a documentUri represents the schema obtained from the \a source + device. It is the base URI of the schema, that is used + internally to resolve relative URIs that appear in the schema, and + for message reporting. + + If \a source is \c null or not readable, or if \a documentUri is not + a valid URI, behavior is undefined. + \sa isValid() + */ +void QXmlSchema::load(QIODevice *source, const QUrl &documentUri) +{ + d->load(source, documentUri, QString()); +} + +/*! + Sets this QXmlSchema to a schema read from the \a data + + \a documentUri represents the schema obtained from the \a data. + It is the base URI of the schema, that is used internally to + resolve relative URIs that appear in the schema, and + for message reporting. + + If \a documentUri is not a valid URI, behavior is undefined. + \sa isValid() + */ +void QXmlSchema::load(const QByteArray &data, const QUrl &documentUri) +{ + d->load(data, documentUri, QString()); +} + +/*! + Returns true if this schema is valid. Examples of invalid schemas + are ones that contain syntax errors or that do not conform the + W3C XML Schema specification. + */ +bool QXmlSchema::isValid() const +{ + return d->isValid(); +} + +/*! + Returns the name pool used by this QXmlSchema for constructing \l + {QXmlName} {names}. There is no setter for the name pool, because + mixing name pools causes errors due to name confusion. + */ +QXmlNamePool QXmlSchema::namePool() const +{ + return d->namePool(); +} + +/*! + Returns the document URI of the schema or an empty URI if no + schema has been set. + */ +QUrl QXmlSchema::documentUri() const +{ + return d->documentUri(); +} + +/*! + Changes the \l {QAbstractMessageHandler}{message handler} for this + QXmlSchema to \a handler. The schema sends all compile and + validation messages to this message handler. QXmlSchema does not take + ownership of \a handler. + + Normally, the default message handler is sufficient. It writes + compile and validation messages to \e stderr. The default message + handler includes color codes if \e stderr can render colors. + + When QXmlSchema calls QAbstractMessageHandler::message(), + the arguments are as follows: + + \table + \header + \o message() argument + \o Semantics + \row + \o QtMsgType type + \o Only QtWarningMsg and QtFatalMsg are used. The former + identifies a warning, while the latter identifies an error. + \row + \o const QString & description + \o An XHTML document which is the actual message. It is translated + into the current language. + \row + \o const QUrl &identifier + \o Identifies the error with a URI, where the fragment is + the error code, and the rest of the URI is the error namespace. + \row + \o const QSourceLocation & sourceLocation + \o Identifies where the error occurred. + \endtable + + */ +void QXmlSchema::setMessageHandler(QAbstractMessageHandler *handler) +{ + d->setMessageHandler(handler); +} + +/*! + Returns the message handler that handles compile and validation + messages for this QXmlSchema. + */ +QAbstractMessageHandler *QXmlSchema::messageHandler() const +{ + return d->messageHandler(); +} + +/*! + Sets the URI resolver to \a resolver. QXmlSchema does not take + ownership of \a resolver. + + \sa uriResolver() + */ +void QXmlSchema::setUriResolver(QAbstractUriResolver *resolver) +{ + d->setUriResolver(resolver); +} + +/*! + Returns the schema's URI resolver. If no URI resolver has been set, + QtXmlPatterns will use the URIs in queries as they are. + + The URI resolver provides a level of abstraction, or \e{polymorphic + URIs}. A resolver can rewrite \e{logical} URIs to physical ones, or + it can translate obsolete or invalid URIs to valid ones. + + When QtXmlPatterns calls QAbstractUriResolver::resolve() the + absolute URI is the URI mandated by the schema specification, and the + relative URI is the URI specified by the user. + + \sa setUriResolver() + */ +QAbstractUriResolver *QXmlSchema::uriResolver() const +{ + return d->uriResolver(); +} + +/*! + Sets the network manager to \a manager. + QXmlSchema does not take ownership of \a manager. + + \sa networkAccessManager() + */ +void QXmlSchema::setNetworkAccessManager(QNetworkAccessManager *manager) +{ + d->setNetworkAccessManager(manager); +} + +/*! + Returns the network manager, or 0 if it has not been set. + + \sa setNetworkAccessManager() + */ +QNetworkAccessManager *QXmlSchema::networkAccessManager() const +{ + return d->networkAccessManager(); +} diff --git a/src/xmlpatterns/api/qxmlschema.h b/src/xmlpatterns/api/qxmlschema.h new file mode 100644 index 0000000..225cce2 --- /dev/null +++ b/src/xmlpatterns/api/qxmlschema.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$ +** +****************************************************************************/ + +#ifndef QXMLSCHEMA_H +#define QXMLSCHEMA_H + +#include +#include + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +QT_MODULE(XmlPatterns) + +class QAbstractMessageHandler; +class QAbstractUriResolver; +class QIODevice; +class QNetworkAccessManager; +class QUrl; +class QXmlNamePool; +class QXmlSchemaPrivate; + +class Q_XMLPATTERNS_EXPORT QXmlSchema +{ + friend class QXmlSchemaValidatorPrivate; + + public: + QXmlSchema(); + QXmlSchema(const QXmlSchema &other); + ~QXmlSchema(); + + void load(const QUrl &source); + void load(QIODevice *source, const QUrl &documentUri); + void load(const QByteArray &data, const QUrl &documentUri); + + bool isValid() const; + + QXmlNamePool namePool() const; + QUrl documentUri() const; + + void setMessageHandler(QAbstractMessageHandler *handler); + QAbstractMessageHandler *messageHandler() const; + + void setUriResolver(QAbstractUriResolver *resolver); + QAbstractUriResolver *uriResolver() const; + + void setNetworkAccessManager(QNetworkAccessManager *networkmanager); + QNetworkAccessManager *networkAccessManager() const; + + private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qxmlschema_p.cpp b/src/xmlpatterns/api/qxmlschema_p.cpp new file mode 100644 index 0000000..ebcccee --- /dev/null +++ b/src/xmlpatterns/api/qxmlschema_p.cpp @@ -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$ +** +****************************************************************************/ + +#include "qacceltreeresourceloader_p.h" +#include "qxmlschema.h" +#include "qxmlschema_p.h" + +#include +#include +#include + +QXmlSchemaPrivate::QXmlSchemaPrivate(const QXmlNamePool &namePool) + : m_namePool(namePool) + , m_userMessageHandler(0) + , m_uriResolver(0) + , m_userNetworkAccessManager(0) + , m_schemaContext(new QPatternist::XsdSchemaContext(m_namePool.d)) + , m_schemaParserContext(new QPatternist::XsdSchemaParserContext(m_namePool.d, m_schemaContext)) + , m_schemaIsValid(false) +{ + m_networkAccessManager = new QPatternist::ReferenceCountedValue(new QNetworkAccessManager()); + m_messageHandler = new QPatternist::ReferenceCountedValue(new QPatternist::ColoringMessageHandler()); +} + +QXmlSchemaPrivate::QXmlSchemaPrivate(const QPatternist::XsdSchemaContext::Ptr &schemaContext) + : m_namePool(QXmlNamePool(schemaContext->namePool().data())) + , m_userMessageHandler(0) + , m_uriResolver(0) + , m_userNetworkAccessManager(0) + , m_schemaContext(schemaContext) + , m_schemaParserContext(new QPatternist::XsdSchemaParserContext(m_namePool.d, m_schemaContext)) + , m_schemaIsValid(false) +{ + m_networkAccessManager = new QPatternist::ReferenceCountedValue(new QNetworkAccessManager()); + m_messageHandler = new QPatternist::ReferenceCountedValue(new QPatternist::ColoringMessageHandler()); +} + +QXmlSchemaPrivate::QXmlSchemaPrivate(const QXmlSchemaPrivate &other) + : QSharedData(other) +{ + m_namePool = other.m_namePool; + m_userMessageHandler = other.m_userMessageHandler; + m_uriResolver = other.m_uriResolver; + m_userNetworkAccessManager = other.m_userNetworkAccessManager; + m_messageHandler = other.m_messageHandler; + m_networkAccessManager = other.m_networkAccessManager; + + m_schemaContext = other.m_schemaContext; + m_schemaParserContext = other.m_schemaParserContext; + m_schemaIsValid = other.m_schemaIsValid; + m_documentUri = other.m_documentUri; +} + +void QXmlSchemaPrivate::load(const QUrl &source, const QString &targetNamespace) +{ + m_documentUri = source; + + m_schemaContext->setMessageHandler(messageHandler()); + m_schemaContext->setUriResolver(uriResolver()); + m_schemaContext->setNetworkAccessManager(networkAccessManager()); + + const QPatternist::AutoPtr reply(QPatternist::AccelTreeResourceLoader::load(source, m_schemaContext->networkAccessManager(), + m_schemaContext, QPatternist::AccelTreeResourceLoader::ContinueOnError)); + if (reply) + load(reply.data(), source, targetNamespace); +} + +void QXmlSchemaPrivate::load(const QByteArray &data, const QUrl &documentUri, const QString &targetNamespace) +{ + QByteArray localData(data); + + QBuffer buffer(&localData); + buffer.open(QIODevice::ReadOnly); + + load(&buffer, documentUri, targetNamespace); +} + +void QXmlSchemaPrivate::load(QIODevice *source, const QUrl &documentUri, const QString &targetNamespace) +{ + m_schemaParserContext = QPatternist::XsdSchemaParserContext::Ptr(new QPatternist::XsdSchemaParserContext(m_namePool.d, m_schemaContext)); + m_schemaIsValid = false; + + if (!source) { + qWarning("A null QIODevice pointer cannot be passed."); + return; + } + + if (!source->isReadable()) { + qWarning("The device must be readable."); + return; + } + + m_documentUri = documentUri; + m_schemaContext->setMessageHandler(messageHandler()); + m_schemaContext->setUriResolver(uriResolver()); + m_schemaContext->setNetworkAccessManager(networkAccessManager()); + + QPatternist::XsdSchemaParser parser(m_schemaContext, m_schemaParserContext, source); + parser.setDocumentURI(documentUri); + parser.setTargetNamespace(targetNamespace); + + try { + parser.parse(); + m_schemaParserContext->resolver()->resolve(); + + m_schemaIsValid = true; + } catch (QPatternist::Exception exception) { + m_schemaIsValid = false; + } +} + +bool QXmlSchemaPrivate::isValid() const +{ + return m_schemaIsValid; +} + +QXmlNamePool QXmlSchemaPrivate::namePool() const +{ + return m_namePool; +} + +QUrl QXmlSchemaPrivate::documentUri() const +{ + return m_documentUri; +} + +void QXmlSchemaPrivate::setMessageHandler(QAbstractMessageHandler *handler) +{ + m_userMessageHandler = handler; +} + +QAbstractMessageHandler *QXmlSchemaPrivate::messageHandler() const +{ + if (m_userMessageHandler) + return m_userMessageHandler; + + return m_messageHandler.data()->value; +} + +void QXmlSchemaPrivate::setUriResolver(QAbstractUriResolver *resolver) +{ + m_uriResolver = resolver; +} + +QAbstractUriResolver *QXmlSchemaPrivate::uriResolver() const +{ + return m_uriResolver; +} + +void QXmlSchemaPrivate::setNetworkAccessManager(QNetworkAccessManager *networkmanager) +{ + m_userNetworkAccessManager = networkmanager; +} + +QNetworkAccessManager *QXmlSchemaPrivate::networkAccessManager() const +{ + if (m_userNetworkAccessManager) + return m_userNetworkAccessManager; + + return m_networkAccessManager.data()->value; +} diff --git a/src/xmlpatterns/api/qxmlschema_p.h b/src/xmlpatterns/api/qxmlschema_p.h new file mode 100644 index 0000000..e625f1e --- /dev/null +++ b/src/xmlpatterns/api/qxmlschema_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 QXMLSCHEMA_P_H +#define QXMLSCHEMA_P_H + +#include "qabstractmessagehandler.h" +#include "qabstracturiresolver.h" +#include "qautoptr_p.h" +#include "qcoloringmessagehandler_p.h" +#include "qreferencecountedvalue_p.h" + +#include "qxsdschemacontext_p.h" +#include "qxsdschemaparser_p.h" +#include "qxsdschemaparsercontext_p.h" + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlSchemaPrivate : public QSharedData +{ + public: + QXmlSchemaPrivate(const QXmlNamePool &namePool); + QXmlSchemaPrivate(const QPatternist::XsdSchemaContext::Ptr &schemaContext); + QXmlSchemaPrivate(const QXmlSchemaPrivate &other); + + void load(const QUrl &source, const QString &targetNamespace); + void load(QIODevice *source, const QUrl &documentUri, const QString &targetNamespace); + void load(const QByteArray &data, const QUrl &documentUri, const QString &targetNamespace); + bool isValid() const; + QXmlNamePool namePool() const; + QUrl documentUri() const; + void setMessageHandler(QAbstractMessageHandler *handler); + QAbstractMessageHandler *messageHandler() const; + void setUriResolver(QAbstractUriResolver *resolver); + QAbstractUriResolver *uriResolver() const; + void setNetworkAccessManager(QNetworkAccessManager *networkmanager); + QNetworkAccessManager *networkAccessManager() const; + + QXmlNamePool m_namePool; + QAbstractMessageHandler* m_userMessageHandler; + QAbstractUriResolver* m_uriResolver; + QNetworkAccessManager* m_userNetworkAccessManager; + QPatternist::ReferenceCountedValue::Ptr m_messageHandler; + QPatternist::ReferenceCountedValue::Ptr m_networkAccessManager; + + QPatternist::XsdSchemaContext::Ptr m_schemaContext; + QPatternist::XsdSchemaParserContext::Ptr m_schemaParserContext; + bool m_schemaIsValid; + QUrl m_documentUri; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qxmlschemavalidator.cpp b/src/xmlpatterns/api/qxmlschemavalidator.cpp new file mode 100644 index 0000000..aa80537 --- /dev/null +++ b/src/xmlpatterns/api/qxmlschemavalidator.cpp @@ -0,0 +1,264 @@ +/**************************************************************************** +** +** 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 "qxmlschemavalidator.h" +#include "qxmlschemavalidator_p.h" + +#include "qacceltreeresourceloader_p.h" +#include "qxmlschema.h" +#include "qxmlschema_p.h" +#include "qxsdvalidatinginstancereader_p.h" + +#include +#include +#include + +/*! + \class QXmlSchemaValidator + + \brief The QXmlSchemaValidator class validates XML instance documents against a W3C XML Schema. + + \reentrant + \since 4.X + \ingroup xml-tools + + The QXmlSchemaValidator class loads, parses an XML instance document and validates it + against a W3C XML Schema that has been compiled with \l{QXmlSchema}. +*/ + +/*! + Constructs a schema validator that will use \a schema for validation. + */ +QXmlSchemaValidator::QXmlSchemaValidator(const QXmlSchema &schema) + : d(new QXmlSchemaValidatorPrivate(schema)) +{ +} + +/*! + Destroys this QXmlSchemaValidator. + */ +QXmlSchemaValidator::~QXmlSchemaValidator() +{ + delete d; +} + +/*! + Sets the \a schema that shall be used for further validation. + */ +void QXmlSchemaValidator::setSchema(const QXmlSchema &schema) +{ + d->setSchema(schema); +} + +/*! + Validates the XML instance document read from \a data with the + given \a documentUri against the schema. + + Returns \c true if the XML instance document is valid according the + schema, \c false otherwise. + */ +bool QXmlSchemaValidator::validate(const QByteArray &data, const QUrl &documentUri) +{ + QByteArray localData(data); + + QBuffer buffer(&localData); + buffer.open(QIODevice::ReadOnly); + + return validate(&buffer, documentUri); +} + +/*! + Validates the XML instance document read from \a source against the schema. + + Returns \c true if the XML instance document is valid according the + schema, \c false otherwise. + */ +bool QXmlSchemaValidator::validate(const QUrl &source) +{ + d->m_context->setMessageHandler(messageHandler()); + d->m_context->setUriResolver(uriResolver()); + d->m_context->setNetworkAccessManager(networkAccessManager()); + + const QPatternist::AutoPtr reply(QPatternist::AccelTreeResourceLoader::load(source, d->m_context->networkAccessManager(), + d->m_context, QPatternist::AccelTreeResourceLoader::ContinueOnError)); + if (reply) + return validate(reply.data(), source); + else + return false; +} + +/*! + Validates the XML instance document read from \a source with the + given \a documentUri against the schema. + + Returns \c true if the XML instance document is valid according the + schema, \c false otherwise. + */ +bool QXmlSchemaValidator::validate(QIODevice *source, const QUrl &documentUri) +{ + if (!source) { + qWarning("A null QIODevice pointer cannot be passed."); + return false; + } + + if (!source->isReadable()) { + qWarning("The device must be readable."); + return false; + } + + d->m_context->setMessageHandler(messageHandler()); + d->m_context->setUriResolver(uriResolver()); + d->m_context->setNetworkAccessManager(networkAccessManager()); + + QPatternist::NetworkAccessDelegator::Ptr delegator(new QPatternist::NetworkAccessDelegator(d->m_context->networkAccessManager(), + d->m_context->networkAccessManager())); + + QPatternist::AccelTreeResourceLoader loader(d->m_context->namePool(), delegator, QPatternist::AccelTreeBuilder::SourceLocationsFeature); + + QPatternist::Item item; + try { + item = loader.openDocument(source, documentUri, d->m_context); + } catch (QPatternist::Exception exception) { + return false; + } + + QXmlNodeModelIndex index = item.asNode(); + const QAbstractXmlNodeModel *model = item.asNode().model(); + + QPatternist::XsdValidatedXmlNodeModel *validatedModel = new QPatternist::XsdValidatedXmlNodeModel(model); + + QPatternist::XsdValidatingInstanceReader reader(validatedModel, documentUri, d->m_context); + if (d->m_schema) + reader.addSchema(d->m_schema, d->m_schemaDocumentUri); + try { + reader.read(); + } catch (QPatternist::Exception exception) { + return false; + } + + return true; +} + +/*! + Returns the name pool used by this QXmlSchemaValidator for constructing \l + {QXmlName} {names}. There is no setter for the name pool, because + mixing name pools causes errors due to name confusion. + */ +QXmlNamePool QXmlSchemaValidator::namePool() const +{ + return d->m_namePool; +} + +/*! + Changes the \l {QAbstractMessageHandler}{message handler} for this + QXmlSchemaValidator to \a handler. The schema validator sends all parsing and + validation messages to this message handler. QXmlSchemaValidator does not take + ownership of \a handler. + + Normally, the default message handler is sufficient. It writes + compile and validation messages to \e stderr. The default message + handler includes color codes if \e stderr can render colors. + + When QXmlSchemaValidator calls QAbstractMessageHandler::message(), + the arguments are as follows: + + \table + \header + \o message() argument + \o Semantics + \row + \o QtMsgType type + \o Only QtWarningMsg and QtFatalMsg are used. The former + identifies a warning, while the latter identifies an error. + \row + \o const QString & description + \o An XHTML document which is the actual message. It is translated + into the current language. + \row + \o const QUrl &identifier + \o Identifies the error with a URI, where the fragment is + the error code, and the rest of the URI is the error namespace. + \row + \o const QSourceLocation & sourceLocation + \o Identifies where the error occurred. + \endtable + + */ +void QXmlSchemaValidator::setMessageHandler(QAbstractMessageHandler *handler) +{ + d->m_userMessageHandler = handler; +} + +/*! + Returns the message handler that handles parsing and validation + messages for this QXmlSchemaValidator. + */ +QAbstractMessageHandler *QXmlSchemaValidator::messageHandler() const +{ + if (d->m_userMessageHandler) + return d->m_userMessageHandler; + + return d->m_messageHandler.data()->value; +} + +/*! + Sets the URI resolver to \a resolver. QXmlSchemaValidator does not take + ownership of \a resolver. + + \sa uriResolver() + */ +void QXmlSchemaValidator::setUriResolver(QAbstractUriResolver *resolver) +{ + d->m_uriResolver = resolver; +} + +/*! + Returns the schema's URI resolver. If no URI resolver has been set, + QtXmlPatterns will use the URIs in queries as they are. + + The URI resolver provides a level of abstraction, or \e{polymorphic + URIs}. A resolver can rewrite \e{logical} URIs to physical ones, or + it can translate obsolete or invalid URIs to valid ones. + + When QtXmlPatterns calls QAbstractUriResolver::resolve() the + absolute URI is the URI mandated by the schema specification, and the + relative URI is the URI specified by the user. + + \sa setUriResolver() + */ +QAbstractUriResolver *QXmlSchemaValidator::uriResolver() const +{ + return d->m_uriResolver; +} + +/*! + Sets the network manager to \a manager. + QXmlSchemaValidator does not take ownership of \a manager. + + \sa networkAccessManager() + */ +void QXmlSchemaValidator::setNetworkAccessManager(QNetworkAccessManager *manager) +{ + d->m_userNetworkAccessManager = manager; +} + +/*! + Returns the network manager, or 0 if it has not been set. + + \sa setNetworkAccessManager() + */ +QNetworkAccessManager *QXmlSchemaValidator::networkAccessManager() const +{ + if (d->m_userNetworkAccessManager) + return d->m_userNetworkAccessManager; + + return d->m_networkAccessManager.data()->value; +} diff --git a/src/xmlpatterns/api/qxmlschemavalidator.h b/src/xmlpatterns/api/qxmlschemavalidator.h new file mode 100644 index 0000000..e643995 --- /dev/null +++ b/src/xmlpatterns/api/qxmlschemavalidator.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QXMLSCHEMAVALIDATOR_H +#define QXMLSCHEMAVALIDATOR_H + +#include + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +QT_MODULE(XmlPatterns) + +class QAbstractMessageHandler; +class QAbstractUriResolver; +class QIODevice; +class QNetworkAccessManager; +class QUrl; +class QXmlNamePool; +class QXmlSchema; +class QXmlSchemaValidatorPrivate; + +class Q_XMLPATTERNS_EXPORT QXmlSchemaValidator +{ + public: + QXmlSchemaValidator(const QXmlSchema &schema); + ~QXmlSchemaValidator(); + + void setSchema(const QXmlSchema &schema); + + bool validate(const QUrl &source); + bool validate(QIODevice *source, const QUrl &documentUri); + bool validate(const QByteArray &data, const QUrl &documentUri); + + QXmlNamePool namePool() const; + + void setMessageHandler(QAbstractMessageHandler *handler); + QAbstractMessageHandler *messageHandler() const; + + void setUriResolver(QAbstractUriResolver *resolver); + QAbstractUriResolver *uriResolver() const; + + void setNetworkAccessManager(QNetworkAccessManager *networkmanager); + QNetworkAccessManager *networkAccessManager() const; + + private: + QXmlSchemaValidatorPrivate* const d; + + Q_DISABLE_COPY(QXmlSchemaValidator) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qxmlschemavalidator_p.h b/src/xmlpatterns/api/qxmlschemavalidator_p.h new file mode 100644 index 0000000..0990f73 --- /dev/null +++ b/src/xmlpatterns/api/qxmlschemavalidator_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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 QXMLSCHEMAVALIDATOR_P_H +#define QXMLSCHEMAVALIDATOR_P_H + +#include "qabstractmessagehandler.h" +#include "qabstracturiresolver.h" +#include "qautoptr_p.h" +#include "qcoloringmessagehandler_p.h" +#include "qxmlschema.h" +#include "qxmlschema_p.h" + +#include "qxsdschemacontext_p.h" +#include "qxsdschema_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlSchemaValidatorPrivate +{ +public: + QXmlSchemaValidatorPrivate(const QXmlSchema &schema) + : m_namePool(schema.namePool()) + , m_userMessageHandler(0) + , m_uriResolver(0) + , m_userNetworkAccessManager(0) + { + setSchema(schema); + + const QXmlSchemaPrivate *p = schema.d; + + // initialize the environment properties with the ones from the schema + + if (p->m_userNetworkAccessManager) // schema has user defined network access manager + m_userNetworkAccessManager = p->m_userNetworkAccessManager; + else + m_networkAccessManager = p->m_networkAccessManager; + + if (p->m_userMessageHandler) // schema has user defined message handler + m_userMessageHandler = p->m_userMessageHandler; + else + m_messageHandler = p->m_messageHandler; + + m_uriResolver = p->m_uriResolver; + } + + void setSchema(const QXmlSchema &schema) + { + // use same name pool as the schema + m_namePool = schema.namePool(); + m_schema = schema.d->m_schemaParserContext->schema(); + m_schemaDocumentUri = schema.documentUri(); + + // create a new schema context + m_context = QPatternist::XsdSchemaContext::Ptr(new QPatternist::XsdSchemaContext(m_namePool.d)); + m_context->m_schemaTypeFactory = schema.d->m_schemaContext->m_schemaTypeFactory; + m_context->m_builtinTypesFacetList = schema.d->m_schemaContext->m_builtinTypesFacetList; + } + + QXmlNamePool m_namePool; + QAbstractMessageHandler* m_userMessageHandler; + QAbstractUriResolver* m_uriResolver; + QNetworkAccessManager* m_userNetworkAccessManager; + QPatternist::ReferenceCountedValue::Ptr m_messageHandler; + QPatternist::ReferenceCountedValue::Ptr m_networkAccessManager; + + QPatternist::XsdSchemaContext::Ptr m_context; + QPatternist::XsdSchema::Ptr m_schema; + QUrl m_schemaDocumentUri; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/common.pri b/src/xmlpatterns/common.pri index 2573a26..27253d8 100644 --- a/src/xmlpatterns/common.pri +++ b/src/xmlpatterns/common.pri @@ -10,6 +10,7 @@ INCLUDEPATH += $$PWD/acceltree \ $$PWD/iterators \ $$PWD/janitors \ $$PWD/parser \ + $$PWD/schema \ $$PWD/type \ $$PWD/utils diff --git a/src/xmlpatterns/data/data.pri b/src/xmlpatterns/data/data.pri index 99591d4..ccfed42 100644 --- a/src/xmlpatterns/data/data.pri +++ b/src/xmlpatterns/data/data.pri @@ -1,8 +1,8 @@ HEADERS += $$PWD/qabstractdatetime_p.h \ $$PWD/qabstractduration_p.h \ $$PWD/qabstractfloatcasters_p.h \ - $$PWD/qabstractfloat_p.h \ $$PWD/qabstractfloatmathematician_p.h \ + $$PWD/qabstractfloat_p.h \ $$PWD/qanyuri_p.h \ $$PWD/qatomiccaster_p.h \ $$PWD/qatomiccasters_p.h \ @@ -14,8 +14,8 @@ HEADERS += $$PWD/qabstractdatetime_p.h \ $$PWD/qbase64binary_p.h \ $$PWD/qboolean_p.h \ $$PWD/qcommonvalues_p.h \ + $$PWD/qcomparisonfactory_p.h \ $$PWD/qdate_p.h \ - $$PWD/qschemadatetime_p.h \ $$PWD/qdaytimeduration_p.h \ $$PWD/qdecimal_p.h \ $$PWD/qderivedinteger_p.h \ @@ -24,19 +24,21 @@ HEADERS += $$PWD/qabstractdatetime_p.h \ $$PWD/qgday_p.h \ $$PWD/qgmonthday_p.h \ $$PWD/qgmonth_p.h \ - $$PWD/qgyear_p.h \ $$PWD/qgyearmonth_p.h \ + $$PWD/qgyear_p.h \ $$PWD/qhexbinary_p.h \ $$PWD/qinteger_p.h \ $$PWD/qitem_p.h \ $$PWD/qnodebuilder_p.h \ - $$PWD/qschemanumeric_p.h \ $$PWD/qqnamevalue_p.h \ $$PWD/qresourceloader_p.h \ - $$PWD/qsorttuple.cpp \ + $$PWD/qschemadatetime_p.h \ + $$PWD/qschemanumeric_p.h \ $$PWD/qschematime_p.h \ + $$PWD/qsorttuple.cpp \ $$PWD/quntypedatomic_p.h \ $$PWD/qvalidationerror_p.h \ + $$PWD/qvaluefactory_p.h \ $$PWD/qyearmonthduration_p.h SOURCES += $$PWD/qabstractdatetime.cpp \ @@ -53,8 +55,8 @@ SOURCES += $$PWD/qabstractdatetime.cpp \ $$PWD/qbase64binary.cpp \ $$PWD/qboolean.cpp \ $$PWD/qcommonvalues.cpp \ + $$PWD/qcomparisonfactory.cpp \ $$PWD/qdate.cpp \ - $$PWD/qschemadatetime.cpp \ $$PWD/qdaytimeduration.cpp \ $$PWD/qdecimal.cpp \ $$PWD/qduration.cpp \ @@ -68,11 +70,13 @@ SOURCES += $$PWD/qabstractdatetime.cpp \ $$PWD/qitem.cpp \ $$PWD/qnodebuilder.cpp \ $$PWD/qnodemodel.cpp \ - $$PWD/qschemanumeric.cpp \ $$PWD/qqnamevalue.cpp \ $$PWD/qresourceloader.cpp \ - $$PWD/qsorttuple.cpp \ + $$PWD/qschemadatetime.cpp \ + $$PWD/qschemanumeric.cpp \ $$PWD/qschematime.cpp \ + $$PWD/qsorttuple.cpp \ $$PWD/quntypedatomic.cpp \ $$PWD/qvalidationerror.cpp \ + $$PWD/qvaluefactory.cpp \ $$PWD/qyearmonthduration.cpp diff --git a/src/xmlpatterns/data/qcomparisonfactory.cpp b/src/xmlpatterns/data/qcomparisonfactory.cpp new file mode 100644 index 0000000..7fe298b --- /dev/null +++ b/src/xmlpatterns/data/qcomparisonfactory.cpp @@ -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$ +** +****************************************************************************/ + +#include "qatomiccomparators_p.h" +#include "qatomicstring_p.h" +#include "qcomparisonplatform_p.h" +#include "qvaluefactory_p.h" + +#include "qcomparisonfactory_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +/** + * @short Helper class for ComparisonFactory::fromLexical() which exposes + * CastingPlatform appropriately. + * + * @relates ComparisonFactory + */ +class PerformComparison : public ComparisonPlatform + , public SourceLocationReflection +{ +public: + PerformComparison(const SourceLocationReflection *const sourceLocationReflection, + const AtomicComparator::Operator op) : m_sourceReflection(sourceLocationReflection) + , m_operator(op) + { + Q_ASSERT(m_sourceReflection); + } + + bool operator()(const AtomicValue::Ptr &operand1, + const AtomicValue::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context) + { + const ItemType::Ptr asItemType((AtomicType::Ptr(type))); + + /* One area where the Query Transform world differs from the Schema + * world is that @c xs:duration is not considedered comparable, because + * it's according to Schema is partially comparable. This means + * ComparisonPlatform::fetchComparator() flags it as impossible, and + * hence we need to override that. + * + * SchemaType::wxsTypeMatches() will return true for sub-types of @c + * xs:duration as well, but that's ok since AbstractDurationComparator + * works for them too. */ + if(BuiltinTypes::xsDuration->wxsTypeMatches(type)) + prepareComparison(AtomicComparator::Ptr(new AbstractDurationComparator())); + else if (BuiltinTypes::xsGYear->wxsTypeMatches(type) || + BuiltinTypes::xsGYearMonth->wxsTypeMatches(type) || + BuiltinTypes::xsGMonth->wxsTypeMatches(type) || + BuiltinTypes::xsGMonthDay->wxsTypeMatches(type) || + BuiltinTypes::xsGDay->wxsTypeMatches(type)) + prepareComparison(AtomicComparator::Ptr(new AbstractDateTimeComparator())); + else + prepareComparison(fetchComparator(asItemType, asItemType, context)); + + return flexibleCompare(operand1, operand2, context); + } + + const SourceLocationReflection *actualReflection() const + { + return m_sourceReflection; + } + + AtomicComparator::Operator operatorID() const + { + return m_operator; + } + +private: + const SourceLocationReflection *const m_sourceReflection; + const AtomicComparator::Operator m_operator; +}; + +bool ComparisonFactory::compare(const AtomicValue::Ptr &operand1, + const AtomicComparator::Operator op, + const AtomicValue::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection) +{ + Q_ASSERT(operand1); + Q_ASSERT(operand2); + Q_ASSERT(context); + Q_ASSERT(sourceLocationReflection); + Q_ASSERT(type); + Q_ASSERT_X(type->category() == SchemaType::SimpleTypeAtomic, Q_FUNC_INFO, + "We can only compare atomic values."); + + return PerformComparison(sourceLocationReflection, op)(operand1, operand2, type, context); +} + +bool ComparisonFactory::constructAndCompare(const DerivedString::Ptr &operand1, + const AtomicComparator::Operator op, + const DerivedString::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection) +{ + Q_ASSERT(operand1); + Q_ASSERT(operand2); + Q_ASSERT(context); + Q_ASSERT(sourceLocationReflection); + Q_ASSERT(type); + Q_ASSERT_X(type->category() == SchemaType::SimpleTypeAtomic, Q_FUNC_INFO, + "We can only compare atomic values."); + + const AtomicValue::Ptr value1 = ValueFactory::fromLexical(operand1->stringValue(), type, context, sourceLocationReflection); + const AtomicValue::Ptr value2 = ValueFactory::fromLexical(operand2->stringValue(), type, context, sourceLocationReflection); + + return compare(value1, op, value2, type, context, sourceLocationReflection); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/data/qcomparisonfactory_p.h b/src/xmlpatterns/data/qcomparisonfactory_p.h new file mode 100644 index 0000000..09fc50b --- /dev/null +++ b/src/xmlpatterns/data/qcomparisonfactory_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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_ComparisonFactory_H +#define Patternist_ComparisonFactory_H + +#include "qatomiccomparator_p.h" +#include "qderivedstring_p.h" +#include "qitem_p.h" +#include "qreportcontext_p.h" +#include "qschematype_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Provides compare(), which is a high-level helper function for + * comparing atomic values. + * + * This class wraps the helper class ComparisonPlatform with a more specific, + * high-level API. + * + * @see ComparisonPlatform + * @author Frans Englich + * @ingroup Patternist_schema + */ + class ComparisonFactory + { + public: + /** + * @short Returns the result of evaluating operator @p op applied to the atomic + * values @p operand1 and @p operand2. + * + * The caller guarantees that both values are of type @p type. + * + * ComparisonFactory does not take ownership of @p sourceLocationReflection. + */ + static bool compare(const AtomicValue::Ptr &operand1, + const AtomicComparator::Operator op, + const AtomicValue::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection); + + /** + * @short Returns the result of evaluating operator @p op applied to the atomic + * values @p operand1 and @p operand2. + * + * In opposite to compare() it converts the operands from string type + * to @p type and compares these constructed types. + * + * The caller guarantees that both values are of type @p type. + * + * ComparisonFactory does not take ownership of @p sourceLocationReflection. + */ + static bool constructAndCompare(const DerivedString::Ptr &operand1, + const AtomicComparator::Operator op, + const DerivedString::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection); + + private: + Q_DISABLE_COPY(ComparisonFactory) + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/data/qitem_p.h b/src/xmlpatterns/data/qitem_p.h index 987a1c2..08b318d 100644 --- a/src/xmlpatterns/data/qitem_p.h +++ b/src/xmlpatterns/data/qitem_p.h @@ -128,6 +128,11 @@ namespace QPatternist typedef QExplicitlySharedDataPointer Ptr; /** + * A list if smart pointers wrapping AtomicValue instances. + */ + typedef QList List; + + /** * Determines whether this atomic value has an error. This is used * for implementing casting. * diff --git a/src/xmlpatterns/data/qvaluefactory.cpp b/src/xmlpatterns/data/qvaluefactory.cpp new file mode 100644 index 0000000..04df29d --- /dev/null +++ b/src/xmlpatterns/data/qvaluefactory.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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 "qatomiccaster_p.h" +#include "qatomicstring_p.h" +#include "qcastingplatform_p.h" +#include "qvaluefactory_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +/** + * @short Helper class for ValueFactory::fromLexical() which exposes + * CastingPlatform appropriately. + * + * @relates ValueFactory + */ +class PerformValueConstruction : public CastingPlatform + , public SourceLocationReflection +{ +public: + PerformValueConstruction(const SourceLocationReflection *const sourceLocationReflection, + const SchemaType::Ptr &toType) : m_sourceReflection(sourceLocationReflection) + , m_targetType(AtomicType::Ptr(toType)) + { + Q_ASSERT(m_sourceReflection); + } + + AtomicValue::Ptr operator()(const AtomicValue::Ptr &lexicalValue, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context) + { + prepareCasting(context, BuiltinTypes::xsString); + return AtomicValue::Ptr(const_cast(cast(lexicalValue, context).asAtomicValue())); + } + + const SourceLocationReflection *actualReflection() const + { + return m_sourceReflection; + } + + ItemType::Ptr targetType() const + { + return m_targetType; + } + +private: + const SourceLocationReflection *const m_sourceReflection; + const ItemType::Ptr m_targetType; +}; + +AtomicValue::Ptr ValueFactory::fromLexical(const QString &lexicalValue, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection) +{ + Q_ASSERT(context); + Q_ASSERT(type); + Q_ASSERT_X(type->category() == SchemaType::SimpleTypeAtomic, Q_FUNC_INFO, + "We can only construct for atomic values."); + + return PerformValueConstruction(sourceLocationReflection, type)(AtomicString::fromValue(lexicalValue), + type, + context); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/data/qvaluefactory_p.h b/src/xmlpatterns/data/qvaluefactory_p.h new file mode 100644 index 0000000..80b6207 --- /dev/null +++ b/src/xmlpatterns/data/qvaluefactory_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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_ValueFactory_H +#define Patternist_ValueFactory_H + +#include "qitem_p.h" +#include "qreportcontext_p.h" +#include "qschematype_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Provides fromLexical(), which allows instantiation of atomic + * values from arbitrary types. + * + * This class wraps the helper class CastingPlatform with a more specific, + * high-level API. + * + * @see CastingPlatform + * @author Frans Englich + * @ingroup Patternist_schema + */ + class ValueFactory + { + public: + /** + * @short Returns an AtomicValue of type @p type from the lexical space + * @p lexicalValue, and raise an error through @p context if that's + * impossible. + * + * ValueFactory does not take ownership of @p sourceLocationReflection. + */ + static AtomicValue::Ptr fromLexical(const QString &lexicalValue, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection); + + private: + Q_DISABLE_COPY(ValueFactory) + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/environment/createReportContext.xsl b/src/xmlpatterns/environment/createReportContext.xsl index e648c56..1db00e7 100644 --- a/src/xmlpatterns/environment/createReportContext.xsl +++ b/src/xmlpatterns/environment/createReportContext.xsl @@ -242,6 +242,11 @@ namespace QPatternist */]]> enum ErrorCode { + /** + * XML Schema error code. + */ + XSDError, + diff --git a/src/xmlpatterns/environment/qreportcontext.cpp b/src/xmlpatterns/environment/qreportcontext.cpp index 9704a54..acd6be0 100644 --- a/src/xmlpatterns/environment/qreportcontext.cpp +++ b/src/xmlpatterns/environment/qreportcontext.cpp @@ -448,6 +448,7 @@ QString ReportContext::codeToString(const ReportContext::ErrorCode code) case XTTE1545: result = "XTTE1545"; break; case XTTE1550: result = "XTTE1550"; break; case XTTE1555: result = "XTTE1555"; break; + case XSDError: result = "XSDError"; break; } Q_ASSERT_X(result, Q_FUNC_INFO, "Unknown enum value."); diff --git a/src/xmlpatterns/environment/qreportcontext_p.h b/src/xmlpatterns/environment/qreportcontext_p.h index bea2a97..8864756 100644 --- a/src/xmlpatterns/environment/qreportcontext_p.h +++ b/src/xmlpatterns/environment/qreportcontext_p.h @@ -151,6 +151,10 @@ namespace QPatternist */ enum ErrorCode { + /** + * XML Schema error code. + */ + XSDError, /** * It is a static error if analysis of an expression relies on some diff --git a/src/xmlpatterns/expr/qcastingplatform.cpp b/src/xmlpatterns/expr/qcastingplatform.cpp index 9e96fd8..16a1d60 100644 --- a/src/xmlpatterns/expr/qcastingplatform.cpp +++ b/src/xmlpatterns/expr/qcastingplatform.cpp @@ -83,7 +83,7 @@ Item CastingPlatform::cast(const Item &sourceValue, else { bool castImpossible = false; - const AtomicCaster::Ptr caster(locateCaster(sourceValue.type(), context, castImpossible)); + const AtomicCaster::Ptr caster(locateCaster(sourceValue.type(), context, castImpossible, static_cast(this), targetType())); if(!issueError && castImpossible) { @@ -112,7 +112,7 @@ bool CastingPlatform::prepareCasting(const ReportContext: or numeric at compile time. We'll do lookup at runtime instead. */ bool castImpossible = false; - m_caster = locateCaster(sourceType, context, castImpossible); + m_caster = locateCaster(sourceType, context, castImpossible, static_cast(this), targetType()); return !castImpossible; } @@ -120,20 +120,22 @@ bool CastingPlatform::prepareCasting(const ReportContext: template AtomicCaster::Ptr CastingPlatform::locateCaster(const ItemType::Ptr &sourceType, const ReportContext::Ptr &context, - bool &castImpossible) const + bool &castImpossible, + const SourceLocationReflection *const location, + const ItemType::Ptr &targetType) { Q_ASSERT(sourceType); - Q_ASSERT(targetType()); + Q_ASSERT(targetType); const AtomicCasterLocator::Ptr locator(static_cast( - targetType().data())->casterLocator()); + targetType.data())->casterLocator()); if(!locator) { if(issueError) { context->error(QtXmlPatterns::tr("No casting is possible with %1 as the target type.") - .arg(formatType(context->namePool(), targetType())), - ReportContext::XPTY0004, static_cast(this)); + .arg(formatType(context->namePool(), targetType)), + ReportContext::XPTY0004, location); } else castImpossible = true; @@ -141,15 +143,15 @@ AtomicCaster::Ptr CastingPlatform::locateCaster(const Ite return AtomicCaster::Ptr(); } - const AtomicCaster::Ptr caster(static_cast(sourceType.data())->accept(locator, static_cast(this))); + const AtomicCaster::Ptr caster(static_cast(sourceType.data())->accept(locator, location)); if(!caster) { if(issueError) { context->error(QtXmlPatterns::tr("It is not possible to cast from %1 to %2.") .arg(formatType(context->namePool(), sourceType)) - .arg(formatType(context->namePool(), targetType())), - ReportContext::XPTY0004, static_cast(this)); + .arg(formatType(context->namePool(), targetType)), + ReportContext::XPTY0004, location); } else castImpossible = true; diff --git a/src/xmlpatterns/expr/qcastingplatform_p.h b/src/xmlpatterns/expr/qcastingplatform_p.h index 458e9eb..a0144b2 100644 --- a/src/xmlpatterns/expr/qcastingplatform_p.h +++ b/src/xmlpatterns/expr/qcastingplatform_p.h @@ -52,16 +52,17 @@ #ifndef Patternist_CastingPlatform_H #define Patternist_CastingPlatform_H +#include "qatomiccasterlocator_p.h" #include "qatomiccaster_p.h" -#include "qqnamevalue_p.h" #include "qatomicstring_p.h" -#include "qvalidationerror_p.h" -#include "qatomiccasterlocator_p.h" #include "qatomictype_p.h" #include "qbuiltintypes_p.h" #include "qcommonsequencetypes_p.h" -#include "qschematypefactory_p.h" #include "qpatternistlocale_p.h" +#include "qqnamevalue_p.h" +#include "qschematypefactory_p.h" +#include "qstaticcontext_p.h" +#include "qvalidationerror_p.h" QT_BEGIN_HEADER @@ -101,6 +102,7 @@ namespace QPatternist * function targetType() must be implemented such that CastingPlatform knows * what type it shall cast to. * + * @see ValueFactory * @author Frans Englich * @ingroup Patternist_expressions */ @@ -167,9 +169,16 @@ namespace QPatternist * * @p castImpossible is not initialized. Initialize it to @c false. */ - AtomicCaster::Ptr locateCaster(const ItemType::Ptr &sourceType, - const ReportContext::Ptr &context, - bool &castImpossible) const; + static AtomicCaster::Ptr locateCaster(const ItemType::Ptr &sourceType, + const ReportContext::Ptr &context, + bool &castImpossible, + const SourceLocationReflection *const location, + const ItemType::Ptr &targetType); + private: + inline Item castWithCaster(const Item &sourceValue, + const AtomicCaster::Ptr &caster, + const DynamicContext::Ptr &context) const; + inline ItemType::Ptr targetType() const { diff --git a/src/xmlpatterns/expr/qexpressionfactory.cpp b/src/xmlpatterns/expr/qexpressionfactory.cpp index ec86be0..b41b0de 100644 --- a/src/xmlpatterns/expr/qexpressionfactory.cpp +++ b/src/xmlpatterns/expr/qexpressionfactory.cpp @@ -81,9 +81,13 @@ Expression::Ptr ExpressionFactory::createExpression(const QString &expr, const QUrl &queryURI, const QXmlName &initialTemplateName) { - if(lang == QXmlQuery::XQuery10) + if(lang == QXmlQuery::XSLT20) { - return createExpression(Tokenizer::Ptr(new XQueryTokenizer(expr, queryURI)), + QByteArray query(expr.toUtf8()); + QBuffer buffer(&query); + buffer.open(QIODevice::ReadOnly); + + return createExpression(&buffer, context, lang, requiredType, @@ -92,12 +96,7 @@ Expression::Ptr ExpressionFactory::createExpression(const QString &expr, } else { - Q_ASSERT(lang == QXmlQuery::XSLT20); - QByteArray query(expr.toUtf8()); - QBuffer buffer(&query); - buffer.open(QIODevice::ReadOnly); - - return createExpression(&buffer, + return createExpression(Tokenizer::Ptr(new XQueryTokenizer(expr, queryURI)), context, lang, requiredType, @@ -118,16 +117,10 @@ Expression::Ptr ExpressionFactory::createExpression(QIODevice *const device, Tokenizer::Ptr tokenizer; - if(lang == QXmlQuery::XQuery10) - { - - tokenizer = Tokenizer::Ptr(new XQueryTokenizer(QString::fromUtf8(device->readAll()), queryURI)); - } - else - { - Q_ASSERT(lang == QXmlQuery::XSLT20); + if(lang == QXmlQuery::XSLT20) tokenizer = Tokenizer::Ptr(new XSLTTokenizer(device, queryURI, context, context->namePool())); - } + else + tokenizer = Tokenizer::Ptr(new XQueryTokenizer(QString::fromUtf8(device->readAll()), queryURI)); return createExpression(tokenizer, context, lang, requiredType, queryURI, initialTemplateName); } diff --git a/src/xmlpatterns/functions/qpatternplatform.cpp b/src/xmlpatterns/functions/qpatternplatform.cpp index 0052a07..d99bac5 100644 --- a/src/xmlpatterns/functions/qpatternplatform.cpp +++ b/src/xmlpatterns/functions/qpatternplatform.cpp @@ -168,8 +168,15 @@ void PatternPlatform::applyFlags(const Flags flags, QRegExp &patternP) // TODO Apply the other flags, like 'x'. } +QRegExp PatternPlatform::parsePattern(const QString &pattern, + const ReportContext::Ptr &context) const +{ + return parsePattern(pattern, context, this); +} + QRegExp PatternPlatform::parsePattern(const QString &patternP, - const DynamicContext::Ptr &context) const + const ReportContext::Ptr &context, + const SourceLocationReflection *const location) { if(patternP == QLatin1String("(.)\\3") || patternP == QLatin1String("\\3") || @@ -177,7 +184,7 @@ QRegExp PatternPlatform::parsePattern(const QString &patternP, { context->error(QLatin1String("We don't want to hang infinitely on K2-MatchesFunc-9, " "10 and 11. See Trolltech task 148505."), - ReportContext::FOER0000, this); + ReportContext::FOER0000, location); return QRegExp(); } @@ -189,14 +196,8 @@ QRegExp PatternPlatform::parsePattern(const QString &patternP, * QChar::category(). */ rewrittenPattern.replace(QLatin1String("[\\i-[:]]"), QLatin1String("[a-zA-Z_]")); rewrittenPattern.replace(QLatin1String("[\\c-[:]]"), QLatin1String("[a-zA-Z0-9_\\-\\.]")); - rewrittenPattern.replace(QLatin1String("\\i"), QLatin1String("[a-zA-Z:_]")); - rewrittenPattern.replace(QLatin1String("\\c"), QLatin1String("[a-zA-Z0-9:_\\-\\.]")); - rewrittenPattern.replace(QLatin1String("\\p{L}"), QLatin1String("[a-zA-Z]")); - rewrittenPattern.replace(QLatin1String("\\p{Lu}"), QLatin1String("[A-Z]")); - rewrittenPattern.replace(QLatin1String("\\p{Ll}"), QLatin1String("[a-z]")); - rewrittenPattern.replace(QLatin1String("\\p{Nd}"), QLatin1String("[0-9]")); - QRegExp retval(rewrittenPattern); + QRegExp retval(rewrittenPattern, Qt::CaseSensitive, QRegExp::W3CXmlSchema11); if(retval.isValid()) return retval; @@ -204,7 +205,7 @@ QRegExp PatternPlatform::parsePattern(const QString &patternP, { context->error(QtXmlPatterns::tr("%1 is an invalid regular expression pattern: %2") .arg(formatExpression(patternP), retval.errorString()), - ReportContext::FORX0002, this); + ReportContext::FORX0002, location); return QRegExp(); } } diff --git a/src/xmlpatterns/functions/qpatternplatform_p.h b/src/xmlpatterns/functions/qpatternplatform_p.h index ce0dbd4..28da452 100644 --- a/src/xmlpatterns/functions/qpatternplatform_p.h +++ b/src/xmlpatterns/functions/qpatternplatform_p.h @@ -122,6 +122,14 @@ namespace QPatternist */ inline int captureCount() const; + /** + * @short Parses pattern + */ + static QRegExp parsePattern(const QString &pattern, + const ReportContext::Ptr &context, + const SourceLocationReflection *const location); + + protected: /** * @short This constructor is protected, because this class is supposed to be sub-classed. @@ -146,14 +154,18 @@ namespace QPatternist }; typedef QFlags PreCompiledParts; + /** + * @short Calls the public parsePattern() function and passes in @c + * this as the location. + */ + inline QRegExp parsePattern(const QString &pattern, + const ReportContext::Ptr &context) const; + Q_DISABLE_COPY(PatternPlatform) Flags parseFlags(const QString &flags, const DynamicContext::Ptr &context) const; - QRegExp parsePattern(const QString &pattern, - const DynamicContext::Ptr &context) const; - static void applyFlags(const Flags flags, QRegExp &pattern); /** diff --git a/src/xmlpatterns/parser/qquerytransformparser.cpp b/src/xmlpatterns/parser/qquerytransformparser.cpp index 60e3a0c..b2f8cd2 100644 --- a/src/xmlpatterns/parser/qquerytransformparser.cpp +++ b/src/xmlpatterns/parser/qquerytransformparser.cpp @@ -300,11 +300,18 @@ static inline QSourceLocation fromYYLTYPE(const YYLTYPE &sourceLocator, } /** + * @internal + * @relates QXmlQuery + */ +typedef QFlags QueryLanguages; + +/** * @short Flags invalid expressions and declarations in the currently * parsed language. * - * Since this grammar is used for several languages: XQuery 1.0, XSL-T 2.0 and - * XPath 2.0 inside XSL-T, it is the union of all the constructs in these + * Since this grammar is used for several languages: XQuery 1.0, XSL-T 2.0, and + * XPath 2.0 inside XSL-T, and field and selector patterns in W3C XML Schema's + * identity constraints, it is the union of all the constructs in these * languages. However, when dealing with each language individually, we * regularly need to disallow some expressions, such as direct element * constructors when parsing XSL-T, or the typeswitch when parsing XPath. @@ -315,19 +322,46 @@ static inline QSourceLocation fromYYLTYPE(const YYLTYPE &sourceLocator, * instance the @c let clause, should not be flagged as an error, because it's * used for internal purposes. * - * Hence, this function is called from each expression and declaration which is - * unavailable in XPath. + * Hence, this function is called from each expression and declaration with @p + * allowedLanguages stating what languages it is allowed in. * * If @p isInternal is @c true, no error is raised. Otherwise, if the current - * language is not XQuery, an error is raised. + * language is not in @p allowedLanguages, an error is raised. */ -static void disallowedConstruct(const ParserContext *const parseInfo, - const YYLTYPE &sourceLocator, - const bool isInternal = false) +static void allowedIn(const QueryLanguages allowedLanguages, + const ParserContext *const parseInfo, + const YYLTYPE &sourceLocator, + const bool isInternal = false) { - if(!isInternal && parseInfo->languageAccent != QXmlQuery::XQuery10) + /* We treat XPath 2.0 as a subset of XSL-T 2.0, so if XPath 2.0 is allowed + * and XSL-T is the language, it's ok. */ + if(!isInternal && + (!allowedLanguages.testFlag(parseInfo->languageAccent) && !(allowedLanguages.testFlag(QXmlQuery::XPath20) && parseInfo->languageAccent == QXmlQuery::XSLT20))) { - parseInfo->staticContext->error(QtXmlPatterns::tr("A construct was encountered which only is allowed in XQuery."), + + QString langName; + + switch(parseInfo->languageAccent) + { + case QXmlQuery::XPath20: + langName = QLatin1String("XPath 2.0"); + break; + case QXmlQuery::XSLT20: + langName = QLatin1String("XSL-T 2.0"); + break; + case QXmlQuery::XQuery10: + langName = QLatin1String("XQuery 1.0"); + break; + case QXmlQuery::XmlSchema11IdentityConstraintSelector: + langName = QtXmlPatterns::tr("W3C XML Schema identity constraint selector"); + break; + case QXmlQuery::XmlSchema11IdentityConstraintField: + langName = QtXmlPatterns::tr("W3C XML Schema identity constraint field"); + break; + } + + parseInfo->staticContext->error(QtXmlPatterns::tr("A construct was encountered " + "which is disallowed in the current language(%1).").arg(langName), ReportContext::XPST0003, fromYYLTYPE(sourceLocator, parseInfo)); @@ -1366,7 +1400,7 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ /* Line 221 of yacc.c. */ -#line 1289 "qquerytransformparser.cpp" +#line 1323 "qquerytransformparser.cpp" #ifdef short # undef short @@ -1850,54 +1884,54 @@ static const yytype_int16 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 1341, 1341, 1342, 1344, 1345, 1376, 1377, 1393, 1491, - 1493, 1499, 1501, 1508, 1514, 1520, 1527, 1530, 1534, 1538, - 1558, 1572, 1576, 1570, 1639, 1643, 1660, 1663, 1665, 1670, - 1671, 1675, 1676, 1680, 1684, 1688, 1690, 1691, 1693, 1695, - 1741, 1755, 1760, 1765, 1766, 1768, 1783, 1798, 1808, 1823, - 1827, 1832, 1846, 1850, 1855, 1869, 1874, 1879, 1884, 1889, - 1905, 1928, 1936, 1937, 1938, 1940, 1957, 1958, 1960, 1961, - 1963, 1964, 1966, 2021, 2025, 2031, 2034, 2039, 2053, 2057, - 2063, 2062, 2171, 2174, 2180, 2201, 2207, 2211, 2213, 2218, - 2228, 2229, 2234, 2235, 2244, 2314, 2325, 2326, 2330, 2335, - 2404, 2405, 2409, 2414, 2458, 2459, 2464, 2471, 2477, 2478, - 2479, 2480, 2481, 2482, 2488, 2493, 2499, 2502, 2507, 2513, - 2519, 2523, 2548, 2549, 2553, 2557, 2551, 2598, 2601, 2596, - 2617, 2618, 2619, 2622, 2626, 2634, 2633, 2647, 2646, 2655, - 2656, 2657, 2659, 2667, 2678, 2681, 2683, 2688, 2695, 2702, - 2708, 2728, 2733, 2739, 2742, 2744, 2745, 2752, 2758, 2762, - 2767, 2768, 2771, 2775, 2770, 2784, 2788, 2783, 2796, 2799, - 2803, 2798, 2812, 2816, 2811, 2824, 2826, 2854, 2853, 2865, - 2873, 2864, 2884, 2885, 2888, 2892, 2897, 2902, 2901, 2917, - 2922, 2923, 2928, 2929, 2934, 2935, 2936, 2937, 2939, 2940, - 2945, 2946, 2951, 2952, 2954, 2955, 2960, 2961, 2962, 2963, - 2965, 2966, 2971, 2972, 2977, 2978, 2980, 2984, 2989, 2990, - 2996, 2997, 3002, 3003, 3008, 3009, 3014, 3015, 3020, 3024, - 3029, 3030, 3031, 3033, 3038, 3039, 3040, 3041, 3042, 3043, - 3045, 3050, 3051, 3052, 3053, 3054, 3055, 3057, 3062, 3063, - 3064, 3066, 3080, 3081, 3082, 3084, 3100, 3104, 3109, 3110, - 3112, 3117, 3118, 3120, 3126, 3130, 3136, 3139, 3140, 3144, - 3153, 3158, 3162, 3163, 3168, 3167, 3182, 3189, 3188, 3203, - 3211, 3211, 3220, 3222, 3225, 3230, 3232, 3236, 3302, 3305, - 3311, 3314, 3323, 3327, 3331, 3336, 3337, 3342, 3343, 3346, - 3345, 3375, 3377, 3378, 3380, 3394, 3395, 3396, 3397, 3398, - 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3408, 3407, 3417, - 3428, 3433, 3435, 3440, 3441, 3443, 3447, 3449, 3453, 3462, - 3468, 3469, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, - 3491, 3492, 3497, 3501, 3506, 3511, 3516, 3521, 3525, 3530, - 3535, 3540, 3569, 3573, 3580, 3582, 3586, 3588, 3589, 3590, - 3624, 3633, 3622, 3874, 3878, 3898, 3901, 3907, 3912, 3917, - 3923, 3926, 3936, 3943, 3947, 3953, 3967, 3973, 3990, 3995, - 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4016, 4024, 4023, - 4063, 4066, 4071, 4086, 4091, 4098, 4110, 4114, 4110, 4120, - 4122, 4126, 4128, 4143, 4147, 4156, 4161, 4165, 4171, 4174, - 4179, 4184, 4189, 4190, 4191, 4192, 4194, 4195, 4196, 4197, - 4202, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4246, 4251, - 4256, 4262, 4263, 4265, 4270, 4275, 4280, 4285, 4301, 4302, - 4304, 4309, 4314, 4318, 4330, 4343, 4353, 4358, 4363, 4368, - 4382, 4396, 4397, 4399, 4409, 4411, 4416, 4423, 4430, 4432, - 4434, 4435, 4437, 4441, 4446, 4447, 4449, 4455, 4457, 4459, - 4460, 4462, 4474 + 0, 1375, 1375, 1376, 1378, 1379, 1410, 1411, 1427, 1525, + 1527, 1533, 1535, 1542, 1548, 1554, 1561, 1564, 1568, 1572, + 1592, 1606, 1610, 1604, 1673, 1677, 1694, 1697, 1699, 1704, + 1705, 1709, 1710, 1714, 1718, 1722, 1724, 1725, 1727, 1729, + 1775, 1789, 1794, 1799, 1800, 1802, 1817, 1832, 1842, 1857, + 1861, 1866, 1880, 1884, 1889, 1903, 1908, 1913, 1918, 1923, + 1939, 1962, 1970, 1971, 1972, 1974, 1991, 1992, 1994, 1995, + 1997, 1998, 2000, 2055, 2059, 2065, 2068, 2073, 2087, 2091, + 2097, 2096, 2205, 2208, 2214, 2235, 2241, 2245, 2247, 2252, + 2262, 2263, 2268, 2269, 2278, 2348, 2359, 2360, 2364, 2369, + 2438, 2439, 2443, 2448, 2492, 2493, 2498, 2505, 2511, 2512, + 2513, 2514, 2515, 2516, 2522, 2527, 2533, 2536, 2541, 2547, + 2553, 2557, 2582, 2583, 2587, 2591, 2585, 2632, 2635, 2630, + 2651, 2652, 2653, 2656, 2660, 2668, 2667, 2681, 2680, 2689, + 2690, 2691, 2693, 2701, 2712, 2715, 2717, 2722, 2729, 2736, + 2742, 2762, 2767, 2773, 2776, 2778, 2779, 2786, 2792, 2796, + 2801, 2802, 2805, 2809, 2804, 2819, 2823, 2818, 2831, 2834, + 2838, 2833, 2848, 2852, 2847, 2860, 2862, 2890, 2889, 2901, + 2909, 2900, 2920, 2921, 2924, 2928, 2933, 2938, 2937, 2953, + 2959, 2960, 2966, 2967, 2973, 2974, 2975, 2976, 2978, 2979, + 2985, 2986, 2992, 2993, 2995, 2996, 3002, 3003, 3004, 3005, + 3007, 3008, 3018, 3019, 3025, 3026, 3028, 3032, 3037, 3038, + 3045, 3046, 3052, 3053, 3059, 3060, 3066, 3067, 3073, 3077, + 3082, 3083, 3084, 3086, 3092, 3093, 3094, 3095, 3096, 3097, + 3099, 3104, 3105, 3106, 3107, 3108, 3109, 3111, 3116, 3117, + 3118, 3120, 3134, 3135, 3136, 3138, 3155, 3159, 3164, 3165, + 3167, 3172, 3173, 3175, 3181, 3185, 3191, 3194, 3195, 3199, + 3208, 3213, 3217, 3218, 3223, 3222, 3237, 3245, 3244, 3260, + 3268, 3268, 3277, 3279, 3282, 3287, 3289, 3293, 3359, 3362, + 3368, 3371, 3380, 3384, 3388, 3393, 3394, 3399, 3400, 3403, + 3402, 3432, 3434, 3435, 3437, 3481, 3482, 3483, 3484, 3485, + 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3495, 3494, 3505, + 3516, 3521, 3523, 3528, 3529, 3534, 3538, 3540, 3544, 3553, + 3560, 3561, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, + 3584, 3585, 3590, 3595, 3601, 3607, 3612, 3617, 3622, 3628, + 3633, 3638, 3668, 3672, 3679, 3681, 3685, 3690, 3691, 3692, + 3726, 3735, 3724, 3976, 3980, 4000, 4003, 4009, 4014, 4019, + 4025, 4028, 4038, 4045, 4049, 4055, 4069, 4075, 4092, 4097, + 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4118, 4126, 4125, + 4165, 4168, 4173, 4188, 4193, 4200, 4212, 4216, 4212, 4222, + 4224, 4228, 4230, 4245, 4249, 4258, 4263, 4267, 4273, 4276, + 4281, 4286, 4291, 4292, 4293, 4294, 4296, 4297, 4298, 4299, + 4304, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4348, 4353, + 4358, 4364, 4365, 4367, 4372, 4377, 4382, 4387, 4403, 4404, + 4406, 4411, 4416, 4420, 4432, 4445, 4455, 4460, 4465, 4470, + 4484, 4498, 4499, 4501, 4511, 4513, 4518, 4525, 4532, 4534, + 4536, 4537, 4539, 4543, 4548, 4549, 4551, 4557, 4559, 4561, + 4565, 4570, 4582 }; #endif @@ -3726,7 +3760,7 @@ yyreduce: { case 5: /* Line 1269 of yacc.c. */ -#line 1346 "querytransformparser.ypp" +#line 1380 "querytransformparser.ypp" { /* Suppress more compiler warnings about unused defines. */ @@ -3760,7 +3794,7 @@ yyreduce: case 7: /* Line 1269 of yacc.c. */ -#line 1378 "querytransformparser.ypp" +#line 1412 "querytransformparser.ypp" { const QRegExp encNameRegExp(QLatin1String("[A-Za-z][A-Za-z0-9._\\-]*")); @@ -3779,7 +3813,7 @@ yyreduce: case 8: /* Line 1269 of yacc.c. */ -#line 1394 "querytransformparser.ypp" +#line 1428 "querytransformparser.ypp" { /* In XSL-T, we can have dangling variable references, so resolve them * before we proceed with other steps, such as checking circularity. */ @@ -3880,7 +3914,7 @@ yyreduce: case 10: /* Line 1269 of yacc.c. */ -#line 1494 "querytransformparser.ypp" +#line 1528 "querytransformparser.ypp" { // TODO add to namespace context parseInfo->moduleNamespace = parseInfo->staticContext->namePool()->allocateNamespace((yyvsp[(3) - (6)].sval)); @@ -3889,9 +3923,9 @@ yyreduce: case 12: /* Line 1269 of yacc.c. */ -#line 1502 "querytransformparser.ypp" +#line 1536 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("A default namespace declaration must occur before function, " "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE((yyloc), parseInfo)); @@ -3900,7 +3934,7 @@ yyreduce: case 13: /* Line 1269 of yacc.c. */ -#line 1509 "querytransformparser.ypp" +#line 1543 "querytransformparser.ypp" { if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("A default namespace declaration must occur before function, " @@ -3910,7 +3944,7 @@ yyreduce: case 14: /* Line 1269 of yacc.c. */ -#line 1515 "querytransformparser.ypp" +#line 1549 "querytransformparser.ypp" { if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("Namespace declarations must occur before function, " @@ -3920,9 +3954,9 @@ yyreduce: case 15: /* Line 1269 of yacc.c. */ -#line 1521 "querytransformparser.ypp" +#line 1555 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("Module imports must occur before function, " "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE((yyloc), parseInfo)); @@ -3931,7 +3965,7 @@ yyreduce: case 17: /* Line 1269 of yacc.c. */ -#line 1531 "querytransformparser.ypp" +#line 1565 "querytransformparser.ypp" { parseInfo->hasSecondPrologPart = true; } @@ -3939,7 +3973,7 @@ yyreduce: case 18: /* Line 1269 of yacc.c. */ -#line 1535 "querytransformparser.ypp" +#line 1569 "querytransformparser.ypp" { parseInfo->hasSecondPrologPart = true; } @@ -3947,16 +3981,16 @@ yyreduce: case 19: /* Line 1269 of yacc.c. */ -#line 1539 "querytransformparser.ypp" +#line 1573 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); parseInfo->hasSecondPrologPart = true; } break; case 20: /* Line 1269 of yacc.c. */ -#line 1562 "querytransformparser.ypp" +#line 1596 "querytransformparser.ypp" { Template::Ptr temp(create(new Template(parseInfo->currentImportPrecedence, (yyvsp[(5) - (7)].sequenceType)), (yyloc), parseInfo)); @@ -3969,7 +4003,7 @@ yyreduce: case 21: /* Line 1269 of yacc.c. */ -#line 1572 "querytransformparser.ypp" +#line 1606 "querytransformparser.ypp" { parseInfo->isParsingPattern = true; } @@ -3977,7 +4011,7 @@ yyreduce: case 22: /* Line 1269 of yacc.c. */ -#line 1576 "querytransformparser.ypp" +#line 1610 "querytransformparser.ypp" { parseInfo->isParsingPattern = false; } @@ -3985,7 +4019,7 @@ yyreduce: case 23: /* Line 1269 of yacc.c. */ -#line 1585 "querytransformparser.ypp" +#line 1619 "querytransformparser.ypp" { /* In this grammar branch, we're guaranteed to be a template rule, but * may also be a named template. */ @@ -4042,7 +4076,7 @@ yyreduce: case 24: /* Line 1269 of yacc.c. */ -#line 1639 "querytransformparser.ypp" +#line 1673 "querytransformparser.ypp" { (yyval.enums.Double) = std::numeric_limits::quiet_NaN(); } @@ -4050,7 +4084,7 @@ yyreduce: case 25: /* Line 1269 of yacc.c. */ -#line 1644 "querytransformparser.ypp" +#line 1678 "querytransformparser.ypp" { const AtomicValue::Ptr val(Decimal::fromLexical((yyvsp[(2) - (2)].sval))); if(val->hasError()) @@ -4069,7 +4103,7 @@ yyreduce: case 26: /* Line 1269 of yacc.c. */ -#line 1660 "querytransformparser.ypp" +#line 1694 "querytransformparser.ypp" { (yyval.qName) = QXmlName(); } @@ -4077,7 +4111,7 @@ yyreduce: case 28: /* Line 1269 of yacc.c. */ -#line 1666 "querytransformparser.ypp" +#line 1700 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(2) - (2)].qName); } @@ -4085,42 +4119,42 @@ yyreduce: case 30: /* Line 1269 of yacc.c. */ -#line 1672 "querytransformparser.ypp" +#line 1706 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 32: /* Line 1269 of yacc.c. */ -#line 1677 "querytransformparser.ypp" +#line 1711 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 33: /* Line 1269 of yacc.c. */ -#line 1681 "querytransformparser.ypp" +#line 1715 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 34: /* Line 1269 of yacc.c. */ -#line 1685 "querytransformparser.ypp" +#line 1719 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 39: /* Line 1269 of yacc.c. */ -#line 1696 "querytransformparser.ypp" +#line 1730 "querytransformparser.ypp" { if(!(yyvsp[(6) - (7)].enums.Bool)) - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); if((yyvsp[(3) - (7)].sval) == QLatin1String("xmlns")) { @@ -4166,7 +4200,7 @@ yyreduce: case 40: /* Line 1269 of yacc.c. */ -#line 1742 "querytransformparser.ypp" +#line 1776 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::BoundarySpaceDecl)) { @@ -4183,7 +4217,7 @@ yyreduce: case 41: /* Line 1269 of yacc.c. */ -#line 1756 "querytransformparser.ypp" +#line 1790 "querytransformparser.ypp" { (yyval.enums.boundarySpacePolicy) = StaticContext::BSPStrip; } @@ -4191,7 +4225,7 @@ yyreduce: case 42: /* Line 1269 of yacc.c. */ -#line 1761 "querytransformparser.ypp" +#line 1795 "querytransformparser.ypp" { (yyval.enums.boundarySpacePolicy) = StaticContext::BSPPreserve; } @@ -4199,7 +4233,7 @@ yyreduce: case 45: /* Line 1269 of yacc.c. */ -#line 1770 "querytransformparser.ypp" +#line 1804 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::DeclareDefaultElementNamespace)) { @@ -4216,7 +4250,7 @@ yyreduce: case 46: /* Line 1269 of yacc.c. */ -#line 1785 "querytransformparser.ypp" +#line 1819 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::DeclareDefaultFunctionNamespace)) { @@ -4233,7 +4267,7 @@ yyreduce: case 47: /* Line 1269 of yacc.c. */ -#line 1799 "querytransformparser.ypp" +#line 1833 "querytransformparser.ypp" { if((yyvsp[(3) - (5)].qName).prefix() == StandardPrefixes::empty) { @@ -4246,9 +4280,9 @@ yyreduce: case 48: /* Line 1269 of yacc.c. */ -#line 1809 "querytransformparser.ypp" +#line 1843 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); if(parseInfo->hasDeclaration(ParserContext::OrderingModeDecl)) { parseInfo->staticContext->error(prologMessage("declare ordering"), @@ -4264,7 +4298,7 @@ yyreduce: case 49: /* Line 1269 of yacc.c. */ -#line 1824 "querytransformparser.ypp" +#line 1858 "querytransformparser.ypp" { (yyval.enums.orderingMode) = StaticContext::Ordered; } @@ -4272,7 +4306,7 @@ yyreduce: case 50: /* Line 1269 of yacc.c. */ -#line 1828 "querytransformparser.ypp" +#line 1862 "querytransformparser.ypp" { (yyval.enums.orderingMode) = StaticContext::Unordered; } @@ -4280,7 +4314,7 @@ yyreduce: case 51: /* Line 1269 of yacc.c. */ -#line 1833 "querytransformparser.ypp" +#line 1867 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::EmptyOrderDecl)) { @@ -4297,7 +4331,7 @@ yyreduce: case 52: /* Line 1269 of yacc.c. */ -#line 1847 "querytransformparser.ypp" +#line 1881 "querytransformparser.ypp" { (yyval.enums.orderingEmptySequence) = StaticContext::Least; } @@ -4305,7 +4339,7 @@ yyreduce: case 53: /* Line 1269 of yacc.c. */ -#line 1851 "querytransformparser.ypp" +#line 1885 "querytransformparser.ypp" { (yyval.enums.orderingEmptySequence) = StaticContext::Greatest; } @@ -4313,7 +4347,7 @@ yyreduce: case 54: /* Line 1269 of yacc.c. */ -#line 1857 "querytransformparser.ypp" +#line 1891 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::CopyNamespacesDecl)) { @@ -4329,7 +4363,7 @@ yyreduce: case 55: /* Line 1269 of yacc.c. */ -#line 1870 "querytransformparser.ypp" +#line 1904 "querytransformparser.ypp" { parseInfo->preserveNamespacesMode = true; } @@ -4337,7 +4371,7 @@ yyreduce: case 56: /* Line 1269 of yacc.c. */ -#line 1875 "querytransformparser.ypp" +#line 1909 "querytransformparser.ypp" { parseInfo->preserveNamespacesMode = false; } @@ -4345,7 +4379,7 @@ yyreduce: case 57: /* Line 1269 of yacc.c. */ -#line 1880 "querytransformparser.ypp" +#line 1914 "querytransformparser.ypp" { parseInfo->inheritNamespacesMode = true; } @@ -4353,7 +4387,7 @@ yyreduce: case 58: /* Line 1269 of yacc.c. */ -#line 1885 "querytransformparser.ypp" +#line 1919 "querytransformparser.ypp" { parseInfo->inheritNamespacesMode = false; } @@ -4361,7 +4395,7 @@ yyreduce: case 59: /* Line 1269 of yacc.c. */ -#line 1890 "querytransformparser.ypp" +#line 1924 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::DefaultCollationDecl)) { @@ -4380,9 +4414,9 @@ yyreduce: case 60: /* Line 1269 of yacc.c. */ -#line 1906 "querytransformparser.ypp" +#line 1940 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(3) - (5)].enums.Bool)); + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, (yyloc), (yyvsp[(3) - (5)].enums.Bool)); if(parseInfo->hasDeclaration(ParserContext::BaseURIDecl)) { parseInfo->staticContext->error(prologMessage("declare base-uri"), @@ -4406,7 +4440,7 @@ yyreduce: case 61: /* Line 1269 of yacc.c. */ -#line 1929 "querytransformparser.ypp" +#line 1963 "querytransformparser.ypp" { parseInfo->staticContext->error(QtXmlPatterns::tr("The Schema Import feature is not supported, " "and therefore %1 declarations cannot occur.") @@ -4417,7 +4451,7 @@ yyreduce: case 65: /* Line 1269 of yacc.c. */ -#line 1941 "querytransformparser.ypp" +#line 1975 "querytransformparser.ypp" { if((yyvsp[(4) - (6)].sval).isEmpty()) { @@ -4437,9 +4471,9 @@ yyreduce: case 72: /* Line 1269 of yacc.c. */ -#line 1968 "querytransformparser.ypp" +#line 2002 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(3) - (9)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(3) - (9)].enums.Bool)); if(variableByName((yyvsp[(5) - (9)].qName), parseInfo)) { parseInfo->staticContext->error(QtXmlPatterns::tr("A variable by name %1 has already " @@ -4494,7 +4528,7 @@ yyreduce: case 73: /* Line 1269 of yacc.c. */ -#line 2022 "querytransformparser.ypp" +#line 2056 "querytransformparser.ypp" { (yyval.expr).reset(); } @@ -4502,7 +4536,7 @@ yyreduce: case 74: /* Line 1269 of yacc.c. */ -#line 2026 "querytransformparser.ypp" +#line 2060 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -4510,7 +4544,7 @@ yyreduce: case 75: /* Line 1269 of yacc.c. */ -#line 2031 "querytransformparser.ypp" +#line 2065 "querytransformparser.ypp" { (yyval.expr).reset(); } @@ -4518,7 +4552,7 @@ yyreduce: case 76: /* Line 1269 of yacc.c. */ -#line 2035 "querytransformparser.ypp" +#line 2069 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -4526,7 +4560,7 @@ yyreduce: case 77: /* Line 1269 of yacc.c. */ -#line 2040 "querytransformparser.ypp" +#line 2074 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::ConstructionDecl)) { @@ -4543,7 +4577,7 @@ yyreduce: case 78: /* Line 1269 of yacc.c. */ -#line 2054 "querytransformparser.ypp" +#line 2088 "querytransformparser.ypp" { (yyval.enums.constructionMode) = StaticContext::CMStrip; } @@ -4551,7 +4585,7 @@ yyreduce: case 79: /* Line 1269 of yacc.c. */ -#line 2058 "querytransformparser.ypp" +#line 2092 "querytransformparser.ypp" { (yyval.enums.constructionMode) = StaticContext::CMPreserve; } @@ -4559,7 +4593,7 @@ yyreduce: case 80: /* Line 1269 of yacc.c. */ -#line 2063 "querytransformparser.ypp" +#line 2097 "querytransformparser.ypp" { (yyval.enums.slot) = parseInfo->currentExpressionSlot() - (yyvsp[(6) - (7)].functionArguments).count(); } @@ -4567,10 +4601,10 @@ yyreduce: case 81: /* Line 1269 of yacc.c. */ -#line 2067 "querytransformparser.ypp" +#line 2101 "querytransformparser.ypp" { if(!(yyvsp[(3) - (11)].enums.Bool)) - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(3) - (11)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(3) - (11)].enums.Bool)); /* If FunctionBody is null, it is 'external', otherwise the value is the body. */ const QXmlName::NamespaceCode ns((yyvsp[(4) - (11)].qName).namespaceURI()); @@ -4674,7 +4708,7 @@ yyreduce: case 82: /* Line 1269 of yacc.c. */ -#line 2171 "querytransformparser.ypp" +#line 2205 "querytransformparser.ypp" { (yyval.functionArguments) = FunctionArgument::List(); } @@ -4682,7 +4716,7 @@ yyreduce: case 83: /* Line 1269 of yacc.c. */ -#line 2175 "querytransformparser.ypp" +#line 2209 "querytransformparser.ypp" { FunctionArgument::List l; l.append((yyvsp[(1) - (1)].functionArgument)); @@ -4692,7 +4726,7 @@ yyreduce: case 84: /* Line 1269 of yacc.c. */ -#line 2181 "querytransformparser.ypp" +#line 2215 "querytransformparser.ypp" { FunctionArgument::List::const_iterator it((yyvsp[(1) - (3)].functionArguments).constBegin()); const FunctionArgument::List::const_iterator end((yyvsp[(1) - (3)].functionArguments).constEnd()); @@ -4716,7 +4750,7 @@ yyreduce: case 85: /* Line 1269 of yacc.c. */ -#line 2202 "querytransformparser.ypp" +#line 2236 "querytransformparser.ypp" { pushVariable((yyvsp[(2) - (3)].qName), (yyvsp[(3) - (3)].sequenceType), Expression::Ptr(), VariableDeclaration::FunctionArgument, (yyloc), parseInfo); (yyval.functionArgument) = FunctionArgument::Ptr(new FunctionArgument((yyvsp[(2) - (3)].qName), (yyvsp[(3) - (3)].sequenceType))); @@ -4725,7 +4759,7 @@ yyreduce: case 86: /* Line 1269 of yacc.c. */ -#line 2208 "querytransformparser.ypp" +#line 2242 "querytransformparser.ypp" { (yyval.expr).reset(); } @@ -4733,7 +4767,7 @@ yyreduce: case 88: /* Line 1269 of yacc.c. */ -#line 2214 "querytransformparser.ypp" +#line 2248 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (3)].expr); } @@ -4741,7 +4775,7 @@ yyreduce: case 91: /* Line 1269 of yacc.c. */ -#line 2230 "querytransformparser.ypp" +#line 2264 "querytransformparser.ypp" { (yyval.expr) = create(new CombineNodes((yyvsp[(1) - (3)].expr), CombineNodes::Union, (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } @@ -4749,7 +4783,7 @@ yyreduce: case 93: /* Line 1269 of yacc.c. */ -#line 2236 "querytransformparser.ypp" +#line 2270 "querytransformparser.ypp" { /* We write this into a node test. The spec says, 5.5.3 The Meaning of a Pattern: * "Similarly, / matches a document node, and only a document node, @@ -4762,7 +4796,7 @@ yyreduce: case 94: /* Line 1269 of yacc.c. */ -#line 2245 "querytransformparser.ypp" +#line 2279 "querytransformparser.ypp" { /* /axis::node-test * => @@ -4836,7 +4870,7 @@ yyreduce: case 95: /* Line 1269 of yacc.c. */ -#line 2315 "querytransformparser.ypp" +#line 2349 "querytransformparser.ypp" { /* //axis::node-test * => @@ -4851,7 +4885,7 @@ yyreduce: case 97: /* Line 1269 of yacc.c. */ -#line 2327 "querytransformparser.ypp" +#line 2361 "querytransformparser.ypp" { createIdPatternPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), QXmlNodeModelIndex::AxisParent, (yylsp[(2) - (3)]), parseInfo); } @@ -4859,7 +4893,7 @@ yyreduce: case 98: /* Line 1269 of yacc.c. */ -#line 2331 "querytransformparser.ypp" +#line 2365 "querytransformparser.ypp" { createIdPatternPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), QXmlNodeModelIndex::AxisAncestor, (yylsp[(2) - (3)]), parseInfo); } @@ -4867,7 +4901,7 @@ yyreduce: case 99: /* Line 1269 of yacc.c. */ -#line 2336 "querytransformparser.ypp" +#line 2370 "querytransformparser.ypp" { const Expression::List ands((yyvsp[(1) - (1)].expr)->operands()); const FunctionSignature::Ptr signature((yyvsp[(1) - (1)].expr)->as()->signature()); @@ -4939,7 +4973,7 @@ yyreduce: case 101: /* Line 1269 of yacc.c. */ -#line 2406 "querytransformparser.ypp" +#line 2440 "querytransformparser.ypp" { (yyval.expr) = createPatternPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), QXmlNodeModelIndex::AxisParent, (yylsp[(2) - (3)]), parseInfo); } @@ -4947,7 +4981,7 @@ yyreduce: case 102: /* Line 1269 of yacc.c. */ -#line 2410 "querytransformparser.ypp" +#line 2444 "querytransformparser.ypp" { (yyval.expr) = createPatternPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), QXmlNodeModelIndex::AxisAncestor, (yylsp[(2) - (3)]), parseInfo); } @@ -4955,7 +4989,7 @@ yyreduce: case 103: /* Line 1269 of yacc.c. */ -#line 2415 "querytransformparser.ypp" +#line 2449 "querytransformparser.ypp" { const Expression::Ptr expr(findAxisStep((yyvsp[(1) - (1)].expr))); @@ -5002,7 +5036,7 @@ yyreduce: case 105: /* Line 1269 of yacc.c. */ -#line 2460 "querytransformparser.ypp" +#line 2494 "querytransformparser.ypp" { (yyval.expr) = create(new ExpressionSequence((yyvsp[(1) - (1)].expressionList)), (yyloc), parseInfo); } @@ -5010,7 +5044,7 @@ yyreduce: case 106: /* Line 1269 of yacc.c. */ -#line 2465 "querytransformparser.ypp" +#line 2499 "querytransformparser.ypp" { Expression::List l; l.append((yyvsp[(1) - (3)].expr)); @@ -5021,7 +5055,7 @@ yyreduce: case 107: /* Line 1269 of yacc.c. */ -#line 2472 "querytransformparser.ypp" +#line 2506 "querytransformparser.ypp" { (yyvsp[(1) - (3)].expressionList).append((yyvsp[(3) - (3)].expr)); (yyval.expressionList) = (yyvsp[(1) - (3)].expressionList); @@ -5030,7 +5064,7 @@ yyreduce: case 113: /* Line 1269 of yacc.c. */ -#line 2483 "querytransformparser.ypp" +#line 2517 "querytransformparser.ypp" { (yyval.expr) = createDirAttributeValue((yyvsp[(3) - (4)].expressionList), parseInfo, (yyloc)); } @@ -5038,7 +5072,7 @@ yyreduce: case 114: /* Line 1269 of yacc.c. */ -#line 2488 "querytransformparser.ypp" +#line 2522 "querytransformparser.ypp" { QVector result; result.append(QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::Default)); @@ -5048,7 +5082,7 @@ yyreduce: case 115: /* Line 1269 of yacc.c. */ -#line 2494 "querytransformparser.ypp" +#line 2528 "querytransformparser.ypp" { (yyval.qNameVector) = (yyvsp[(2) - (2)].qNameVector); } @@ -5056,7 +5090,7 @@ yyreduce: case 116: /* Line 1269 of yacc.c. */ -#line 2499 "querytransformparser.ypp" +#line 2533 "querytransformparser.ypp" { (yyval.qName) = QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::Default); } @@ -5064,7 +5098,7 @@ yyreduce: case 117: /* Line 1269 of yacc.c. */ -#line 2503 "querytransformparser.ypp" +#line 2537 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(2) - (2)].qName); } @@ -5072,7 +5106,7 @@ yyreduce: case 118: /* Line 1269 of yacc.c. */ -#line 2508 "querytransformparser.ypp" +#line 2542 "querytransformparser.ypp" { QVector result; result.append((yyvsp[(1) - (1)].qName)); @@ -5082,7 +5116,7 @@ yyreduce: case 119: /* Line 1269 of yacc.c. */ -#line 2514 "querytransformparser.ypp" +#line 2548 "querytransformparser.ypp" { (yyvsp[(1) - (3)].qNameVector).append((yyvsp[(3) - (3)].qName)); (yyval.qNameVector) = (yyvsp[(1) - (3)].qNameVector); @@ -5091,7 +5125,7 @@ yyreduce: case 120: /* Line 1269 of yacc.c. */ -#line 2520 "querytransformparser.ypp" +#line 2554 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(1) - (1)].qName); } @@ -5099,7 +5133,7 @@ yyreduce: case 121: /* Line 1269 of yacc.c. */ -#line 2524 "querytransformparser.ypp" +#line 2558 "querytransformparser.ypp" { if((yyvsp[(1) - (1)].sval) == QLatin1String("#current")) (yyval.qName) = QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::current); @@ -5126,7 +5160,7 @@ yyreduce: case 124: /* Line 1269 of yacc.c. */ -#line 2553 "querytransformparser.ypp" +#line 2587 "querytransformparser.ypp" { /* We're pushing the range variable here, not the positional. */ (yyval.expr) = pushVariable((yyvsp[(3) - (7)].qName), quantificationType((yyvsp[(4) - (7)].sequenceType)), (yyvsp[(7) - (7)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5135,7 +5169,7 @@ yyreduce: case 125: /* Line 1269 of yacc.c. */ -#line 2557 "querytransformparser.ypp" +#line 2591 "querytransformparser.ypp" { /* It is ok this appears after PositionalVar, because currentRangeSlot() * uses a different "channel" than currentPositionSlot(), so they can't trash @@ -5146,7 +5180,7 @@ yyreduce: case 126: /* Line 1269 of yacc.c. */ -#line 2564 "querytransformparser.ypp" +#line 2598 "querytransformparser.ypp" { Q_ASSERT((yyvsp[(7) - (10)].expr)); Q_ASSERT((yyvsp[(10) - (10)].expr)); @@ -5182,7 +5216,7 @@ yyreduce: case 127: /* Line 1269 of yacc.c. */ -#line 2598 "querytransformparser.ypp" +#line 2632 "querytransformparser.ypp" { pushVariable((yyvsp[(3) - (7)].qName), quantificationType((yyvsp[(4) - (7)].sequenceType)), (yyvsp[(7) - (7)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); } @@ -5190,7 +5224,7 @@ yyreduce: case 128: /* Line 1269 of yacc.c. */ -#line 2601 "querytransformparser.ypp" +#line 2635 "querytransformparser.ypp" { /* It is ok this appears after PositionalVar, because currentRangeSlot() * uses a different "channel" than currentPositionSlot(), so they can't trash @@ -5201,7 +5235,7 @@ yyreduce: case 129: /* Line 1269 of yacc.c. */ -#line 2608 "querytransformparser.ypp" +#line 2642 "querytransformparser.ypp" { (yyval.expr) = create(new ForClause((yyvsp[(9) - (10)].enums.slot), (yyvsp[(7) - (10)].expr), (yyvsp[(10) - (10)].expr), (yyvsp[(5) - (10)].enums.slot)), (yyloc), parseInfo); @@ -5214,7 +5248,7 @@ yyreduce: case 133: /* Line 1269 of yacc.c. */ -#line 2622 "querytransformparser.ypp" +#line 2656 "querytransformparser.ypp" { (yyval.enums.slot) = -1; } @@ -5222,7 +5256,7 @@ yyreduce: case 134: /* Line 1269 of yacc.c. */ -#line 2627 "querytransformparser.ypp" +#line 2661 "querytransformparser.ypp" { pushVariable((yyvsp[(3) - (3)].qName), CommonSequenceTypes::ExactlyOneInteger, Expression::Ptr(), VariableDeclaration::PositionalVariable, (yyloc), parseInfo); @@ -5232,7 +5266,7 @@ yyreduce: case 135: /* Line 1269 of yacc.c. */ -#line 2634 "querytransformparser.ypp" +#line 2668 "querytransformparser.ypp" { (yyval.expr) = pushVariable((yyvsp[(4) - (7)].qName), quantificationType((yyvsp[(5) - (7)].sequenceType)), (yyvsp[(7) - (7)].expr), VariableDeclaration::ExpressionVariable, (yyloc), parseInfo); } @@ -5240,9 +5274,9 @@ yyreduce: case 136: /* Line 1269 of yacc.c. */ -#line 2638 "querytransformparser.ypp" +#line 2672 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (9)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (9)].enums.Bool)); Q_ASSERT(parseInfo->variables.top()->name == (yyvsp[(4) - (9)].qName)); (yyval.expr) = create(new LetClause((yyvsp[(8) - (9)].expr), (yyvsp[(9) - (9)].expr), parseInfo->variables.top()), (yyloc), parseInfo); @@ -5252,13 +5286,13 @@ yyreduce: case 137: /* Line 1269 of yacc.c. */ -#line 2647 "querytransformparser.ypp" +#line 2681 "querytransformparser.ypp" { (yyval.expr) = pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::ExpressionVariable, (yyloc), parseInfo);} break; case 138: /* Line 1269 of yacc.c. */ -#line 2649 "querytransformparser.ypp" +#line 2683 "querytransformparser.ypp" { Q_ASSERT(parseInfo->variables.top()->name == (yyvsp[(3) - (8)].qName)); (yyval.expr) = create(new LetClause((yyvsp[(7) - (8)].expr), (yyvsp[(8) - (8)].expr), parseInfo->variables.top()), (yyloc), parseInfo); @@ -5268,7 +5302,7 @@ yyreduce: case 142: /* Line 1269 of yacc.c. */ -#line 2660 "querytransformparser.ypp" +#line 2694 "querytransformparser.ypp" { if((yyvsp[(1) - (3)].orderSpecs).isEmpty()) (yyval.expr) = (yyvsp[(3) - (3)].expr); @@ -5279,7 +5313,7 @@ yyreduce: case 143: /* Line 1269 of yacc.c. */ -#line 2668 "querytransformparser.ypp" +#line 2702 "querytransformparser.ypp" { if((yyvsp[(3) - (5)].orderSpecs).isEmpty()) (yyval.expr) = create(new IfThenClause((yyvsp[(2) - (5)].expr), (yyvsp[(5) - (5)].expr), create(new EmptySequence, (yyloc), parseInfo)), (yyloc), parseInfo); @@ -5292,7 +5326,7 @@ yyreduce: case 144: /* Line 1269 of yacc.c. */ -#line 2678 "querytransformparser.ypp" +#line 2712 "querytransformparser.ypp" { (yyval.orderSpecs) = OrderSpecTransfer::List(); } @@ -5300,7 +5334,7 @@ yyreduce: case 146: /* Line 1269 of yacc.c. */ -#line 2684 "querytransformparser.ypp" +#line 2718 "querytransformparser.ypp" { (yyval.orderSpecs) = (yyvsp[(2) - (2)].orderSpecs); } @@ -5308,7 +5342,7 @@ yyreduce: case 147: /* Line 1269 of yacc.c. */ -#line 2689 "querytransformparser.ypp" +#line 2723 "querytransformparser.ypp" { OrderSpecTransfer::List list; list += (yyvsp[(1) - (3)].orderSpecs); @@ -5319,7 +5353,7 @@ yyreduce: case 148: /* Line 1269 of yacc.c. */ -#line 2696 "querytransformparser.ypp" +#line 2730 "querytransformparser.ypp" { OrderSpecTransfer::List list; list.append((yyvsp[(1) - (1)].orderSpec)); @@ -5329,7 +5363,7 @@ yyreduce: case 149: /* Line 1269 of yacc.c. */ -#line 2703 "querytransformparser.ypp" +#line 2737 "querytransformparser.ypp" { (yyval.orderSpec) = OrderSpecTransfer((yyvsp[(1) - (4)].expr), OrderBy::OrderSpec((yyvsp[(2) - (4)].enums.sortDirection), (yyvsp[(3) - (4)].enums.orderingEmptySequence))); } @@ -5337,7 +5371,7 @@ yyreduce: case 150: /* Line 1269 of yacc.c. */ -#line 2708 "querytransformparser.ypp" +#line 2742 "querytransformparser.ypp" { /* Where does the specification state the default value is ascending? * @@ -5361,7 +5395,7 @@ yyreduce: case 151: /* Line 1269 of yacc.c. */ -#line 2729 "querytransformparser.ypp" +#line 2763 "querytransformparser.ypp" { (yyval.enums.sortDirection) = OrderBy::OrderSpec::Ascending; } @@ -5369,7 +5403,7 @@ yyreduce: case 152: /* Line 1269 of yacc.c. */ -#line 2734 "querytransformparser.ypp" +#line 2768 "querytransformparser.ypp" { (yyval.enums.sortDirection) = OrderBy::OrderSpec::Descending; } @@ -5377,7 +5411,7 @@ yyreduce: case 153: /* Line 1269 of yacc.c. */ -#line 2739 "querytransformparser.ypp" +#line 2773 "querytransformparser.ypp" { (yyval.enums.orderingEmptySequence) = parseInfo->staticContext->orderingEmptySequence(); } @@ -5385,7 +5419,7 @@ yyreduce: case 156: /* Line 1269 of yacc.c. */ -#line 2746 "querytransformparser.ypp" +#line 2780 "querytransformparser.ypp" { if(parseInfo->isXSLT()) resolveAndCheckCollation((yyvsp[(2) - (2)].sval), parseInfo, (yyloc)); @@ -5396,7 +5430,7 @@ yyreduce: case 157: /* Line 1269 of yacc.c. */ -#line 2753 "querytransformparser.ypp" +#line 2787 "querytransformparser.ypp" { /* We do nothing. We don't use collations, and we have this non-terminal * in order to accept expressions. */ @@ -5405,7 +5439,7 @@ yyreduce: case 158: /* Line 1269 of yacc.c. */ -#line 2759 "querytransformparser.ypp" +#line 2793 "querytransformparser.ypp" { parseInfo->orderStability.push(OrderBy::StableOrder); } @@ -5413,7 +5447,7 @@ yyreduce: case 159: /* Line 1269 of yacc.c. */ -#line 2763 "querytransformparser.ypp" +#line 2797 "querytransformparser.ypp" { parseInfo->orderStability.push(OrderBy::UnstableOrder); } @@ -5421,7 +5455,7 @@ yyreduce: case 162: /* Line 1269 of yacc.c. */ -#line 2771 "querytransformparser.ypp" +#line 2805 "querytransformparser.ypp" { pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5430,14 +5464,15 @@ yyreduce: case 163: /* Line 1269 of yacc.c. */ -#line 2775 "querytransformparser.ypp" +#line 2809 "querytransformparser.ypp" {(yyval.enums.slot) = parseInfo->staticContext->currentRangeSlot();} break; case 164: /* Line 1269 of yacc.c. */ -#line 2777 "querytransformparser.ypp" +#line 2811 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new QuantifiedExpression((yyvsp[(8) - (9)].enums.slot), QuantifiedExpression::Some, (yyvsp[(6) - (9)].expr), (yyvsp[(9) - (9)].expr)), (yyloc), parseInfo); parseInfo->finalizePushedVariable(); @@ -5446,7 +5481,7 @@ yyreduce: case 165: /* Line 1269 of yacc.c. */ -#line 2784 "querytransformparser.ypp" +#line 2819 "querytransformparser.ypp" { (yyval.expr) = pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5455,13 +5490,13 @@ yyreduce: case 166: /* Line 1269 of yacc.c. */ -#line 2788 "querytransformparser.ypp" +#line 2823 "querytransformparser.ypp" {(yyval.enums.slot) = parseInfo->staticContext->currentRangeSlot();} break; case 167: /* Line 1269 of yacc.c. */ -#line 2790 "querytransformparser.ypp" +#line 2825 "querytransformparser.ypp" { (yyval.expr) = create(new QuantifiedExpression((yyvsp[(8) - (9)].enums.slot), QuantifiedExpression::Some, (yyvsp[(7) - (9)].expr), (yyvsp[(9) - (9)].expr)), (yyloc), parseInfo); @@ -5471,7 +5506,7 @@ yyreduce: case 169: /* Line 1269 of yacc.c. */ -#line 2799 "querytransformparser.ypp" +#line 2834 "querytransformparser.ypp" { pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5480,14 +5515,15 @@ yyreduce: case 170: /* Line 1269 of yacc.c. */ -#line 2803 "querytransformparser.ypp" +#line 2838 "querytransformparser.ypp" {(yyval.enums.slot) = parseInfo->staticContext->currentRangeSlot();} break; case 171: /* Line 1269 of yacc.c. */ -#line 2805 "querytransformparser.ypp" +#line 2840 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new QuantifiedExpression((yyvsp[(8) - (9)].enums.slot), QuantifiedExpression::Every, (yyvsp[(6) - (9)].expr), (yyvsp[(9) - (9)].expr)), (yyloc), parseInfo); parseInfo->finalizePushedVariable(); @@ -5496,7 +5532,7 @@ yyreduce: case 172: /* Line 1269 of yacc.c. */ -#line 2812 "querytransformparser.ypp" +#line 2848 "querytransformparser.ypp" { (yyval.expr) = pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5505,13 +5541,13 @@ yyreduce: case 173: /* Line 1269 of yacc.c. */ -#line 2816 "querytransformparser.ypp" +#line 2852 "querytransformparser.ypp" {(yyval.enums.slot) = parseInfo->staticContext->currentRangeSlot();} break; case 174: /* Line 1269 of yacc.c. */ -#line 2818 "querytransformparser.ypp" +#line 2854 "querytransformparser.ypp" { (yyval.expr) = create(new QuantifiedExpression((yyvsp[(8) - (9)].enums.slot), QuantifiedExpression::Every, (yyvsp[(7) - (9)].expr), (yyvsp[(9) - (9)].expr)), (yyloc), parseInfo); @@ -5521,7 +5557,7 @@ yyreduce: case 176: /* Line 1269 of yacc.c. */ -#line 2827 "querytransformparser.ypp" +#line 2863 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -5529,7 +5565,7 @@ yyreduce: case 177: /* Line 1269 of yacc.c. */ -#line 2854 "querytransformparser.ypp" +#line 2890 "querytransformparser.ypp" { parseInfo->typeswitchSource.push((yyvsp[(3) - (4)].expr)); } @@ -5537,9 +5573,9 @@ yyreduce: case 178: /* Line 1269 of yacc.c. */ -#line 2858 "querytransformparser.ypp" +#line 2894 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); parseInfo->typeswitchSource.pop(); (yyval.expr) = (yyvsp[(6) - (6)].expr); } @@ -5547,7 +5583,7 @@ yyreduce: case 179: /* Line 1269 of yacc.c. */ -#line 2865 "querytransformparser.ypp" +#line 2901 "querytransformparser.ypp" { if(!(yyvsp[(2) - (3)].qName).isNull()) { @@ -5559,7 +5595,7 @@ yyreduce: case 180: /* Line 1269 of yacc.c. */ -#line 2873 "querytransformparser.ypp" +#line 2909 "querytransformparser.ypp" { /* The variable shouldn't be in-scope for other case branches. */ if(!(yyvsp[(2) - (6)].qName).isNull()) @@ -5569,7 +5605,7 @@ yyreduce: case 181: /* Line 1269 of yacc.c. */ -#line 2879 "querytransformparser.ypp" +#line 2915 "querytransformparser.ypp" { const Expression::Ptr instanceOf(create(new InstanceOf(parseInfo->typeswitchSource.top(), (yyvsp[(3) - (8)].sequenceType)), (yyloc), parseInfo)); (yyval.expr) = create(new IfThenClause(instanceOf, (yyvsp[(6) - (8)].expr), (yyvsp[(8) - (8)].expr)), (yyloc), parseInfo); @@ -5578,7 +5614,7 @@ yyreduce: case 184: /* Line 1269 of yacc.c. */ -#line 2888 "querytransformparser.ypp" +#line 2924 "querytransformparser.ypp" { (yyval.qName) = QXmlName(); } @@ -5586,7 +5622,7 @@ yyreduce: case 185: /* Line 1269 of yacc.c. */ -#line 2893 "querytransformparser.ypp" +#line 2929 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(2) - (3)].qName); } @@ -5594,7 +5630,7 @@ yyreduce: case 186: /* Line 1269 of yacc.c. */ -#line 2898 "querytransformparser.ypp" +#line 2934 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(3) - (3)].expr); } @@ -5602,7 +5638,7 @@ yyreduce: case 187: /* Line 1269 of yacc.c. */ -#line 2902 "querytransformparser.ypp" +#line 2938 "querytransformparser.ypp" { if(!(yyvsp[(3) - (3)].qName).isNull()) { @@ -5615,7 +5651,7 @@ yyreduce: case 188: /* Line 1269 of yacc.c. */ -#line 2911 "querytransformparser.ypp" +#line 2947 "querytransformparser.ypp" { if(!(yyvsp[(3) - (6)].qName).isNull()) parseInfo->finalizePushedVariable(); @@ -5625,107 +5661,119 @@ yyreduce: case 189: /* Line 1269 of yacc.c. */ -#line 2918 "querytransformparser.ypp" +#line 2954 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new IfThenClause((yyvsp[(3) - (8)].expr), (yyvsp[(6) - (8)].expr), (yyvsp[(8) - (8)].expr)), (yyloc), parseInfo); } break; case 191: /* Line 1269 of yacc.c. */ -#line 2924 "querytransformparser.ypp" +#line 2961 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new OrExpression((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 193: /* Line 1269 of yacc.c. */ -#line 2930 "querytransformparser.ypp" +#line 2968 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new AndExpression((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 199: /* Line 1269 of yacc.c. */ -#line 2941 "querytransformparser.ypp" +#line 2980 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new RangeExpression((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 201: /* Line 1269 of yacc.c. */ -#line 2947 "querytransformparser.ypp" +#line 2987 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new ArithmeticExpression((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.mathOperator), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 202: /* Line 1269 of yacc.c. */ -#line 2951 "querytransformparser.ypp" +#line 2992 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Add;} break; case 203: /* Line 1269 of yacc.c. */ -#line 2952 "querytransformparser.ypp" +#line 2993 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Substract;} break; case 205: /* Line 1269 of yacc.c. */ -#line 2956 "querytransformparser.ypp" +#line 2997 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new ArithmeticExpression((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.mathOperator), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 206: /* Line 1269 of yacc.c. */ -#line 2960 "querytransformparser.ypp" +#line 3002 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Multiply;} break; case 207: /* Line 1269 of yacc.c. */ -#line 2961 "querytransformparser.ypp" +#line 3003 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Div;} break; case 208: /* Line 1269 of yacc.c. */ -#line 2962 "querytransformparser.ypp" +#line 3004 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::IDiv;} break; case 209: /* Line 1269 of yacc.c. */ -#line 2963 "querytransformparser.ypp" +#line 3005 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Mod;} break; case 211: /* Line 1269 of yacc.c. */ -#line 2967 "querytransformparser.ypp" +#line 3009 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 + | QXmlQuery::XPath20 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XmlSchema11IdentityConstraintSelector), + parseInfo, (yyloc)); (yyval.expr) = create(new CombineNodes((yyvsp[(1) - (3)].expr), CombineNodes::Union, (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 213: /* Line 1269 of yacc.c. */ -#line 2973 "querytransformparser.ypp" +#line 3020 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new CombineNodes((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.combinedNodeOp), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 216: /* Line 1269 of yacc.c. */ -#line 2981 "querytransformparser.ypp" +#line 3029 "querytransformparser.ypp" { (yyval.enums.combinedNodeOp) = CombineNodes::Intersect; } @@ -5733,7 +5781,7 @@ yyreduce: case 217: /* Line 1269 of yacc.c. */ -#line 2985 "querytransformparser.ypp" +#line 3033 "querytransformparser.ypp" { (yyval.enums.combinedNodeOp) = CombineNodes::Except; } @@ -5741,48 +5789,53 @@ yyreduce: case 219: /* Line 1269 of yacc.c. */ -#line 2991 "querytransformparser.ypp" +#line 3039 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new InstanceOf((yyvsp[(1) - (4)].expr), - SequenceType::Ptr((yyvsp[(4) - (4)].sequenceType))), (yyloc), parseInfo); + SequenceType::Ptr((yyvsp[(4) - (4)].sequenceType))), (yyloc), parseInfo); } break; case 221: /* Line 1269 of yacc.c. */ -#line 2998 "querytransformparser.ypp" +#line 3047 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new TreatAs((yyvsp[(1) - (4)].expr), (yyvsp[(4) - (4)].sequenceType)), (yyloc), parseInfo); } break; case 223: /* Line 1269 of yacc.c. */ -#line 3004 "querytransformparser.ypp" +#line 3054 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new CastableAs((yyvsp[(1) - (4)].expr), (yyvsp[(4) - (4)].sequenceType)), (yyloc), parseInfo); } break; case 225: /* Line 1269 of yacc.c. */ -#line 3010 "querytransformparser.ypp" +#line 3061 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new CastAs((yyvsp[(1) - (4)].expr), (yyvsp[(4) - (4)].sequenceType)), (yyloc), parseInfo); } break; case 227: /* Line 1269 of yacc.c. */ -#line 3016 "querytransformparser.ypp" +#line 3068 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new UnaryExpression((yyvsp[(1) - (2)].enums.mathOperator), (yyvsp[(2) - (2)].expr), parseInfo->staticContext), (yyloc), parseInfo); } break; case 228: /* Line 1269 of yacc.c. */ -#line 3021 "querytransformparser.ypp" +#line 3074 "querytransformparser.ypp" { (yyval.enums.mathOperator) = AtomicMathematician::Add; } @@ -5790,7 +5843,7 @@ yyreduce: case 229: /* Line 1269 of yacc.c. */ -#line 3025 "querytransformparser.ypp" +#line 3078 "querytransformparser.ypp" { (yyval.enums.mathOperator) = AtomicMathematician::Substract; } @@ -5798,51 +5851,52 @@ yyreduce: case 233: /* Line 1269 of yacc.c. */ -#line 3034 "querytransformparser.ypp" +#line 3087 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new GeneralComparison((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.valueOperator), (yyvsp[(3) - (3)].expr), parseInfo->isBackwardsCompat.top()), (yyloc), parseInfo); } break; case 234: /* Line 1269 of yacc.c. */ -#line 3038 "querytransformparser.ypp" +#line 3092 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorEqual;} break; case 235: /* Line 1269 of yacc.c. */ -#line 3039 "querytransformparser.ypp" +#line 3093 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorNotEqual;} break; case 236: /* Line 1269 of yacc.c. */ -#line 3040 "querytransformparser.ypp" +#line 3094 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorGreaterOrEqual;} break; case 237: /* Line 1269 of yacc.c. */ -#line 3041 "querytransformparser.ypp" +#line 3095 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorGreaterThan;} break; case 238: /* Line 1269 of yacc.c. */ -#line 3042 "querytransformparser.ypp" +#line 3096 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorLessOrEqual;} break; case 239: /* Line 1269 of yacc.c. */ -#line 3043 "querytransformparser.ypp" +#line 3097 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorLessThan;} break; case 240: /* Line 1269 of yacc.c. */ -#line 3046 "querytransformparser.ypp" +#line 3100 "querytransformparser.ypp" { (yyval.expr) = create(new ValueComparison((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.valueOperator), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } @@ -5850,43 +5904,43 @@ yyreduce: case 241: /* Line 1269 of yacc.c. */ -#line 3050 "querytransformparser.ypp" +#line 3104 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorEqual;} break; case 242: /* Line 1269 of yacc.c. */ -#line 3051 "querytransformparser.ypp" +#line 3105 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorNotEqual;} break; case 243: /* Line 1269 of yacc.c. */ -#line 3052 "querytransformparser.ypp" +#line 3106 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorGreaterOrEqual;} break; case 244: /* Line 1269 of yacc.c. */ -#line 3053 "querytransformparser.ypp" +#line 3107 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorGreaterThan;} break; case 245: /* Line 1269 of yacc.c. */ -#line 3054 "querytransformparser.ypp" +#line 3108 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorLessOrEqual;} break; case 246: /* Line 1269 of yacc.c. */ -#line 3055 "querytransformparser.ypp" +#line 3109 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorLessThan;} break; case 247: /* Line 1269 of yacc.c. */ -#line 3058 "querytransformparser.ypp" +#line 3112 "querytransformparser.ypp" { (yyval.expr) = create(new NodeComparison((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.nodeOperator), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } @@ -5894,27 +5948,27 @@ yyreduce: case 248: /* Line 1269 of yacc.c. */ -#line 3062 "querytransformparser.ypp" +#line 3116 "querytransformparser.ypp" {(yyval.enums.nodeOperator) = QXmlNodeModelIndex::Is;} break; case 249: /* Line 1269 of yacc.c. */ -#line 3063 "querytransformparser.ypp" +#line 3117 "querytransformparser.ypp" {(yyval.enums.nodeOperator) = QXmlNodeModelIndex::Precedes;} break; case 250: /* Line 1269 of yacc.c. */ -#line 3064 "querytransformparser.ypp" +#line 3118 "querytransformparser.ypp" {(yyval.enums.nodeOperator) = QXmlNodeModelIndex::Follows;} break; case 251: /* Line 1269 of yacc.c. */ -#line 3067 "querytransformparser.ypp" +#line 3121 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); parseInfo->staticContext->error(QtXmlPatterns::tr("The Schema Validation Feature is not supported. " "Hence, %1-expressions may not be used.") .arg(formatKeyword("validate")), @@ -5927,26 +5981,27 @@ yyreduce: case 252: /* Line 1269 of yacc.c. */ -#line 3080 "querytransformparser.ypp" +#line 3134 "querytransformparser.ypp" {(yyval.enums.validationMode) = Validate::Strict;} break; case 253: /* Line 1269 of yacc.c. */ -#line 3081 "querytransformparser.ypp" +#line 3135 "querytransformparser.ypp" {(yyval.enums.validationMode) = Validate::Strict;} break; case 254: /* Line 1269 of yacc.c. */ -#line 3082 "querytransformparser.ypp" +#line 3136 "querytransformparser.ypp" {(yyval.enums.validationMode) = Validate::Lax;} break; case 255: /* Line 1269 of yacc.c. */ -#line 3085 "querytransformparser.ypp" +#line 3139 "querytransformparser.ypp" { + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); /* We don't support any pragmas, so we only do the * necessary validation and use the fallback expression. */ @@ -5964,7 +6019,7 @@ yyreduce: case 256: /* Line 1269 of yacc.c. */ -#line 3101 "querytransformparser.ypp" +#line 3156 "querytransformparser.ypp" { (yyval.expr).reset(); } @@ -5972,7 +6027,7 @@ yyreduce: case 257: /* Line 1269 of yacc.c. */ -#line 3105 "querytransformparser.ypp" +#line 3160 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (3)].expr); } @@ -5980,15 +6035,15 @@ yyreduce: case 260: /* Line 1269 of yacc.c. */ -#line 3113 "querytransformparser.ypp" +#line 3168 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 263: /* Line 1269 of yacc.c. */ -#line 3121 "querytransformparser.ypp" +#line 3176 "querytransformparser.ypp" { /* This is "/step". That is, fn:root(self::node()) treat as document-node()/RelativePathExpr. */ (yyval.expr) = create(new Path(createRootExpression(parseInfo, (yyloc)), (yyvsp[(2) - (2)].expr)), (yyloc), parseInfo); @@ -5997,7 +6052,7 @@ yyreduce: case 264: /* Line 1269 of yacc.c. */ -#line 3127 "querytransformparser.ypp" +#line 3182 "querytransformparser.ypp" { (yyval.expr) = createSlashSlashPath(createRootExpression(parseInfo, (yyloc)), (yyvsp[(2) - (2)].expr), (yyloc), parseInfo); } @@ -6005,7 +6060,7 @@ yyreduce: case 265: /* Line 1269 of yacc.c. */ -#line 3131 "querytransformparser.ypp" +#line 3186 "querytransformparser.ypp" { /* This is "/". That is, fn:root(self::node()) treat as document-node(). */ (yyval.expr) = createRootExpression(parseInfo, (yyloc)); @@ -6014,7 +6069,7 @@ yyreduce: case 268: /* Line 1269 of yacc.c. */ -#line 3141 "querytransformparser.ypp" +#line 3196 "querytransformparser.ypp" { (yyval.expr) = create(new Path((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), (yyvsp[(2) - (3)].enums.pathKind)), (yyloc), parseInfo); } @@ -6022,7 +6077,7 @@ yyreduce: case 269: /* Line 1269 of yacc.c. */ -#line 3145 "querytransformparser.ypp" +#line 3200 "querytransformparser.ypp" { const Expression::Ptr orderBy(createReturnOrderBy((yyvsp[(4) - (7)].orderSpecs), (yyvsp[(6) - (7)].expr), parseInfo->orderStability.pop(), (yyloc), parseInfo)); @@ -6035,7 +6090,7 @@ yyreduce: case 270: /* Line 1269 of yacc.c. */ -#line 3154 "querytransformparser.ypp" +#line 3209 "querytransformparser.ypp" { (yyval.expr) = createSlashSlashPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), (yyloc), parseInfo); } @@ -6043,7 +6098,7 @@ yyreduce: case 271: /* Line 1269 of yacc.c. */ -#line 3159 "querytransformparser.ypp" +#line 3214 "querytransformparser.ypp" { (yyval.expr) = NodeSortExpression::wrapAround((yyvsp[(1) - (1)].expr), parseInfo->staticContext); } @@ -6051,7 +6106,7 @@ yyreduce: case 273: /* Line 1269 of yacc.c. */ -#line 3164 "querytransformparser.ypp" +#line 3219 "querytransformparser.ypp" { (yyval.expr) = create(new CurrentItemStore((yyvsp[(2) - (2)].expr)), (yyloc), parseInfo); } @@ -6059,7 +6114,7 @@ yyreduce: case 274: /* Line 1269 of yacc.c. */ -#line 3168 "querytransformparser.ypp" +#line 3223 "querytransformparser.ypp" { const xsDouble version = (yyvsp[(1) - (1)].sval).toDouble(); @@ -6071,7 +6126,7 @@ yyreduce: case 275: /* Line 1269 of yacc.c. */ -#line 3176 "querytransformparser.ypp" +#line 3231 "querytransformparser.ypp" { if((yyvsp[(2) - (3)].enums.Double) < 2) (yyval.expr) = createCompatStore((yyvsp[(3) - (3)].expr), (yyloc), parseInfo); @@ -6082,8 +6137,9 @@ yyreduce: case 276: /* Line 1269 of yacc.c. */ -#line 3183 "querytransformparser.ypp" +#line 3238 "querytransformparser.ypp" { + allowedIn(QXmlQuery::XSLT20, parseInfo, (yyloc)); Q_ASSERT(!(yyvsp[(2) - (5)].sval).isEmpty()); (yyval.expr) = create(new StaticBaseURIStore((yyvsp[(2) - (5)].sval), (yyvsp[(4) - (5)].expr)), (yyloc), parseInfo); } @@ -6091,8 +6147,9 @@ yyreduce: case 277: /* Line 1269 of yacc.c. */ -#line 3189 "querytransformparser.ypp" +#line 3245 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, (yyloc)); parseInfo->resolvers.push(parseInfo->staticContext->namespaceBindings()); const NamespaceResolver::Ptr resolver(new DelegatingNamespaceResolver(parseInfo->staticContext->namespaceBindings())); resolver->addBinding(QXmlName(parseInfo->staticContext->namePool()->allocateNamespace((yyvsp[(5) - (6)].sval)), @@ -6104,7 +6161,7 @@ yyreduce: case 278: /* Line 1269 of yacc.c. */ -#line 3199 "querytransformparser.ypp" +#line 3256 "querytransformparser.ypp" { parseInfo->staticContext->setNamespaceBindings(parseInfo->resolvers.pop()); (yyval.expr) = (yyvsp[(8) - (9)].expr); @@ -6113,7 +6170,7 @@ yyreduce: case 279: /* Line 1269 of yacc.c. */ -#line 3204 "querytransformparser.ypp" +#line 3261 "querytransformparser.ypp" { (yyval.expr) = create(new CallTemplate((yyvsp[(2) - (5)].qName), parseInfo->templateWithParams), (yyloc), parseInfo); parseInfo->templateWithParametersHandled(); @@ -6123,7 +6180,7 @@ yyreduce: case 280: /* Line 1269 of yacc.c. */ -#line 3211 "querytransformparser.ypp" +#line 3268 "querytransformparser.ypp" { parseInfo->startParsingWithParam(); } @@ -6131,7 +6188,7 @@ yyreduce: case 281: /* Line 1269 of yacc.c. */ -#line 3215 "querytransformparser.ypp" +#line 3272 "querytransformparser.ypp" { parseInfo->endParsingWithParam(); } @@ -6139,42 +6196,42 @@ yyreduce: case 282: /* Line 1269 of yacc.c. */ -#line 3220 "querytransformparser.ypp" +#line 3277 "querytransformparser.ypp" { } break; case 283: /* Line 1269 of yacc.c. */ -#line 3223 "querytransformparser.ypp" +#line 3280 "querytransformparser.ypp" { } break; case 284: /* Line 1269 of yacc.c. */ -#line 3226 "querytransformparser.ypp" +#line 3283 "querytransformparser.ypp" { } break; case 285: /* Line 1269 of yacc.c. */ -#line 3230 "querytransformparser.ypp" +#line 3287 "querytransformparser.ypp" { } break; case 286: /* Line 1269 of yacc.c. */ -#line 3233 "querytransformparser.ypp" +#line 3290 "querytransformparser.ypp" { } break; case 287: /* Line 1269 of yacc.c. */ -#line 3237 "querytransformparser.ypp" +#line 3294 "querytransformparser.ypp" { /* Note, this grammar rule is invoked for @c xsl:param @em and @c * xsl:with-param. */ @@ -6242,7 +6299,7 @@ yyreduce: case 288: /* Line 1269 of yacc.c. */ -#line 3302 "querytransformparser.ypp" +#line 3359 "querytransformparser.ypp" { (yyval.enums.Bool) = false; } @@ -6250,7 +6307,7 @@ yyreduce: case 289: /* Line 1269 of yacc.c. */ -#line 3306 "querytransformparser.ypp" +#line 3363 "querytransformparser.ypp" { (yyval.enums.Bool) = true; } @@ -6258,7 +6315,7 @@ yyreduce: case 290: /* Line 1269 of yacc.c. */ -#line 3311 "querytransformparser.ypp" +#line 3368 "querytransformparser.ypp" { (yyval.expr) = Expression::Ptr(); } @@ -6266,7 +6323,7 @@ yyreduce: case 291: /* Line 1269 of yacc.c. */ -#line 3315 "querytransformparser.ypp" +#line 3372 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -6274,7 +6331,7 @@ yyreduce: case 292: /* Line 1269 of yacc.c. */ -#line 3324 "querytransformparser.ypp" +#line 3381 "querytransformparser.ypp" { (yyval.enums.pathKind) = Path::RegularPath; } @@ -6282,7 +6339,7 @@ yyreduce: case 293: /* Line 1269 of yacc.c. */ -#line 3328 "querytransformparser.ypp" +#line 3385 "querytransformparser.ypp" { (yyval.enums.pathKind) = Path::XSLTForEach; } @@ -6290,7 +6347,7 @@ yyreduce: case 294: /* Line 1269 of yacc.c. */ -#line 3332 "querytransformparser.ypp" +#line 3389 "querytransformparser.ypp" { (yyval.enums.pathKind) = Path::ForApplyTemplate; } @@ -6298,7 +6355,7 @@ yyreduce: case 296: /* Line 1269 of yacc.c. */ -#line 3338 "querytransformparser.ypp" +#line 3395 "querytransformparser.ypp" { (yyval.expr) = create(GenericPredicate::create((yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr), parseInfo->staticContext, fromYYLTYPE((yyloc), parseInfo)), (yyloc), parseInfo); } @@ -6306,7 +6363,7 @@ yyreduce: case 299: /* Line 1269 of yacc.c. */ -#line 3346 "querytransformparser.ypp" +#line 3403 "querytransformparser.ypp" { if((yyvsp[(1) - (1)].enums.axis) == QXmlNodeModelIndex::AxisAttribute) parseInfo->nodeTestSource = BuiltinTypes::attribute; @@ -6315,7 +6372,7 @@ yyreduce: case 300: /* Line 1269 of yacc.c. */ -#line 3351 "querytransformparser.ypp" +#line 3408 "querytransformparser.ypp" { if((yyvsp[(3) - (3)].itemType)) { @@ -6344,7 +6401,7 @@ yyreduce: case 304: /* Line 1269 of yacc.c. */ -#line 3381 "querytransformparser.ypp" +#line 3438 "querytransformparser.ypp" { if((yyvsp[(1) - (2)].enums.axis) == QXmlNodeModelIndex::AxisNamespace) { @@ -6356,84 +6413,114 @@ yyreduce: } else (yyval.enums.axis) = (yyvsp[(1) - (2)].enums.axis); + + switch((yyvsp[(1) - (2)].enums.axis)) + { + case QXmlNodeModelIndex::AxisAttribute: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XSLT20), + parseInfo, (yyloc)); + break; + } + case QXmlNodeModelIndex::AxisChild: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XmlSchema11IdentityConstraintSelector + | QXmlQuery::XSLT20), + parseInfo, (yyloc)); + break; + } + default: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XSLT20), + parseInfo, (yyloc)); + } + } } break; case 305: /* Line 1269 of yacc.c. */ -#line 3394 "querytransformparser.ypp" +#line 3481 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisAncestorOrSelf ;} break; case 306: /* Line 1269 of yacc.c. */ -#line 3395 "querytransformparser.ypp" +#line 3482 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisAncestor ;} break; case 307: /* Line 1269 of yacc.c. */ -#line 3396 "querytransformparser.ypp" +#line 3483 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisAttribute ;} break; case 308: /* Line 1269 of yacc.c. */ -#line 3397 "querytransformparser.ypp" +#line 3484 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisChild ;} break; case 309: /* Line 1269 of yacc.c. */ -#line 3398 "querytransformparser.ypp" +#line 3485 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisDescendantOrSelf;} break; case 310: /* Line 1269 of yacc.c. */ -#line 3399 "querytransformparser.ypp" +#line 3486 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisDescendant ;} break; case 311: /* Line 1269 of yacc.c. */ -#line 3400 "querytransformparser.ypp" +#line 3487 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisFollowing ;} break; case 312: /* Line 1269 of yacc.c. */ -#line 3401 "querytransformparser.ypp" +#line 3488 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisPreceding ;} break; case 313: /* Line 1269 of yacc.c. */ -#line 3402 "querytransformparser.ypp" +#line 3489 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisFollowingSibling;} break; case 314: /* Line 1269 of yacc.c. */ -#line 3403 "querytransformparser.ypp" +#line 3490 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisPrecedingSibling;} break; case 315: /* Line 1269 of yacc.c. */ -#line 3404 "querytransformparser.ypp" +#line 3491 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisParent ;} break; case 316: /* Line 1269 of yacc.c. */ -#line 3405 "querytransformparser.ypp" +#line 3492 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisSelf ;} break; case 317: /* Line 1269 of yacc.c. */ -#line 3408 "querytransformparser.ypp" +#line 3495 "querytransformparser.ypp" { parseInfo->nodeTestSource = BuiltinTypes::attribute; } @@ -6441,8 +6528,9 @@ yyreduce: case 318: /* Line 1269 of yacc.c. */ -#line 3412 "querytransformparser.ypp" +#line 3499 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20 | QXmlQuery::XmlSchema11IdentityConstraintField), parseInfo, (yyloc)); (yyval.expr) = create(new AxisStep(QXmlNodeModelIndex::AxisAttribute, (yyvsp[(3) - (3)].itemType)), (yyloc), parseInfo); parseInfo->restoreNodeTestSource(); @@ -6451,7 +6539,7 @@ yyreduce: case 319: /* Line 1269 of yacc.c. */ -#line 3418 "querytransformparser.ypp" +#line 3506 "querytransformparser.ypp" { ItemType::Ptr nodeTest; @@ -6466,7 +6554,7 @@ yyreduce: case 320: /* Line 1269 of yacc.c. */ -#line 3429 "querytransformparser.ypp" +#line 3517 "querytransformparser.ypp" { (yyval.expr) = create(new AxisStep(QXmlNodeModelIndex::AxisAttribute, (yyvsp[(1) - (1)].itemType)), (yyloc), parseInfo); } @@ -6474,15 +6562,23 @@ yyreduce: case 322: /* Line 1269 of yacc.c. */ -#line 3436 "querytransformparser.ypp" +#line 3524 "querytransformparser.ypp" { (yyval.expr) = create(new AxisStep(QXmlNodeModelIndex::AxisParent, BuiltinTypes::node), (yyloc), parseInfo); } break; + case 324: +/* Line 1269 of yacc.c. */ +#line 3530 "querytransformparser.ypp" + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); + } + break; + case 325: /* Line 1269 of yacc.c. */ -#line 3444 "querytransformparser.ypp" +#line 3535 "querytransformparser.ypp" { (yyval.itemType) = QNameTest::create(parseInfo->nodeTestSource, (yyvsp[(1) - (1)].qName)); } @@ -6490,7 +6586,7 @@ yyreduce: case 327: /* Line 1269 of yacc.c. */ -#line 3450 "querytransformparser.ypp" +#line 3541 "querytransformparser.ypp" { (yyval.itemType) = parseInfo->nodeTestSource; } @@ -6498,7 +6594,7 @@ yyreduce: case 328: /* Line 1269 of yacc.c. */ -#line 3454 "querytransformparser.ypp" +#line 3545 "querytransformparser.ypp" { const NamePool::Ptr np(parseInfo->staticContext->namePool()); const ReflectYYLTYPE ryy((yyloc), parseInfo); @@ -6511,8 +6607,9 @@ yyreduce: case 329: /* Line 1269 of yacc.c. */ -#line 3463 "querytransformparser.ypp" +#line 3554 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); const QXmlName::LocalNameCode c = parseInfo->staticContext->namePool()->allocateLocalName((yyvsp[(1) - (1)].sval)); (yyval.itemType) = LocalNameTest::create(parseInfo->nodeTestSource, c); } @@ -6520,15 +6617,16 @@ yyreduce: case 331: /* Line 1269 of yacc.c. */ -#line 3470 "querytransformparser.ypp" +#line 3562 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(GenericPredicate::create((yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr), parseInfo->staticContext, fromYYLTYPE((yylsp[(4) - (4)]), parseInfo)), (yyloc), parseInfo); } break; case 339: /* Line 1269 of yacc.c. */ -#line 3482 "querytransformparser.ypp" +#line 3575 "querytransformparser.ypp" { (yyval.expr) = create(new ApplyTemplate(parseInfo->modeFor((yyvsp[(2) - (5)].qName)), parseInfo->templateWithParams, @@ -6541,7 +6639,7 @@ yyreduce: case 341: /* Line 1269 of yacc.c. */ -#line 3493 "querytransformparser.ypp" +#line 3586 "querytransformparser.ypp" { (yyval.expr) = create(new Literal(AtomicString::fromValue((yyvsp[(1) - (1)].sval))), (yyloc), parseInfo); } @@ -6549,31 +6647,34 @@ yyreduce: case 342: /* Line 1269 of yacc.c. */ -#line 3498 "querytransformparser.ypp" +#line 3591 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = createNumericLiteral((yyvsp[(1) - (1)].sval), (yyloc), parseInfo); } break; case 343: /* Line 1269 of yacc.c. */ -#line 3502 "querytransformparser.ypp" +#line 3596 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = createNumericLiteral((yyvsp[(1) - (1)].sval), (yyloc), parseInfo); } break; case 344: /* Line 1269 of yacc.c. */ -#line 3507 "querytransformparser.ypp" +#line 3602 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = resolveVariable((yyvsp[(2) - (2)].qName), (yyloc), parseInfo, false); } break; case 345: /* Line 1269 of yacc.c. */ -#line 3512 "querytransformparser.ypp" +#line 3608 "querytransformparser.ypp" { /* See: http://www.w3.org/TR/xpath20/#id-variables */ (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(QString(), (yyvsp[(1) - (1)].sval)); @@ -6582,7 +6683,7 @@ yyreduce: case 346: /* Line 1269 of yacc.c. */ -#line 3517 "querytransformparser.ypp" +#line 3613 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(1) - (1)].qName); } @@ -6590,23 +6691,25 @@ yyreduce: case 347: /* Line 1269 of yacc.c. */ -#line 3522 "querytransformparser.ypp" +#line 3618 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = (yyvsp[(2) - (3)].expr); } break; case 348: /* Line 1269 of yacc.c. */ -#line 3526 "querytransformparser.ypp" +#line 3623 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new EmptySequence, (yyloc), parseInfo); } break; case 349: /* Line 1269 of yacc.c. */ -#line 3531 "querytransformparser.ypp" +#line 3629 "querytransformparser.ypp" { (yyval.expr) = create(new ContextItem(), (yyloc), parseInfo); } @@ -6614,7 +6717,7 @@ yyreduce: case 350: /* Line 1269 of yacc.c. */ -#line 3536 "querytransformparser.ypp" +#line 3634 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -6622,8 +6725,9 @@ yyreduce: case 351: /* Line 1269 of yacc.c. */ -#line 3541 "querytransformparser.ypp" +#line 3639 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); if(XPathHelper::isReservedNamespace((yyvsp[(1) - (4)].qName).namespaceURI()) || (yyvsp[(1) - (4)].qName).namespaceURI() == StandardNamespaces::InternalXSLT) { /* We got a call to a builtin function. */ const ReflectYYLTYPE ryy((yyloc), parseInfo); @@ -6653,7 +6757,7 @@ yyreduce: case 352: /* Line 1269 of yacc.c. */ -#line 3569 "querytransformparser.ypp" +#line 3668 "querytransformparser.ypp" { (yyval.expressionList) = Expression::List(); } @@ -6661,7 +6765,7 @@ yyreduce: case 353: /* Line 1269 of yacc.c. */ -#line 3574 "querytransformparser.ypp" +#line 3673 "querytransformparser.ypp" { Expression::List list; list.append((yyvsp[(1) - (1)].expr)); @@ -6671,15 +6775,15 @@ yyreduce: case 355: /* Line 1269 of yacc.c. */ -#line 3583 "querytransformparser.ypp" +#line 3682 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 360: /* Line 1269 of yacc.c. */ -#line 3624 "querytransformparser.ypp" +#line 3726 "querytransformparser.ypp" { (yyval.enums.tokenizerPosition) = parseInfo->tokenizer->commenceScanOnly(); parseInfo->scanOnlyStack.push(true); @@ -6688,7 +6792,7 @@ yyreduce: case 361: /* Line 1269 of yacc.c. */ -#line 3633 "querytransformparser.ypp" +#line 3735 "querytransformparser.ypp" { ++parseInfo->elementConstructorDepth; Expression::List constructors; @@ -6836,7 +6940,7 @@ yyreduce: case 362: /* Line 1269 of yacc.c. */ -#line 3779 "querytransformparser.ypp" +#line 3881 "querytransformparser.ypp" { /* We add the content constructor after the attribute constructors. This might result * in nested ExpressionSequences, but it will be optimized away later on. */ @@ -6935,7 +7039,7 @@ yyreduce: case 363: /* Line 1269 of yacc.c. */ -#line 3875 "querytransformparser.ypp" +#line 3977 "querytransformparser.ypp" { (yyval.expr) = create(new EmptySequence(), (yyloc), parseInfo); } @@ -6943,7 +7047,7 @@ yyreduce: case 364: /* Line 1269 of yacc.c. */ -#line 3879 "querytransformparser.ypp" +#line 3981 "querytransformparser.ypp" { if(!(yyvsp[(4) - (5)].qName).isLexicallyEqual(parseInfo->tagStack.top())) { @@ -6965,7 +7069,7 @@ yyreduce: case 365: /* Line 1269 of yacc.c. */ -#line 3898 "querytransformparser.ypp" +#line 4000 "querytransformparser.ypp" { (yyval.attributeHolders) = AttributeHolderVector(); } @@ -6973,7 +7077,7 @@ yyreduce: case 366: /* Line 1269 of yacc.c. */ -#line 3902 "querytransformparser.ypp" +#line 4004 "querytransformparser.ypp" { (yyvsp[(1) - (2)].attributeHolders).append((yyvsp[(2) - (2)].attributeHolder)); (yyval.attributeHolders) = (yyvsp[(1) - (2)].attributeHolders); @@ -6982,7 +7086,7 @@ yyreduce: case 367: /* Line 1269 of yacc.c. */ -#line 3908 "querytransformparser.ypp" +#line 4010 "querytransformparser.ypp" { (yyval.attributeHolder) = qMakePair((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].expr)); } @@ -6990,7 +7094,7 @@ yyreduce: case 368: /* Line 1269 of yacc.c. */ -#line 3913 "querytransformparser.ypp" +#line 4015 "querytransformparser.ypp" { (yyval.expr) = createDirAttributeValue((yyvsp[(2) - (3)].expressionList), parseInfo, (yyloc)); } @@ -6998,7 +7102,7 @@ yyreduce: case 369: /* Line 1269 of yacc.c. */ -#line 3918 "querytransformparser.ypp" +#line 4020 "querytransformparser.ypp" { (yyval.expr) = createDirAttributeValue((yyvsp[(2) - (3)].expressionList), parseInfo, (yyloc)); } @@ -7006,7 +7110,7 @@ yyreduce: case 370: /* Line 1269 of yacc.c. */ -#line 3923 "querytransformparser.ypp" +#line 4025 "querytransformparser.ypp" { (yyval.expressionList) = Expression::List(); } @@ -7014,7 +7118,7 @@ yyreduce: case 371: /* Line 1269 of yacc.c. */ -#line 3927 "querytransformparser.ypp" +#line 4029 "querytransformparser.ypp" { Expression::Ptr content((yyvsp[(1) - (2)].expr)); @@ -7028,7 +7132,7 @@ yyreduce: case 372: /* Line 1269 of yacc.c. */ -#line 3937 "querytransformparser.ypp" +#line 4039 "querytransformparser.ypp" { (yyvsp[(2) - (2)].expressionList).prepend(create(new Literal(AtomicString::fromValue((yyvsp[(1) - (2)].sval))), (yyloc), parseInfo)); (yyval.expressionList) = (yyvsp[(2) - (2)].expressionList); @@ -7037,7 +7141,7 @@ yyreduce: case 373: /* Line 1269 of yacc.c. */ -#line 3943 "querytransformparser.ypp" +#line 4045 "querytransformparser.ypp" { (yyval.expressionList) = Expression::List(); parseInfo->isPreviousEnclosedExpr = false; @@ -7046,7 +7150,7 @@ yyreduce: case 374: /* Line 1269 of yacc.c. */ -#line 3948 "querytransformparser.ypp" +#line 4050 "querytransformparser.ypp" { (yyvsp[(1) - (2)].expressionList).append((yyvsp[(2) - (2)].expr)); (yyval.expressionList) = (yyvsp[(1) - (2)].expressionList); @@ -7056,7 +7160,7 @@ yyreduce: case 375: /* Line 1269 of yacc.c. */ -#line 3954 "querytransformparser.ypp" +#line 4056 "querytransformparser.ypp" { if(parseInfo->staticContext->boundarySpacePolicy() == StaticContext::BSPStrip && XPathHelper::isWhitespaceOnly((yyvsp[(2) - (2)].sval))) @@ -7074,7 +7178,7 @@ yyreduce: case 376: /* Line 1269 of yacc.c. */ -#line 3968 "querytransformparser.ypp" +#line 4070 "querytransformparser.ypp" { (yyvsp[(1) - (2)].expressionList).append(create(new TextNodeConstructor(create(new Literal(AtomicString::fromValue((yyvsp[(2) - (2)].sval))), (yyloc), parseInfo)), (yyloc), parseInfo)); (yyval.expressionList) = (yyvsp[(1) - (2)].expressionList); @@ -7084,7 +7188,7 @@ yyreduce: case 377: /* Line 1269 of yacc.c. */ -#line 3974 "querytransformparser.ypp" +#line 4076 "querytransformparser.ypp" { /* We insert a text node constructor that send an empty text node between * the two enclosed expressions, in order to ensure that no space is inserted. @@ -7104,7 +7208,7 @@ yyreduce: case 378: /* Line 1269 of yacc.c. */ -#line 3991 "querytransformparser.ypp" +#line 4093 "querytransformparser.ypp" { (yyval.expr) = create(new CommentConstructor(create(new Literal(AtomicString::fromValue((yyvsp[(2) - (2)].sval))), (yyloc), parseInfo)), (yyloc), parseInfo); } @@ -7112,7 +7216,7 @@ yyreduce: case 379: /* Line 1269 of yacc.c. */ -#line 3996 "querytransformparser.ypp" +#line 4098 "querytransformparser.ypp" { const ReflectYYLTYPE ryy((yyloc), parseInfo); NCNameConstructor::validateTargetNameelementConstructorDepth; @@ -7147,10 +7251,10 @@ yyreduce: case 389: /* Line 1269 of yacc.c. */ -#line 4029 "querytransformparser.ypp" +#line 4131 "querytransformparser.ypp" { Q_ASSERT(5); - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (5)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (5)].enums.Bool)); Expression::Ptr effExpr; @@ -7184,7 +7288,7 @@ yyreduce: case 390: /* Line 1269 of yacc.c. */ -#line 4063 "querytransformparser.ypp" +#line 4165 "querytransformparser.ypp" { (yyval.enums.Bool) = false; } @@ -7192,7 +7296,7 @@ yyreduce: case 391: /* Line 1269 of yacc.c. */ -#line 4067 "querytransformparser.ypp" +#line 4169 "querytransformparser.ypp" { (yyval.enums.Bool) = true; } @@ -7200,9 +7304,9 @@ yyreduce: case 392: /* Line 1269 of yacc.c. */ -#line 4075 "querytransformparser.ypp" +#line 4177 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (4)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (4)].enums.Bool)); const Expression::Ptr name(create(new AttributeNameValidator((yyvsp[(3) - (4)].expr)), (yyloc), parseInfo)); @@ -7215,7 +7319,7 @@ yyreduce: case 393: /* Line 1269 of yacc.c. */ -#line 4087 "querytransformparser.ypp" +#line 4189 "querytransformparser.ypp" { (yyval.expr) = create(new TextNodeConstructor(createSimpleContent((yyvsp[(3) - (3)].expr), (yyloc), parseInfo)), (yyloc), parseInfo); } @@ -7223,9 +7327,9 @@ yyreduce: case 394: /* Line 1269 of yacc.c. */ -#line 4092 "querytransformparser.ypp" +#line 4194 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (3)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (3)].enums.Bool)); (yyval.expr) = create(new CommentConstructor(createSimpleContent((yyvsp[(3) - (3)].expr), (yyloc), parseInfo)), (yyloc), parseInfo); } @@ -7233,9 +7337,9 @@ yyreduce: case 395: /* Line 1269 of yacc.c. */ -#line 4099 "querytransformparser.ypp" +#line 4201 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (3)].expr)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (3)].expr)); if((yyvsp[(3) - (3)].expr)) { @@ -7248,7 +7352,7 @@ yyreduce: case 396: /* Line 1269 of yacc.c. */ -#line 4110 "querytransformparser.ypp" +#line 4212 "querytransformparser.ypp" { parseInfo->nodeTestSource = BuiltinTypes::attribute; } @@ -7256,7 +7360,7 @@ yyreduce: case 397: /* Line 1269 of yacc.c. */ -#line 4114 "querytransformparser.ypp" +#line 4216 "querytransformparser.ypp" { parseInfo->restoreNodeTestSource(); } @@ -7264,7 +7368,7 @@ yyreduce: case 398: /* Line 1269 of yacc.c. */ -#line 4117 "querytransformparser.ypp" +#line 4219 "querytransformparser.ypp" { (yyval.expr) = create(new Literal(toItem(QNameValue::fromValue(parseInfo->staticContext->namePool(), (yyvsp[(2) - (3)].qName)))), (yyloc), parseInfo); } @@ -7272,7 +7376,7 @@ yyreduce: case 400: /* Line 1269 of yacc.c. */ -#line 4123 "querytransformparser.ypp" +#line 4225 "querytransformparser.ypp" { (yyval.expr) = create(new Literal(toItem(QNameValue::fromValue(parseInfo->staticContext->namePool(), (yyvsp[(1) - (1)].qName)))), (yyloc), parseInfo); } @@ -7280,7 +7384,7 @@ yyreduce: case 402: /* Line 1269 of yacc.c. */ -#line 4129 "querytransformparser.ypp" +#line 4231 "querytransformparser.ypp" { if(BuiltinTypes::xsQName->xdtTypeMatches((yyvsp[(1) - (1)].expr)->staticType()->itemType())) (yyval.expr) = (yyvsp[(1) - (1)].expr); @@ -7295,7 +7399,7 @@ yyreduce: case 403: /* Line 1269 of yacc.c. */ -#line 4144 "querytransformparser.ypp" +#line 4246 "querytransformparser.ypp" { (yyval.expr) = create(new NCNameConstructor(create(new Literal(AtomicString::fromValue((yyvsp[(1) - (1)].sval))), (yyloc), parseInfo)), (yyloc), parseInfo); } @@ -7303,7 +7407,7 @@ yyreduce: case 404: /* Line 1269 of yacc.c. */ -#line 4148 "querytransformparser.ypp" +#line 4250 "querytransformparser.ypp" { (yyval.expr) = create(new NCNameConstructor((yyvsp[(1) - (1)].expr)), (yyloc), parseInfo); } @@ -7311,7 +7415,7 @@ yyreduce: case 405: /* Line 1269 of yacc.c. */ -#line 4157 "querytransformparser.ypp" +#line 4259 "querytransformparser.ypp" { (yyval.expr) = create(new ComputedNamespaceConstructor((yyvsp[(2) - (3)].expr), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } @@ -7319,7 +7423,7 @@ yyreduce: case 406: /* Line 1269 of yacc.c. */ -#line 4162 "querytransformparser.ypp" +#line 4264 "querytransformparser.ypp" { (yyval.sequenceType) = makeGenericSequenceType((yyvsp[(1) - (1)].itemType), Cardinality::exactlyOne()); } @@ -7327,7 +7431,7 @@ yyreduce: case 407: /* Line 1269 of yacc.c. */ -#line 4166 "querytransformparser.ypp" +#line 4268 "querytransformparser.ypp" { (yyval.sequenceType) = makeGenericSequenceType((yyvsp[(1) - (2)].itemType), Cardinality::zeroOrOne()); } @@ -7335,7 +7439,7 @@ yyreduce: case 408: /* Line 1269 of yacc.c. */ -#line 4171 "querytransformparser.ypp" +#line 4273 "querytransformparser.ypp" { (yyval.sequenceType) = CommonSequenceTypes::ZeroOrMoreItems; } @@ -7343,7 +7447,7 @@ yyreduce: case 409: /* Line 1269 of yacc.c. */ -#line 4175 "querytransformparser.ypp" +#line 4277 "querytransformparser.ypp" { (yyval.sequenceType) = (yyvsp[(2) - (2)].sequenceType); } @@ -7351,7 +7455,7 @@ yyreduce: case 410: /* Line 1269 of yacc.c. */ -#line 4180 "querytransformparser.ypp" +#line 4282 "querytransformparser.ypp" { (yyval.sequenceType) = makeGenericSequenceType((yyvsp[(1) - (2)].itemType), (yyvsp[(2) - (2)].cardinality)); } @@ -7359,7 +7463,7 @@ yyreduce: case 411: /* Line 1269 of yacc.c. */ -#line 4185 "querytransformparser.ypp" +#line 4287 "querytransformparser.ypp" { (yyval.sequenceType) = CommonSequenceTypes::Empty; } @@ -7367,31 +7471,31 @@ yyreduce: case 412: /* Line 1269 of yacc.c. */ -#line 4189 "querytransformparser.ypp" +#line 4291 "querytransformparser.ypp" {(yyval.cardinality) = Cardinality::exactlyOne();} break; case 413: /* Line 1269 of yacc.c. */ -#line 4190 "querytransformparser.ypp" +#line 4292 "querytransformparser.ypp" {(yyval.cardinality) = Cardinality::oneOrMore();} break; case 414: /* Line 1269 of yacc.c. */ -#line 4191 "querytransformparser.ypp" +#line 4293 "querytransformparser.ypp" {(yyval.cardinality) = Cardinality::zeroOrMore();} break; case 415: /* Line 1269 of yacc.c. */ -#line 4192 "querytransformparser.ypp" +#line 4294 "querytransformparser.ypp" {(yyval.cardinality) = Cardinality::zeroOrOne();} break; case 419: /* Line 1269 of yacc.c. */ -#line 4198 "querytransformparser.ypp" +#line 4300 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::item; } @@ -7399,7 +7503,7 @@ yyreduce: case 420: /* Line 1269 of yacc.c. */ -#line 4203 "querytransformparser.ypp" +#line 4305 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(1) - (1)].qName))); @@ -7435,7 +7539,7 @@ yyreduce: case 428: /* Line 1269 of yacc.c. */ -#line 4247 "querytransformparser.ypp" +#line 4349 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::node; } @@ -7443,7 +7547,7 @@ yyreduce: case 429: /* Line 1269 of yacc.c. */ -#line 4252 "querytransformparser.ypp" +#line 4354 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::document; } @@ -7451,7 +7555,7 @@ yyreduce: case 430: /* Line 1269 of yacc.c. */ -#line 4257 "querytransformparser.ypp" +#line 4359 "querytransformparser.ypp" { // TODO support for document element testing (yyval.itemType) = BuiltinTypes::document; @@ -7460,7 +7564,7 @@ yyreduce: case 433: /* Line 1269 of yacc.c. */ -#line 4266 "querytransformparser.ypp" +#line 4368 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::text; } @@ -7468,7 +7572,7 @@ yyreduce: case 434: /* Line 1269 of yacc.c. */ -#line 4271 "querytransformparser.ypp" +#line 4373 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::comment; } @@ -7476,7 +7580,7 @@ yyreduce: case 435: /* Line 1269 of yacc.c. */ -#line 4276 "querytransformparser.ypp" +#line 4378 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::pi; } @@ -7484,7 +7588,7 @@ yyreduce: case 436: /* Line 1269 of yacc.c. */ -#line 4281 "querytransformparser.ypp" +#line 4383 "querytransformparser.ypp" { (yyval.itemType) = LocalNameTest::create(BuiltinTypes::pi, parseInfo->staticContext->namePool()->allocateLocalName((yyvsp[(3) - (4)].sval))); } @@ -7492,7 +7596,7 @@ yyreduce: case 437: /* Line 1269 of yacc.c. */ -#line 4286 "querytransformparser.ypp" +#line 4388 "querytransformparser.ypp" { if(QXmlUtils::isNCName((yyvsp[(3) - (4)].sval))) { @@ -7511,7 +7615,7 @@ yyreduce: case 440: /* Line 1269 of yacc.c. */ -#line 4305 "querytransformparser.ypp" +#line 4407 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::attribute; } @@ -7519,7 +7623,7 @@ yyreduce: case 441: /* Line 1269 of yacc.c. */ -#line 4310 "querytransformparser.ypp" +#line 4412 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::attribute; } @@ -7527,7 +7631,7 @@ yyreduce: case 442: /* Line 1269 of yacc.c. */ -#line 4315 "querytransformparser.ypp" +#line 4417 "querytransformparser.ypp" { (yyval.itemType) = QNameTest::create(BuiltinTypes::attribute, (yyvsp[(3) - (4)].qName)); } @@ -7535,7 +7639,7 @@ yyreduce: case 443: /* Line 1269 of yacc.c. */ -#line 4319 "querytransformparser.ypp" +#line 4421 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(5) - (6)].qName))); @@ -7551,7 +7655,7 @@ yyreduce: case 444: /* Line 1269 of yacc.c. */ -#line 4331 "querytransformparser.ypp" +#line 4433 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(5) - (6)].qName))); @@ -7567,7 +7671,7 @@ yyreduce: case 445: /* Line 1269 of yacc.c. */ -#line 4344 "querytransformparser.ypp" +#line 4446 "querytransformparser.ypp" { parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is not in the in-scope attribute " "declarations. Note that the schema import " @@ -7580,7 +7684,7 @@ yyreduce: case 446: /* Line 1269 of yacc.c. */ -#line 4354 "querytransformparser.ypp" +#line 4456 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::element; } @@ -7588,7 +7692,7 @@ yyreduce: case 447: /* Line 1269 of yacc.c. */ -#line 4359 "querytransformparser.ypp" +#line 4461 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::element; } @@ -7596,7 +7700,7 @@ yyreduce: case 448: /* Line 1269 of yacc.c. */ -#line 4364 "querytransformparser.ypp" +#line 4466 "querytransformparser.ypp" { (yyval.itemType) = QNameTest::create(BuiltinTypes::element, (yyvsp[(3) - (4)].qName)); } @@ -7604,7 +7708,7 @@ yyreduce: case 449: /* Line 1269 of yacc.c. */ -#line 4369 "querytransformparser.ypp" +#line 4471 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(5) - (7)].qName))); @@ -7621,7 +7725,7 @@ yyreduce: case 450: /* Line 1269 of yacc.c. */ -#line 4383 "querytransformparser.ypp" +#line 4485 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(5) - (7)].qName))); @@ -7638,7 +7742,7 @@ yyreduce: case 453: /* Line 1269 of yacc.c. */ -#line 4400 "querytransformparser.ypp" +#line 4502 "querytransformparser.ypp" { parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is not in the in-scope attribute " "declarations. Note that the schema import " @@ -7651,7 +7755,7 @@ yyreduce: case 455: /* Line 1269 of yacc.c. */ -#line 4412 "querytransformparser.ypp" +#line 4514 "querytransformparser.ypp" { (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(StandardNamespaces::empty, (yyvsp[(1) - (1)].sval)); } @@ -7659,7 +7763,7 @@ yyreduce: case 457: /* Line 1269 of yacc.c. */ -#line 4424 "querytransformparser.ypp" +#line 4526 "querytransformparser.ypp" { if(parseInfo->nodeTestSource == BuiltinTypes::element) (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(parseInfo->staticContext->namespaceBindings()->lookupNamespaceURI(StandardPrefixes::empty), (yyvsp[(1) - (1)].sval)); @@ -7670,7 +7774,7 @@ yyreduce: case 462: /* Line 1269 of yacc.c. */ -#line 4438 "querytransformparser.ypp" +#line 4540 "querytransformparser.ypp" { (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(parseInfo->staticContext->defaultFunctionNamespace(), (yyvsp[(1) - (1)].sval)); } @@ -7678,7 +7782,7 @@ yyreduce: case 463: /* Line 1269 of yacc.c. */ -#line 4442 "querytransformparser.ypp" +#line 4544 "querytransformparser.ypp" { (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(StandardNamespaces::InternalXSLT, (yyvsp[(2) - (2)].sval)); } @@ -7686,7 +7790,7 @@ yyreduce: case 466: /* Line 1269 of yacc.c. */ -#line 4450 "querytransformparser.ypp" +#line 4552 "querytransformparser.ypp" { parseInfo->staticContext->error(QtXmlPatterns::tr("The name of an extension expression must be in " "a namespace."), @@ -7694,9 +7798,25 @@ yyreduce: } break; + case 469: +/* Line 1269 of yacc.c. */ +#line 4562 "querytransformparser.ypp" + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); + } + break; + + case 470: +/* Line 1269 of yacc.c. */ +#line 4566 "querytransformparser.ypp" + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); + } + break; + case 471: /* Line 1269 of yacc.c. */ -#line 4463 "querytransformparser.ypp" +#line 4571 "querytransformparser.ypp" { const ReflectYYLTYPE ryy((yyloc), parseInfo); @@ -7712,7 +7832,7 @@ yyreduce: case 472: /* Line 1269 of yacc.c. */ -#line 4475 "querytransformparser.ypp" +#line 4583 "querytransformparser.ypp" { (yyval.qName) = parseInfo->staticContext->namePool()->fromClarkName((yyvsp[(1) - (1)].sval)); } @@ -7720,7 +7840,7 @@ yyreduce: /* Line 1269 of yacc.c. */ -#line 7643 "qquerytransformparser.cpp" +#line 7763 "qquerytransformparser.cpp" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -7938,7 +8058,7 @@ yyreturn: /* Line 1486 of yacc.c. */ -#line 4479 "querytransformparser.ypp" +#line 4587 "querytransformparser.ypp" QString Tokenizer::tokenToString(const Token &token) diff --git a/src/xmlpatterns/parser/qquerytransformparser_p.h b/src/xmlpatterns/parser/qquerytransformparser_p.h index fcf8896..759c39f 100644 --- a/src/xmlpatterns/parser/qquerytransformparser_p.h +++ b/src/xmlpatterns/parser/qquerytransformparser_p.h @@ -49,6 +49,27 @@ // // We mean it. +/**************************************************************************** +** +** Copyright (C) 2009 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. + /* A Bison parser, made by GNU Bison 2.3a. */ /* Skeleton interface for Bison's Yacc-like parsers in C @@ -104,6 +125,25 @@ # undef SELF #endif +/* These tokens are defined to nothing on Windows because they're + * used in their documentation parser, for use in things like: + * + * int foo(IN char* name, OUT char* path); + * + * Hence this un-break fix. Note that this file was auto generated. */ +#ifdef IN +# undef IN +#endif +#ifdef INSTANCE +# undef INSTANCE +#endif +#ifdef STRICT +# undef STRICT +#endif +#ifdef SELF +# undef SELF +#endif + /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE diff --git a/src/xmlpatterns/parser/querytransformparser.ypp b/src/xmlpatterns/parser/querytransformparser.ypp index 93974a4..e4f6b2d 100644 --- a/src/xmlpatterns/parser/querytransformparser.ypp +++ b/src/xmlpatterns/parser/querytransformparser.ypp @@ -227,11 +227,18 @@ static inline QSourceLocation fromYYLTYPE(const YYLTYPE &sourceLocator, } /** + * @internal + * @relates QXmlQuery + */ +typedef QFlags QueryLanguages; + +/** * @short Flags invalid expressions and declarations in the currently * parsed language. * - * Since this grammar is used for several languages: XQuery 1.0, XSL-T 2.0 and - * XPath 2.0 inside XSL-T, it is the union of all the constructs in these + * Since this grammar is used for several languages: XQuery 1.0, XSL-T 2.0, and + * XPath 2.0 inside XSL-T, and field and selector patterns in W3C XML Schema's + * identity constraints, it is the union of all the constructs in these * languages. However, when dealing with each language individually, we * regularly need to disallow some expressions, such as direct element * constructors when parsing XSL-T, or the typeswitch when parsing XPath. @@ -242,19 +249,46 @@ static inline QSourceLocation fromYYLTYPE(const YYLTYPE &sourceLocator, * instance the @c let clause, should not be flagged as an error, because it's * used for internal purposes. * - * Hence, this function is called from each expression and declaration which is - * unavailable in XPath. + * Hence, this function is called from each expression and declaration with @p + * allowedLanguages stating what languages it is allowed in. * * If @p isInternal is @c true, no error is raised. Otherwise, if the current - * language is not XQuery, an error is raised. + * language is not in @p allowedLanguages, an error is raised. */ -static void disallowedConstruct(const ParserContext *const parseInfo, - const YYLTYPE &sourceLocator, - const bool isInternal = false) +static void allowedIn(const QueryLanguages allowedLanguages, + const ParserContext *const parseInfo, + const YYLTYPE &sourceLocator, + const bool isInternal = false) { - if(!isInternal && parseInfo->languageAccent != QXmlQuery::XQuery10) + /* We treat XPath 2.0 as a subset of XSL-T 2.0, so if XPath 2.0 is allowed + * and XSL-T is the language, it's ok. */ + if(!isInternal && + (!allowedLanguages.testFlag(parseInfo->languageAccent) && !(allowedLanguages.testFlag(QXmlQuery::XPath20) && parseInfo->languageAccent == QXmlQuery::XSLT20))) { - parseInfo->staticContext->error(QtXmlPatterns::tr("A construct was encountered which only is allowed in XQuery."), + + QString langName; + + switch(parseInfo->languageAccent) + { + case QXmlQuery::XPath20: + langName = QLatin1String("XPath 2.0"); + break; + case QXmlQuery::XSLT20: + langName = QLatin1String("XSL-T 2.0"); + break; + case QXmlQuery::XQuery10: + langName = QLatin1String("XQuery 1.0"); + break; + case QXmlQuery::XmlSchema11IdentityConstraintSelector: + langName = QtXmlPatterns::tr("W3C XML Schema identity constraint selector"); + break; + case QXmlQuery::XmlSchema11IdentityConstraintField: + langName = QtXmlPatterns::tr("W3C XML Schema identity constraint field"); + break; + } + + parseInfo->staticContext->error(QtXmlPatterns::tr("A construct was encountered " + "which is disallowed in the current language(%1).").arg(langName), ReportContext::XPST0003, fromYYLTYPE(sourceLocator, parseInfo)); @@ -1560,7 +1594,7 @@ Prolog: /* Empty. */ /* First part. */ | Prolog DefaultNamespaceDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("A default namespace declaration must occur before function, " "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo)); @@ -1579,7 +1613,7 @@ Prolog: /* Empty. */ } | Prolog Import { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("Module imports must occur before function, " "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo)); @@ -1597,7 +1631,7 @@ Prolog: /* Empty. */ } | Prolog OptionDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); parseInfo->hasSecondPrologPart = true; } @@ -1730,20 +1764,20 @@ TemplateName: NAME ElementName Setter: BoundarySpaceDecl /* [7] */ | DefaultCollationDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | BaseURIDecl | ConstructionDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | OrderingModeDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | EmptyOrderDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | CopyNamespacesDecl @@ -1755,7 +1789,7 @@ Separator: SEMI_COLON NamespaceDecl: DECLARE NAMESPACE NCNAME G_EQ URILiteral IsInternal Separator /* [10] */ { if(!$6) - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); if($3 == QLatin1String("xmlns")) { @@ -1867,7 +1901,7 @@ OptionDecl: DECLARE OPTION ElementName StringLiteral Separator OrderingModeDecl: DECLARE ORDERING OrderingMode Separator /* [14] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); if(parseInfo->hasDeclaration(ParserContext::OrderingModeDecl)) { parseInfo->staticContext->error(prologMessage("declare ordering"), @@ -1964,7 +1998,7 @@ DefaultCollationDecl: DECLARE DEFAULT COLLATION StringLiteral Separator BaseURIDecl: DECLARE BASEURI IsInternal URILiteral Separator /* [20] */ { - disallowedConstruct(parseInfo, @$, $3); + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, @$, $3); if(parseInfo->hasDeclaration(ParserContext::BaseURIDecl)) { parseInfo->staticContext->error(prologMessage("declare base-uri"), @@ -2026,7 +2060,7 @@ FileLocation: URILiteral VarDecl: DECLARE VARIABLE IsInternal DOLLAR VarName TypeDeclaration VariableValue OptionalDefaultValue Separator /* [24] */ { - disallowedConstruct(parseInfo, @$, $3); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $3); if(variableByName($5, parseInfo)) { parseInfo->staticContext->error(QtXmlPatterns::tr("A variable by name %1 has already " @@ -2126,7 +2160,7 @@ FunctionDecl: DECLARE FUNCTION IsInternal FunctionName LPAREN ParamList RPAREN TypeDeclaration FunctionBody Separator /* [26] */ { if(!$3) - disallowedConstruct(parseInfo, @$, $3); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $3); /* If FunctionBody is null, it is 'external', otherwise the value is the body. */ const QXmlName::NamespaceCode ns($4.namespaceURI()); @@ -2696,7 +2730,7 @@ LetClause: LET IsInternal DOLLAR VarName TypeDeclaration ASSIGN ExprSingle } LetTail /* [36] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); Q_ASSERT(parseInfo->variables.top()->name == $4); $$ = create(new LetClause($8, $9, parseInfo->variables.top()), @$, parseInfo); @@ -2835,6 +2869,7 @@ SomeQuantificationExpr: SOME DOLLAR VarName TypeDeclaration IN ExprSingle {$$ = parseInfo->staticContext->currentRangeSlot();} SomeQuantificationTail /* [X] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new QuantifiedExpression($8, QuantifiedExpression::Some, $6, $9), @$, parseInfo); parseInfo->finalizePushedVariable(); @@ -2863,6 +2898,7 @@ EveryQuantificationExpr: EVERY DOLLAR VarName TypeDeclaration IN ExprSingle {$$ = parseInfo->staticContext->currentRangeSlot();} EveryQuantificationTail /* [X] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new QuantifiedExpression($8, QuantifiedExpression::Every, $6, $9), @$, parseInfo); parseInfo->finalizePushedVariable(); @@ -2916,7 +2952,7 @@ TypeswitchExpr: TYPESWITCH LPAREN Expr RPAREN } CaseClause /* [43] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); parseInfo->typeswitchSource.pop(); $$ = $6; } @@ -2976,18 +3012,21 @@ CaseDefault: DEFAULT RETURN ExprSingle IfExpr: IF LPAREN Expr RPAREN THEN ExprSingle ELSE ExprSingle /* [45] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new IfThenClause($3, $6, $8), @$, parseInfo); } OrExpr: AndExpr /* [46] */ | OrExpr OR AndExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new OrExpression($1, $3), @$, parseInfo); } AndExpr: ComparisonExpr /* [47] */ | AndExpr AND ComparisonExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new AndExpression($1, $3), @$, parseInfo); } @@ -2999,12 +3038,14 @@ ComparisonExpr: RangeExpr RangeExpr: AdditiveExpr /* [49] */ | AdditiveExpr TO AdditiveExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new RangeExpression($1, $3), @$, parseInfo); } AdditiveExpr: MultiplicativeExpr /* [50] */ | AdditiveExpr AdditiveOperator MultiplicativeExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new ArithmeticExpression($1, $2, $3), @$, parseInfo); } @@ -3014,6 +3055,7 @@ AdditiveOperator: PLUS {$$ = AtomicMathematician::Add;} MultiplicativeExpr: UnionExpr /* [51] */ | MultiplicativeExpr MultiplyOperator UnionExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new ArithmeticExpression($1, $2, $3), @$, parseInfo); } @@ -3025,12 +3067,18 @@ MultiplyOperator: STAR {$$ = AtomicMathematician::Multiply;} UnionExpr: IntersectExceptExpr /* [52] */ | UnionExpr UnionOperator IntersectExceptExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 + | QXmlQuery::XPath20 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XmlSchema11IdentityConstraintSelector), + parseInfo, @$); $$ = create(new CombineNodes($1, CombineNodes::Union, $3), @$, parseInfo); } IntersectExceptExpr: InstanceOfExpr /* [53] */ | IntersectExceptExpr IntersectOperator InstanceOfExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new CombineNodes($1, $2, $3), @$, parseInfo); } @@ -3049,31 +3097,36 @@ IntersectOperator: INTERSECT InstanceOfExpr: TreatExpr /* [54] */ | TreatExpr INSTANCE OF SequenceType { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new InstanceOf($1, - SequenceType::Ptr($4)), @$, parseInfo); + SequenceType::Ptr($4)), @$, parseInfo); } TreatExpr: CastableExpr /* [55] */ | CastableExpr TREAT AS SequenceType { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new TreatAs($1, $4), @$, parseInfo); } CastableExpr: CastExpr /* [56] */ | CastExpr CASTABLE AS SingleType { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new CastableAs($1, $4), @$, parseInfo); } CastExpr: UnaryExpr /* [57] */ | UnaryExpr CAST AS SingleType { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new CastAs($1, $4), @$, parseInfo); } UnaryExpr: ValueExpr /* [58] */ | UnaryOperator UnaryExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new UnaryExpression($1, $2, parseInfo->staticContext), @$, parseInfo); } @@ -3092,6 +3145,7 @@ ValueExpr: ValidateExpr GeneralComp: RangeExpr GeneralComparisonOperator RangeExpr /* [60] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new GeneralComparison($1, $2, $3, parseInfo->isBackwardsCompat.top()), @$, parseInfo); } @@ -3125,7 +3179,7 @@ NodeOperator: IS {$$ = QXmlNodeModelIndex::Is;} ValidateExpr: ValidationMode EnclosedExpr /* [63] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); parseInfo->staticContext->error(QtXmlPatterns::tr("The Schema Validation Feature is not supported. " "Hence, %1-expressions may not be used.") .arg(formatKeyword("validate")), @@ -3143,6 +3197,7 @@ ValidationMode: VALIDATE {$$ = Validate::Strict;} ExtensionExpr: Pragmas EnclosedOptionalExpr /* [65] */ { + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); /* We don't support any pragmas, so we only do the * necessary validation and use the fallback expression. */ @@ -3171,7 +3226,7 @@ Pragmas: Pragmas Pragma Pragma: PRAGMA_START PragmaName PragmaContents PRAGMA_END /* [66] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } PragmaContents: /* empty */ /* [67] */ @@ -3241,12 +3296,14 @@ StepExpr: FilteredAxisStep } | BASEURI StringLiteral CURLY_LBRACE Expr CURLY_RBRACE /* [X] */ { + allowedIn(QXmlQuery::XSLT20, parseInfo, @$); Q_ASSERT(!$2.isEmpty()); $$ = create(new StaticBaseURIStore($2, $4), @$, parseInfo); } | DECLARE NAMESPACE NCNAME G_EQ STRING_LITERAL CURLY_LBRACE /* [X] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, @$); parseInfo->resolvers.push(parseInfo->staticContext->namespaceBindings()); const NamespaceResolver::Ptr resolver(new DelegatingNamespaceResolver(parseInfo->staticContext->namespaceBindings())); resolver->addBinding(QXmlName(parseInfo->staticContext->namePool()->allocateNamespace($5), @@ -3449,6 +3506,36 @@ Axis: AxisToken COLONCOLON } else $$ = $1; + + switch($1) + { + case QXmlNodeModelIndex::AxisAttribute: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XSLT20), + parseInfo, @$); + break; + } + case QXmlNodeModelIndex::AxisChild: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XmlSchema11IdentityConstraintSelector + | QXmlQuery::XSLT20), + parseInfo, @$); + break; + } + default: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XSLT20), + parseInfo, @$); + } + } } AxisToken: ANCESTOR_OR_SELF {$$ = QXmlNodeModelIndex::AxisAncestorOrSelf ;} @@ -3470,6 +3557,7 @@ AbbrevForwardStep: AT_SIGN } NodeTest /* [72] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20 | QXmlQuery::XmlSchema11IdentityConstraintField), parseInfo, @$); $$ = create(new AxisStep(QXmlNodeModelIndex::AxisAttribute, $3), @$, parseInfo); parseInfo->restoreNodeTestSource(); @@ -3499,6 +3587,9 @@ AbbrevReverseStep: DOTDOT NodeTest: NameTest /* [78] */ | KindTest + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); + } NameTest: ElementName /* [79] */ { @@ -3521,6 +3612,7 @@ WildCard: STAR } | ANY_PREFIX { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); const QXmlName::LocalNameCode c = parseInfo->staticContext->namePool()->allocateLocalName($1); $$ = LocalNameTest::create(parseInfo->nodeTestSource, c); } @@ -3528,6 +3620,7 @@ WildCard: STAR FilterExpr: PrimaryExpr /* [81] */ | FilterExpr LBRACKET Expr RBRACKET { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(GenericPredicate::create($1, $3, parseInfo->staticContext, fromYYLTYPE(@4, parseInfo)), @$, parseInfo); } @@ -3556,15 +3649,18 @@ Literal: NumericLiteral NumericLiteral: XPATH2_NUMBER /* [86] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = createNumericLiteral($1, @$, parseInfo); } | NUMBER { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = createNumericLiteral($1, @$, parseInfo); } VarRef: DOLLAR VarName /* [87] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = resolveVariable($2, @$, parseInfo, false); } @@ -3580,10 +3676,12 @@ VarName: NCNAME ParenthesizedExpr: LPAREN Expr RPAREN /* [89] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = $2; } | LPAREN RPAREN { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new EmptySequence, @$, parseInfo); } @@ -3599,6 +3697,7 @@ OrderingExpr: OrderingMode EnclosedExpr FunctionCallExpr: FunctionName LPAREN FunctionArguments RPAREN /* [93] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); if(XPathHelper::isReservedNamespace($1.namespaceURI()) || $1.namespaceURI() == StandardNamespaces::InternalXSLT) { /* We got a call to a builtin function. */ const ReflectYYLTYPE ryy(@$, parseInfo); @@ -3641,9 +3740,12 @@ FunctionArguments: /* empty */ Constructor: DirectConstructor /* [94] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | ComputedConstructor +/* The reason we cannot call alloweIn() as the action for ComputedConstructor, + * is that we use the computed constructors for XSL-T, and therefore generate + * INTERNAL tokens. */ DirectConstructor: DirElemConstructor /* [95] */ | DirCommentConstructor @@ -4075,7 +4177,7 @@ ComputedConstructor: CompDocConstructor CompDocConstructor: DOCUMENT IsInternal EnclosedExpr /* [110] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); $$ = create(new DocumentConstructor($3), @$, parseInfo); } @@ -4088,7 +4190,7 @@ CompElemConstructor: ELEMENT IsInternal CompElementName EnclosedOptionalExpr /* [111] */ { Q_ASSERT(5); - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); Expression::Ptr effExpr; @@ -4133,7 +4235,7 @@ CompAttrConstructor: ATTRIBUTE CompAttributeName EnclosedOptionalExpr /* [113] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); const Expression::Ptr name(create(new AttributeNameValidator($3), @$, parseInfo)); @@ -4150,14 +4252,14 @@ CompTextConstructor: TEXT IsInternal EnclosedExpr CompCommentConstructor: COMMENT IsInternal EnclosedExpr /* [115] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); $$ = create(new CommentConstructor(createSimpleContent($3, @$, parseInfo)), @$, parseInfo); } CompPIConstructor: PROCESSING_INSTRUCTION CompPIName EnclosedOptionalExpr /* [116] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); if($3) { @@ -4517,7 +4619,13 @@ PragmaName: NCNAME URILiteral: StringLiteral /* [140] */ StringLiteral: STRING_LITERAL /* [144] */ + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); + } | XPATH2_STRING_LITERAL + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); + } QName: QNAME /* [154] */ { diff --git a/src/xmlpatterns/schema/.gitignore b/src/xmlpatterns/schema/.gitignore new file mode 100644 index 0000000..2b29f27 --- /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 0000000..fb43d78 --- /dev/null +++ b/src/xmlpatterns/schema/builtinschemas.qrc @@ -0,0 +1,5 @@ + + + schemas/xml.xsd + + diff --git a/src/xmlpatterns/schema/doc/All_diagram.dot b/src/xmlpatterns/schema/doc/All_diagram.dot new file mode 100644 index 0000000..3352b723 --- /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 0000000..2119c49 --- /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 0000000..260b6f7 --- /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 0000000..d252ebd --- /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 0000000..f54063f --- /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 0000000..7093bef --- /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 0000000..7b32016 --- /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 0000000..6131612 --- /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 0000000..bfda892 --- /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 0000000..949c27e --- /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 0000000..61e7d14 --- /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 0000000..91be76b --- /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 0000000..1c597b3 --- /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 0000000..5e098b3 --- /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 0000000..25a1a43 --- /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 0000000..05e40b7 --- /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 0000000..20447a7 --- /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 0000000..ccb7f54 --- /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 0000000..3484bc3 --- /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 0000000..357e4c9 --- /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 0000000..ff425b9 --- /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 0000000..bbc09cd --- /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 0000000..1f9205b --- /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 0000000..44cc698 --- /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 0000000..88f1b61 --- /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 0000000..b01f0cf --- /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 0000000..b16c47f --- /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 0000000..92c54b7 --- /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 0000000..397397a --- /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 0000000..0dc7f39 --- /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 0000000..ac13305 --- /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 0000000..28364f7 --- /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 0000000..9e2c265 --- /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 0000000..d565217 --- /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 0000000..d3b3f1f --- /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 0000000..e5ca65d --- /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 0000000..1dcced4 --- /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 0000000..1754f67 --- /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 0000000..6d9a289 --- /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 0000000..951f26a --- /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 0000000..448451a --- /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 0000000..794d74c --- /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 0000000..ba4871d --- /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 0000000..fd08872 --- /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 0000000..c32f69f --- /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 0000000..7d39337 --- /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 0000000..f3e93dc --- /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 0000000..9172744 --- /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 0000000..3ceebfd --- /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 0000000..75b0b71 --- /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 0000000..c996329 --- /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 0000000..09cb041 --- /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 0000000..0ef4cd6 --- /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 0000000..d6c1865 --- /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 0000000..5b1d098 --- /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 0000000..596403c --- /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 0000000..4f5792e --- /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 0000000..00698d6 --- /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 NamespaceSupport::namespaceBindings() const +{ + QList bindings; + + QHashIterator 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 0000000..d338eae --- /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 +#include +#include +#include +#include + +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 + */ + 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 namespaceBindings() const; + + private: + typedef QHash NamespaceHash; + + NamePool::Ptr m_namePool; + QStack 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 0000000..f3f589a --- /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 0000000..451441e --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD alternative object. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAlternative : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the xpath @p test of the alternative. + * + * @see Test Definition + */ + 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 Type Definition + */ + 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 0000000..a29b5c4 --- /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 0000000..251b252 --- /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 + */ + 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 0000000..0a9dc04 --- /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::Ptr &id) +{ + m_id = id; +} + +DerivedString::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 0000000..8c23bae --- /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 annotation object of a XML schema as described + * here. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAnnotation : public NamedSchemaComponent + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the @p id of the annotation. + */ + void setId(const DerivedString::Ptr &id); + + /** + * Returns the @p id of the annotation. + */ + DerivedString::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::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 0000000..5669220 --- /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 0000000..30839d3 --- /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 appinfo component of an annotation object + * of a XML schema as described here. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdApplicationInformation : public NamedSchemaComponent + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList 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 0000000..f6cbf81 --- /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 0000000..0ae5ff6 --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD assertion object. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + * @see Assertion Definition + */ + class XsdAssertion : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the @p test of the assertion. + * + * @see Test Definition + */ + 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 0000000..6cf60ec --- /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 0000000..46d7355 --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD attribute object. + * + * This class represents the attribute object of a XML schema as described + * here. + * + * It contains information from either a top-level attribute declaration (as child of + * a schema object) or of a local attribute declaration (as child of complexType + * or attributeGroup object without a 'ref' attribute). + * + * All other occurrences of the attribute object are represented by the XsdAttributeUse class. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAttribute : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * @short Describes the scope of an attribute. + * + * @see Scope Definition + */ + class Scope : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the scope of an attribute. + */ + enum Variety + { + Global, ///< The attribute is defined globally as child of the schema 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 Variety Definition + */ + 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 Parent Definition + */ + 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 Value Constraint Definition + */ + class ValueConstraint : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the value constraint 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 Variety Definition + */ + void setVariety(Variety variety); + + /** + * Returns the variety of the attribute value constraint. + */ + Variety variety() const; + + /** + * Sets the @p value of the constraint. + * + * @see Value Definition + */ + void setValue(const QString &value); + + /** + * Returns the value of the constraint. + */ + QString value() const; + + /** + * Sets the lexical @p form of the constraint. + * + * @see Lexical Form Definition + */ + 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 Simple Type Definition + */ + 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 Scope Definition + */ + 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 Value Constraint Definition + */ + 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 0000000..8f2a47e --- /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 0000000..7a3bd79 --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents the XSD attributeGroup object. + * + * This class represents the attributeGroup object of a XML schema as described + * here. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAttributeGroup : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the list of attribute @p uses that are defined in the attribute group. + * + * @see Attribute Uses + */ + 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 Attribute Wildcard + */ + 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 0000000..3c36a4e --- /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 0000000..be48b3a --- /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 + +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 + */ + class XsdAttributeReference : public XsdAttributeUse + { + public: + typedef QExplicitlySharedDataPointer 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 0000000..a9c3898 --- /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 0000000..507df32 --- /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 + */ + class XsdAttributeTerm : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer 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 0000000..96d81bc --- /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 0000000..86021e1 --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD attribute use object. + * + * This class represents the attribute use object of a XML schema as described + * here. + * + * It contains information from a local attribute declaration (as child of complexType + * or attributeGroup object). + * + * All other occurrences of the attribute object are represented by the XsdAttribute class. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAttributeUse : public XsdAttributeTerm + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Describes the value constraint of an attribute use. + * + * @see Value Constraint Definition + */ + class ValueConstraint : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the value constraint 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 Required Definition + */ + 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 Attribute Declaration + */ + 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 0000000..ddc9110 --- /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 0000000..078c8f0 --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD complexType object. + * + * This class represents the complexType object of a XML schema as described + * here. + * + * It contains information from either a top-level complex type declaration (as child of a schema object) + * or a local complex type declaration (as descendant of an element object). + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdComplexType : public XsdUserSchemaType + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * @short Describes the open content object of a complex type. + * + * @see Open Content Definition + */ + class OpenContent : public QSharedData, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the mode of the open content. + * + * @see Mode Definition + */ + enum Mode + { + None, + Interleave, + Suffix + }; + + /** + * Sets the @p mode of the open content. + * + * @see Mode Definition + */ + void setMode(Mode mode); + + /** + * Returns the mode of the open content. + */ + Mode mode() const; + + /** + * Sets the @p wildcard of the open content. + * + * @see Wildcard Definition + */ + 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 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 Variety Definition + */ + 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 Particle Declaration + */ + 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 Open Content Declaration + */ + 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 Simple Type Definition + */ + 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 Base Type Definition + */ + 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 Derivation Method Definition + * @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 Abstract Definition + */ + 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 Attribute Uses Declaration + */ + 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 Attribute Wildcard Declaration + */ + 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 Prohibited Substitutions Definition + */ + 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 Assertions Definition + */ + void setAssertions(const XsdAssertion::List &assertions); + + /** + * Adds an @p assertion to the complex type. + * + * @see Assertions Definition + */ + 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 0000000..4994143 --- /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::Ptr &language) +{ + m_language = language; +} + +DerivedString::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 0000000..c44a2bb --- /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 documentation component of an annotation object + * of a XML schema as described here. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdDocumentation : public NamedSchemaComponent + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList 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::Ptr &language); + + /** + * Returns the language of the documentation. + */ + DerivedString::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::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 0000000..2b8ccab --- /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 0000000..e571687 --- /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 +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD element object. + * + * This class represents the element object of a XML schema as described + * here. + * + * It contains information from either a top-level element declaration (as child of a schema object) + * or a local element declaration (as descendant of an complexType object). + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdElement : public XsdTerm + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + + /** + * Describes the constraint type 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 Scope Definition + */ + class Scope : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the scope of an attribute. + */ + enum Variety + { + Global, ///< The element is defined globally as child of the schema 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 Type Table Definition + */ + class TypeTable : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer 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 Value Constraint Definition + */ + class ValueConstraint : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the value constraint 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 Type Definition + */ + void setType(const SchemaType::Ptr &type); + + /** + * Returns the type of the element. + */ + SchemaType::Ptr type() const; + + /** + * Sets the @p scope of the element. + * + * @see Scope Definition + */ + 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 Value Constraint Definition + */ + 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 Type Table Definition + */ + 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 Abstract Definition + */ + void setIsAbstract(bool abstract); + + /** + * Returns whether the element is abstract. + */ + bool isAbstract() const; + + /** + * Sets whether the element is @p nillable. + * + * @see Nillable Definition + */ + 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 Disallowed Substitutions Definition + */ + 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 Substitution Group Exclusions Definition + */ + 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 Identity Constraint Definition + */ + 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 Substitution Group Affiliations + */ + 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 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 0000000..513eee8 --- /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 0000000..f1f8110 --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD facet object. + * + * This class represents one of the following XML schema objects: + * + * + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdFacet : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the type of the facet. + */ + enum Type + { + None = 0, ///< An invalid facet. + Length = 1 << 0, ///< Match the exact length (Length Definition) + MinimumLength = 1 << 1, ///< Match the minimum length (Minimum Length Definition) + MaximumLength = 1 << 2, ///< Match the maximum length (Maximum Length Definition) + Pattern = 1 << 3, ///< Match a regular expression (Pattern Definition) + WhiteSpace = 1 << 4, ///< Match a whitespace rule (White Space Definition) + MaximumInclusive = 1 << 5, ///< Match a maximum inclusive (Maximum Inclusive Definition) + MaximumExclusive = 1 << 6, ///< Match a maximum exclusive (Maximum Exclusive Definition) + MinimumInclusive = 1 << 7, ///< Match a minimum inclusive (Minimum Inclusive Definition) + MinimumExclusive = 1 << 8, ///< Match a minimum exclusive (Minimum Exclusive Definition) + TotalDigits = 1 << 9, ///< Match some integer digits (Total Digits Definition) + FractionDigits = 1 << 10, ///< Match some double digits (Fraction Digits Definition) + Enumeration = 1 << 11, ///< Match an enumeration (Enumeration Definition) + Assertion = 1 << 12, ///< Match an assertion (Assertion Definition) + }; + typedef QHash Hash; + typedef QHashIterator 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 0000000..d4a7b64 --- /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 +#include + +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 0000000..b1d3c0f --- /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 +#include +#include +#include + +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 + */ + class XsdIdCache : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer 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 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 0000000..70980cb --- /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::Ptr string = DerivedString::fromLexical(namePool, m_data); + const DerivedString::Ptr otherString = DerivedString::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 TargetNode::fieldItems() const +{ + QVector 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 0000000..3034292 --- /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 + +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 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 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 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 0000000..e72a005 --- /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 0000000..6870b1e --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD identity constraint object. + * + * This class represents the identity constraint object of a XML schema as described + * here. + * + * It contains information from either a key object, a keyref object or an + * unique object. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdIdentityConstraint : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Describes the category 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 + */ + 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 + */ + 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 + */ + 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 0000000..81c40c9 --- /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 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 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 0000000..9df02d6 --- /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 + */ + class XsdInstanceReader + { + public: + typedef QExplicitlySharedDataPointer 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 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 namespaceBindings(const QXmlNodeModelIndex &index) const; + + /** + * The shared schema context. + */ + XsdSchemaContext::Ptr m_context; + + private: + PullBridge m_model; + QHash m_cachedAttributes; + QHash 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 0000000..1245822 --- /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 0000000..b7b59ac --- /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 class QList; + +namespace QPatternist +{ + /** + * @short Represents a XSD model group object. + * + * This class represents the model group object of a XML schema as described + * here. + * + * It contains information from either a sequence object, a choice object or an + * all object. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdModelGroup : public XsdTerm + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Describes the compositor 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 Particles Definition + */ + 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 0000000..cfa0cd3 --- /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::Ptr &id) +{ + m_publicId = id; +} + +DerivedString::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 0000000..dc1d597 --- /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 + +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 notation object of a XML schema as described + * here. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdNotation : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the public @p identifier of the notation. + * + * @see Public Identifier Definition + */ + void setPublicId(const DerivedString::Ptr &identifier); + + /** + * Returns the public identifier of the notation. + */ + DerivedString::Ptr publicId() const; + + /** + * Sets the system @p identifier of the notation. + * + * @see System Identifier Definition + */ + void setSystemId(const AnyURI::Ptr &identifier); + + /** + * Returns the system identifier of the notation. + */ + AnyURI::Ptr systemId() const; + + private: + DerivedString::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 0000000..a2671fa --- /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 0000000..61e3eb3 --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD particle object. + * + * This class represents the particle object of a XML schema as described + * here. + * + * It contains information about the number of occurrence and a reference to + * either an element object, a group object or an any object. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdParticle : public NamedSchemaComponent + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Creates a new particle object. + */ + XsdParticle(); + + /** + * Sets the minimum @p occurrence of the particle. + * + * @see Minimum Occurrence Definition + */ + 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 Maximum Occurrence Definition + */ + 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 Maximum Occurrence Definition + */ + 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 Term Definition + */ + 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 0000000..1bdef00 --- /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 + +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::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 &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(), 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 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 stateMachine(namePool); + + XsdStateMachineBuilder builder(&stateMachine, namePool); + const XsdStateMachine::StateId endState = builder.reset(); + const XsdStateMachine::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 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::StateId, XsdStateMachine::StateType> states = dfa.states(); + const QHash::StateId, QHash::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::StateId, XsdStateMachine::StateType> stateIt(states); + while (stateIt.hasNext()) { // iterate over all states + stateIt.next(); + + // fetch all transitions the current state allows + const QHash::StateId> > currentTransitions = transitions.value(stateIt.key()); + QHashIterator::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::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 baseStateMachine(namePool); + XsdStateMachine derivedStateMachine(namePool); + + // build up state machines for both particles + { + XsdStateMachineBuilder builder(&baseStateMachine, namePool); + const XsdStateMachine::StateId endState = builder.reset(); + const XsdStateMachine::StateId startState = builder.buildParticle(particle, endState); + builder.addStartState(startState); + + baseStateMachine = baseStateMachine.toDFA(); + } + { + XsdStateMachineBuilder builder(&derivedStateMachine, namePool); + const XsdStateMachine::StateId endState = builder.reset(); + const XsdStateMachine::StateId startState = builder.buildParticle(derivedParticle, endState); + builder.addStartState(startState); + + derivedStateMachine = derivedStateMachine.toDFA(); + } + + QHash 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::StateId baseStartState = baseStateMachine.startState(); + const QHash::StateId, XsdStateMachine::StateType> baseStates = baseStateMachine.states(); + const QHash::StateId, QHash::StateId> > > baseTransitions = baseStateMachine.transitions(); + + const XsdStateMachine::StateId derivedStartState = derivedStateMachine.startState(); + const QHash::StateId, XsdStateMachine::StateType> derivedStates = derivedStateMachine.states(); + const QHash::StateId, QHash::StateId> > > derivedTransitions = derivedStateMachine.transitions(); + + // @see http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html#S2.3.1 + + // define working set + QList::StateId, XsdStateMachine::StateId> > workSet; + QList::StateId, XsdStateMachine::StateId> > processedSet; + + // 1) fill working set initially with start states + workSet.append(qMakePair::StateId, XsdStateMachine::StateId>(baseStartState, derivedStartState)); + processedSet.append(qMakePair::StateId, XsdStateMachine::StateId>(baseStartState, derivedStartState)); + + while (!workSet.isEmpty()) { // while there are state sets to process + + // 3) dequeue on state set + const QPair::StateId, XsdStateMachine::StateId> set = workSet.takeFirst(); + + const QHash::StateId> > derivedTrans = derivedTransitions.value(set.second); + QHashIterator::StateId> > derivedIt(derivedTrans); + + const QHash::StateId> > baseTrans = baseTransitions.value(set.first); + + while (derivedIt.hasNext()) { + derivedIt.next(); + + bool found = false; + QHashIterator::StateId> > baseIt(baseTrans); + while (baseIt.hasNext()) { + baseIt.next(); + if (derivedTermValid(baseIt.key(), derivedIt.key(), particlesHash, context, errorMsg)) { + const QPair::StateId, XsdStateMachine::StateId> endSet = + qMakePair::StateId, XsdStateMachine::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::StateId, XsdStateMachine::StateType> it(derivedStates); + while (it.hasNext()) { + it.next(); + + if (it.value() == XsdStateMachine::EndState || it.value() == XsdStateMachine::StartEndState) { + for (int i = 0; i < processedSet.count(); ++i) { + if (processedSet.at(i).second == it.key() && + (baseStates.value(processedSet.at(i).first) != XsdStateMachine::EndState && + baseStates.value(processedSet.at(i).first) != XsdStateMachine::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 0000000..16a8d95 --- /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 + */ + 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 0000000..0a934dd --- /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 0000000..afcca25 --- /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 + +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 + */ + class XsdReference : public XsdTerm + { + public: + typedef QExplicitlySharedDataPointer 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 0000000..260b06b --- /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 +#include + +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 ¬ation) +{ + 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 0000000..b41a2d5 --- /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 +#include + +/** + * @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 schema object, are called top-level objects. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSchema : public QSharedData, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList 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 Element Declaration + */ + 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 Attribute Declaration + */ + 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 Simple Type Declaration + * @see Complex Type Declaration + */ + 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 Attribute Group Declaration + */ + 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 Element Group Declaration + */ + 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 Notation Declaration + */ + void addNotation(const XsdNotation::Ptr ¬ation); + + /** + * 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 m_elements; + QHash m_attributes; + QHash m_types; + QHash m_anonymousTypes; + QHash m_attributeGroups; + QHash m_elementGroups; + QHash m_notations; + QHash 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 0000000..2a64327 --- /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 &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 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 &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 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 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::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::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::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::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::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::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::Ptr minLengthValue = minLengthFacet->value(); + + if (facets.contains(XsdFacet::MaximumLength)) { + const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength); + const DerivedInteger::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::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::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::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::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(), 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 >()->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::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::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::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::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::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::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::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 allowedFacets = m_allowedAtomicFacets.value(primitiveTypeName); + QSet 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::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::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 elements = collectAllElements(m_schema); + QSetIterator 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(), 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 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(), 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 0000000..98c4c63 --- /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 collectAllElements(const XsdParticle::Ptr &particle) +{ + QSet 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 collectAllElements(const XsdSchema::Ptr &schema) +{ + QSet 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 0000000..65fb87f --- /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 + +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 + */ + class XsdSchemaChecker : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer 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 &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 &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 DuplicatedElementMap; + + /** + * A map used to find duplicated wildcards inside a model group. + */ + typedef QHash 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 m_context; + NamePool::Ptr m_namePool; + XsdSchema::Ptr m_schema; + QHash > m_allowedAtomicFacets; + QHash 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 0000000..b027129 --- /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 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 facets; + facets << XsdFacet::Pattern + << XsdFacet::WhiteSpace + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsBoolean->name(m_namePool), facets); + } + + // float + { + QSet 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 0000000..57736bd --- /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 XsdSchemaContext::setupBuiltinTypesFacetList() const +{ + QHash hash; + + const XsdFacet::Ptr fixedCollapseWhiteSpace(new XsdFacet()); + fixedCollapseWhiteSpace->setType(XsdFacet::WhiteSpace); + fixedCollapseWhiteSpace->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse))); + fixedCollapseWhiteSpace->setFixed(true); + + const XsdFacet::Ptr collapseWhiteSpace(new XsdFacet()); + collapseWhiteSpace->setType(XsdFacet::WhiteSpace); + collapseWhiteSpace->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse))); + collapseWhiteSpace->setFixed(false); + + const XsdFacet::Ptr preserveWhiteSpace(new XsdFacet()); + preserveWhiteSpace->setType(XsdFacet::WhiteSpace); + preserveWhiteSpace->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Preserve))); + preserveWhiteSpace->setFixed(false); + + const XsdFacet::Ptr replaceWhiteSpace(new XsdFacet()); + replaceWhiteSpace->setType(XsdFacet::WhiteSpace); + replaceWhiteSpace->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Replace))); + replaceWhiteSpace->setFixed(false); + + const XsdFacet::Ptr fixedZeroFractionDigits(new XsdFacet()); + fixedZeroFractionDigits->setType(XsdFacet::FractionDigits); + fixedZeroFractionDigits->setValue(DerivedInteger::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::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::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::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::fromLexical(m_namePool, QString::fromLatin1("\\i\\c*")); + patterns << DerivedString::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::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::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::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::fromLexical(m_namePool, QString::fromLatin1("9223372036854775807"))); + facets.insert(maxInclusive->type(), maxInclusive); + + const XsdFacet::Ptr minInclusive(new XsdFacet()); + minInclusive->setType(XsdFacet::MinimumInclusive); + minInclusive->setValue(DerivedString::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::fromLexical(m_namePool, QString::fromLatin1("2147483647"))); + facets.insert(maxInclusive->type(), maxInclusive); + + const XsdFacet::Ptr minInclusive(new XsdFacet()); + minInclusive->setType(XsdFacet::MinimumInclusive); + minInclusive->setValue(DerivedString::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::fromLexical(m_namePool, QString::fromLatin1("32767"))); + facets.insert(maxInclusive->type(), maxInclusive); + + const XsdFacet::Ptr minInclusive(new XsdFacet()); + minInclusive->setType(XsdFacet::MinimumInclusive); + minInclusive->setValue(DerivedString::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::fromLexical(m_namePool, QString::fromLatin1("127"))); + facets.insert(maxInclusive->type(), maxInclusive); + + const XsdFacet::Ptr minInclusive(new XsdFacet()); + minInclusive->setType(XsdFacet::MinimumInclusive); + minInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("-128"))); + facets.insert(minInclusive->type(), minInclusive); + } + + const XsdFacet::Ptr unsignedMinInclusive(new XsdFacet()); + unsignedMinInclusive->setType(XsdFacet::MinimumInclusive); + unsignedMinInclusive->setValue(DerivedString::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::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::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::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::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::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::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::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 0000000..cf52028 --- /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 +#include +#include + +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 + */ + class XsdSchemaContext : public ReportContext + { + public: + /** + * A smart pointer wrapping XsdSchemaContext instances. + */ + typedef QExplicitlySharedDataPointer 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 m_builtinTypesFacetList; + + private: + QHash 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 0000000..850192c --- /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 varietyNames; + varietyNames.append(QLatin1String("Any")); + varietyNames.append(QLatin1String("Enumeration")); + varietyNames.append(QLatin1String("Not")); + + QVector 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 0000000..8c12f0f --- /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 0000000..752af89 --- /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 +static inline bool containsSet(const QSet &super, const QSet &sub) +{ + QSetIterator 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(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(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() << XsdWildcard::absentNamespace()); + return unionWildcard; + } + } + + // 5 + QSet 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() << 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() += 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 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 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 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::Ptr &operand1, + const AtomicComparator::Operator op, + const DerivedString::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 &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 &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 visitedElements; + if (!foundSubstitutionGroupTransitive(head, member, visitedElements)) + return false; + } + + // 2.3 + { + QSet 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 baseAttributeUsesLookup; + for (int i = 0; i < baseAttributeUses.count(); ++i) + baseAttributeUsesLookup.insert(baseAttributeUses.at(i)->attribute()->name(namePool), baseAttributeUses.at(i)); + + QHash 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(), 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 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 0000000..1722b4c --- /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 + */ + 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::Ptr &operand1, + const AtomicComparator::Operator op, + const DerivedString::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 &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 &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 0000000..a924c9c --- /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 0000000..54cc0f2 --- /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 + */ + class XsdSchemaMerger : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer 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 0000000..9f1e75d --- /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 +#include + +QT_BEGIN_NAMESPACE + +/** + * @page schema_overview Overview + * @section structure_and_components Structure and Components + * + * The schema validator code consists of 4 major components + * + *
+ *
The schema parser (QPatternist::XsdSchemaParser)
+ *
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.
+ * + *
The schema resolver (QPatternist::XsdSchemaResolver)
+ *
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).
+ * + *
The schema checker (QPatternist::XsdSchemaChecker)
+ *
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.
+ * + *
The validator (QPatternist::XsdValidatingInstanceReader)
+ *
This component is responsible for validating a XML instance document, provided via a QIODevice, against + * a valid compiled schema.
+ *
+ * + * @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 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(parserContext->elementDescriptions(), QSet(), 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::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 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 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 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()->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 patternFacets; + QList enumerationFacets; + QList 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::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 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()->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::Ptr string = DerivedString::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()->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::Ptr string = DerivedString::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()->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::Ptr string = DerivedString::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()->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::Ptr string = DerivedString::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()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::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()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::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()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::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()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::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()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::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::Ptr string = DerivedString::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()->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::Ptr string = DerivedString::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::Ptr string = DerivedString::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()->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()->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()->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 patternFacets; + QList enumerationFacets; + QList 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()->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()->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()->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 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()->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::Ptr publicId = DerivedString::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 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() << m_targetNamespace); + else + wildcard->namespaceConstraint()->setNamespaces(QSet() << 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 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() << m_targetNamespace); + else + wildcard->namespaceConstraint()->setNamespaces(QSet() << 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::Ptr integer = DerivedInteger::fromLexical(m_namePool, value); + if (integer->hasError()) { + attributeContentError("minOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger); + return false; + } else { + particle->setMinimumOccurs(integer->as< DerivedInteger >()->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::Ptr integer = DerivedInteger::fromLexical(m_namePool, value); + if (integer->hasError()) { + attributeContentError("maxOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger); + return false; + } else { + particle->setMaximumOccurs(integer->as< DerivedInteger >()->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 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 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 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 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 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 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::Ptr id = DerivedString::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 ¬ation) +{ + 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 0000000..960fb86 --- /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 +#include +#include +#include +#include + +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 + */ + class XsdSchemaParser : public MaintainingReader + { + 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 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 schema object. + */ + void parseSchema(ParserType parserType); + + /** + * This method is called for parsing any top-level include object. + */ + void parseInclude(); + + /** + * This method is called for parsing any top-level import object. + */ + void parseImport(); + + /** + * This method is called for parsing any top-level redefine object. + */ + void parseRedefine(); + + /** + * This method is called for parsing any annotation object everywhere + * in the schema. + */ + XsdAnnotation::Ptr parseAnnotation(); + + /** + * This method is called for parsing an appinfo object as child of + * an annotation object. + */ + XsdApplicationInformation::Ptr parseAppInfo(); + + /** + * This method is called for parsing a documentation object as child of + * an annotation object. + */ + XsdDocumentation::Ptr parseDocumentation(); + + /** + * This method is called for parsing a defaultOpenContent object. + */ + void parseDefaultOpenContent(); + + /** + * This method is called for parsing any top-level simpleType object. + */ + XsdSimpleType::Ptr parseGlobalSimpleType(); + + /** + * This method is called for parsing any simpleType object as descendant + * of an element or complexType object. + */ + XsdSimpleType::Ptr parseLocalSimpleType(); + + /** + * This method is called for parsing a restriction object as child + * of a simpleType object. + */ + void parseSimpleRestriction(const XsdSimpleType::Ptr &ptr); + + /** + * This method is called for parsing a list object as child + * of a simpleType object. + */ + void parseList(const XsdSimpleType::Ptr &ptr); + + /** + * This method is called for parsing a union object as child + * of a simpleType object. + */ + void parseUnion(const XsdSimpleType::Ptr &ptr); + + /** + * This method is called for parsing a minExclusive object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMinExclusiveFacet(); + + /** + * This method is called for parsing a minInclusive object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMinInclusiveFacet(); + + /** + * This method is called for parsing a maxExclusive object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMaxExclusiveFacet(); + + /** + * This method is called for parsing a maxInclusive object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMaxInclusiveFacet(); + + /** + * This method is called for parsing a totalDigits object as child + * of a restriction object. + */ + XsdFacet::Ptr parseTotalDigitsFacet(); + + /** + * This method is called for parsing a fractionDigits object as child + * of a restriction object. + */ + XsdFacet::Ptr parseFractionDigitsFacet(); + + /** + * This method is called for parsing a length object as child + * of a restriction object. + */ + XsdFacet::Ptr parseLengthFacet(); + + /** + * This method is called for parsing a minLength object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMinLengthFacet(); + + /** + * This method is called for parsing a maxLength object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMaxLengthFacet(); + + /** + * This method is called for parsing an enumeration object as child + * of a restriction object. + */ + XsdFacet::Ptr parseEnumerationFacet(); + + /** + * This method is called for parsing a whiteSpace object as child + * of a restriction object. + */ + XsdFacet::Ptr parseWhiteSpaceFacet(); + + /** + * This method is called for parsing a pattern object as child + * of a restriction object. + */ + XsdFacet::Ptr parsePatternFacet(); + + /** + * This method is called for parsing an assertion object as child + * of a restriction object. + */ + XsdFacet::Ptr parseAssertionFacet(); + + /** + * This method is called for parsing any top-level complexType object. + */ + XsdComplexType::Ptr parseGlobalComplexType(); + + /** + * This method is called for parsing any complexType object as descendant + * of an element 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 simpleContent object as child + * of a complexType object. + */ + void parseSimpleContent(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing a restriction object as child + * of a simpleContent object. + */ + void parseSimpleContentRestriction(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing an extension object as child + * of a simpleContent object. + */ + void parseSimpleContentExtension(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing a complexContent object as child + * of a complexType 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 restriction object as child + * of a complexContent object. + */ + void parseComplexContentRestriction(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing an extension object as child + * of a complexContent object. + */ + void parseComplexContentExtension(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing an assert object as child + * of a complexType or parsing a assertion facet object as + * child of a simpleType. + * + * @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 openContent object. + */ + XsdComplexType::OpenContent::Ptr parseOpenContent(); + + /** + * This method is called for parsing a top-level group object. + */ + XsdModelGroup::Ptr parseNamedGroup(); + + /** + * This method is called for parsing a non-top-level group object + * that contains a ref attribute. + */ + XsdTerm::Ptr parseReferredGroup(const XsdParticle::Ptr &particle); + + /** + * This method is called for parsing an all object as child + * of a top-level group object. + * + * @param parent The schema component the all object is part of. + */ + XsdModelGroup::Ptr parseAll(const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing an all object as descendant + * of a complexType object. + * + * @param particle The particle the all object belongs to. + * @param parent The schema component the all object is part of. + */ + XsdModelGroup::Ptr parseLocalAll(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a choice object as child + * of a top-level group object. + * + * @param parent The schema component the choice object is part of. + */ + XsdModelGroup::Ptr parseChoice(const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a choice object as descendant + * of a complexType object or a choice object. + * + * @param particle The particle the choice object belongs to. + * @param parent The schema component the choice object is part of. + */ + XsdModelGroup::Ptr parseLocalChoice(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a sequence object as child + * of a top-level group object. + * + * @param parent The schema component the sequence object is part of. + */ + XsdModelGroup::Ptr parseSequence(const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a sequence object as descendant + * of a complexType object or a sequence object. + * + * @param particle The particle the sequence object belongs to. + * @param parent The schema component the sequence 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 attribute object. + */ + XsdAttribute::Ptr parseGlobalAttribute(); + + /** + * This method is called for parsing any non-top-level attribute object as a + * descendant of a complexType object or an attributeGroup object. + * + * @param parent The parent component the attribute object is part of. + */ + XsdAttributeUse::Ptr parseLocalAttribute(const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a top-level attributeGroup object. + */ + XsdAttributeGroup::Ptr parseNamedAttributeGroup(); + + /** + * This method is called for parsing a non-top-level attributeGroup object + * that contains a ref attribute. + */ + XsdAttributeUse::Ptr parseReferredAttributeGroup(); + + /** + * This method is called for parsing any top-level element object. + */ + XsdElement::Ptr parseGlobalElement(); + + /** + * This method is called for parsing any non-top-level element object as a + * descendant of a complexType object or a group object. + * + * @param particle The particle the element object belongs to. + * @param parent The parent component the element object is part of. + */ + XsdTerm::Ptr parseLocalElement(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a unique object as child of an element object. + */ + XsdIdentityConstraint::Ptr parseUnique(); + + /** + * This method is called for parsing a key object as child of an element object. + */ + XsdIdentityConstraint::Ptr parseKey(); + + /** + * This method is called for parsing a keyref object as child of an element object. + */ + XsdIdentityConstraint::Ptr parseKeyRef(const XsdElement::Ptr &element); + + /** + * This method is called for parsing a selector object as child of an unique object, + * key object or keyref object, + * + * @param ptr The identity constraint it belongs to. + */ + void parseSelector(const XsdIdentityConstraint::Ptr &ptr); + + /** + * This method is called for parsing a field object as child of an unique object, + * key object or keyref object, + * + * @param ptr The identity constraint it belongs to. + */ + void parseField(const XsdIdentityConstraint::Ptr &ptr); + + /** + * This method is called for parsing an alternative object inside an element object. + */ + XsdAlternative::Ptr parseAlternative(); + + /** + * This method is called for parsing a top-level notation object. + */ + XsdNotation::Ptr parseNotation(); + + /** + * This method is called for parsing an any object somewhere in + * the schema. + * + * @param particle The particle the any object belongs to. + */ + XsdWildcard::Ptr parseAny(const XsdParticle::Ptr &particle); + + /** + * This method is called for parsing an anyAttribute object somewhere in + * the schema. + */ + XsdWildcard::Ptr parseAnyAttribute(); + + /** + * This method is called for parsing unknown object as descendant of the annotation 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 ¬ation); + + /** + * 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 > m_stateMachines; + ComponentLocationHash m_componentLocationHash; + QSet 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 0000000..167af7a --- /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 attribute tag in XML Schema is (annotation?, simpleType?). + * That means the attribute tag can contain an annotation tag followed + * by a simpleType tag, or just one simpleType 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 annotation 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. + * + *

Legend:

+ * \dotfile legend.dot + *
+ * + *

DFA for all tag

+ * \dotfile All_diagram.dot + *
+ *

DFA for alternative tag

+ * \dotfile Alternative_diagram.dot + *
+ *

DFA for annotation tag

+ * \dotfile Annotation_diagram.dot + *
+ *

DFA for anyAttribute tag

+ * \dotfile AnyAttribute_diagram.dot + *
+ *

DFA for any tag

+ * \dotfile Any_diagram.dot + *
+ *

DFA for assert tag

+ * \dotfile Assert_diagram.dot + *
+ *

DFA for choice tag

+ * \dotfile Choice_diagram.dot + *
+ *

DFA for complexContent tag

+ * \dotfile ComplexContent_diagram.dot + *
+ *

DFA for extension tag inside a complexContent tag

+ * \dotfile ComplexContentExtension_diagram.dot + *
+ *

DFA for restriction tag inside a complexContent tag

+ * \dotfile ComplexContentRestriction_diagram.dot + *
+ *

DFA for defaultOpenContent tag

+ * \dotfile DefaultOpenContent_diagram.dot + *
+ *

DFA for enumeration tag

+ * \dotfile EnumerationFacet_diagram.dot + *
+ *

DFA for field tag

+ * \dotfile Field_diagram.dot + *
+ *

DFA for fractionDigits tag

+ * \dotfile FractionDigitsFacet_diagram.dot + *
+ *

DFA for attribute tag

+ * \dotfile GlobalAttribute_diagram.dot + *
+ *

DFA for complexType tag

+ * \dotfile GlobalComplexType_diagram.dot + *
+ *

DFA for element tag

+ * \dotfile GlobalElement_diagram.dot + *
+ *

DFA for simpleType tag

+ * \dotfile GlobalSimpleType_diagram.dot + *
+ *

DFA for import tag

+ * \dotfile Import_diagram.dot + *
+ *

DFA for include tag

+ * \dotfile Include_diagram.dot + *
+ *

DFA for key tag

+ * \dotfile Key_diagram.dot + *
+ *

DFA for keyref tag

+ * \dotfile KeyRef_diagram.dot + *
+ *

DFA for length tag

+ * \dotfile LengthFacet_diagram.dot + *
+ *

DFA for list tag

+ * \dotfile List_diagram.dot + *
+ *

DFA for all tag

+ * \dotfile LocalAll_diagram.dot + *
+ *

DFA for attribute tag

+ * \dotfile LocalAttribute_diagram.dot + *
+ *

DFA for choice tag

+ * \dotfile LocalChoice_diagram.dot + *
+ *

DFA for complexType tag

+ * \dotfile LocalComplexType_diagram.dot + *
+ *

DFA for element tag

+ * \dotfile LocalElement_diagram.dot + *
+ *

DFA for sequence tag

+ * \dotfile LocalSequence_diagram.dot + *
+ *

DFA for simpleType tag that

+ * \dotfile LocalSimpleType_diagram.dot + *
+ *

DFA for maxExclusive tag

+ * \dotfile MaxExclusiveFacet_diagram.dot + *
+ *

DFA for maxInclusive tag

+ * \dotfile MaxInclusiveFacet_diagram.dot + *
+ *

DFA for maxLength tag

+ * \dotfile MaxLengthFacet_diagram.dot + *
+ *

DFA for minExclusive tag

+ * \dotfile MinExclusiveFacet_diagram.dot + *
+ *

DFA for minInclusive tag

+ * \dotfile MinInclusiveFacet_diagram.dot + *
+ *

DFA for minLength tag

+ * \dotfile MinLengthFacet_diagram.dot + *
+ *

DFA for attributeGroup tag without ref attribute

+ * \dotfile NamedAttributeGroup_diagram.dot + *
+ *

DFA for group tag without ref attribute

+ * \dotfile NamedGroup_diagram.dot + *
+ *

DFA for notation tag

+ * \dotfile Notation_diagram.dot + *
+ *

DFA for override tag

+ * \dotfile Override_diagram.dot + *
+ *

DFA for pattern tag

+ * \dotfile PatternFacet_diagram.dot + *
+ *

DFA for redefine tag

+ * \dotfile Redefine_diagram.dot + *
+ *

DFA for attributeGroup tag with ref attribute

+ * \dotfile ReferredAttributeGroup_diagram.dot + *
+ *

DFA for group tag with ref attribute

+ * \dotfile ReferredGroup_diagram.dot + *
+ *

DFA for schema tag

+ * \dotfile Schema_diagram.dot + *
+ *

DFA for selector tag

+ * \dotfile Selector_diagram.dot + *
+ *

DFA for sequence tag

+ * \dotfile Sequence_diagram.dot + *
+ *

DFA for simpleContent tag

+ * \dotfile SimpleContent_diagram.dot + *
+ *

DFA for extension tag inside a simpleContent tag

+ * \dotfile SimpleContentExtension_diagram.dot + *
+ *

DFA for restriction tag inside a simpleContent tag

+ * \dotfile SimpleContentRestriction_diagram.dot + *
+ *

DFA for restriction tag inside a simpleType tag

+ * \dotfile SimpleRestriction_diagram.dot + *
+ *

DFA for totalDigits tag

+ * \dotfile TotalDigitsFacet_diagram.dot + *
+ *

DFA for union tag

+ * \dotfile Union_diagram.dot + *
+ *

DFA for unique tag

+ * \dotfile Unique_diagram.dot + *
+ *

DFA for whiteSpace tag

+ * \dotfile WhiteSpaceFacet_diagram.dot + */ + +void XsdSchemaParser::setupStateMachines() +{ + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, simpleType?) : attribute + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, ((simpleType | complexType)?, alternative*, (unique | key | keyref)*)) : element + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, (simpleContent | complexContent | (openContent?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?), assert*))) : complexType + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s6 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s7 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, (restriction | extension)) : simpleContent/complexContent + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 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::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s6 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, ((attribute | attributeGroup)*, anyAttribute?), assert*) : simple content extension + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::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 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::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s6 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, ((attribute | attributeGroup)*, anyAttribute?)) : named attribute group + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, (all | choice | sequence)?) : group + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, (element | any)*) : all + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, (element | group | choice | sequence | any)*) : choice sequence + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?) : any/selector/field/notation/include/import/referred attribute group/anyAttribute/all facets/assert + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, (selector, field+)) : unique/key/keyref + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, (simpleType | complexType)?) : alternative + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (appinfo | documentation)* : annotation + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, (restriction | list | union)) : simpleType + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 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::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, simpleType?) : list + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, simpleType*) : union + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 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::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation?, any) : defaultOpenContent + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation | (simpleType | complexType | group | attributeGroup))* : redefine + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::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 machine(m_namePool); + + // setup state machine for (annotation | (simpleType | complexType | group | attributeGroup | element | attribute | notation))* : override + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::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 0000000..896619e --- /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::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::Hash XsdSchemaParserContext::setupElementDescriptions() +{ + enum + { + ReservedForElements = 60 + }; + + ElementDescription::Hash elementDescriptions; + elementDescriptions.reserve(ReservedForElements); + + { + ElementDescription &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 &description = elementDescriptions[XsdTagScope::Include]; + //description.tagToken = XsdSchemaToken::Include; + description.requiredAttributes.insert(XsdSchemaToken::SchemaLocation); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Import]; + //description.tagToken = XsdSchemaToken::Import; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Namespace); + description.optionalAttributes.insert(XsdSchemaToken::SchemaLocation); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Redefine]; + //description.tagToken = XsdSchemaToken::Redefine; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::SchemaLocation); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Override]; + //description.tagToken = XsdSchemaToken::Override; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::SchemaLocation); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Annotation]; + //description.tagToken = XsdSchemaToken::Annotation; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::AppInfo]; + //description.tagToken = XsdSchemaToken::Appinfo; + description.optionalAttributes.insert(XsdSchemaToken::Source); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Documentation]; + //description.tagToken = XsdSchemaToken::Documentation; + description.optionalAttributes.insert(XsdSchemaToken::Source); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::GlobalSimpleType]; + //description.tagToken = XsdSchemaToken::SimpleType; + description.optionalAttributes.insert(XsdSchemaToken::Final); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalSimpleType]; + //description.tagToken = XsdSchemaToken::SimpleType; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::SimpleRestriction]; + //description.tagToken = XsdSchemaToken::Restriction; + description.optionalAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::List]; + //description.tagToken = XsdSchemaToken::List; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::ItemType); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Union]; + //description.tagToken = XsdSchemaToken::Union; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MemberTypes); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MinExclusiveFacet]; + //description.tagToken = XsdSchemaToken::MinExclusive; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MinInclusiveFacet]; + //description.tagToken = XsdSchemaToken::MinInclusive; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MaxExclusiveFacet]; + //description.tagToken = XsdSchemaToken::MaxExclusive; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MaxInclusiveFacet]; + //description.tagToken = XsdSchemaToken::MaxInclusive; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::TotalDigitsFacet]; + //description.tagToken = XsdSchemaToken::TotalDigits; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::FractionDigitsFacet]; + //description.tagToken = XsdSchemaToken::FractionDigits; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LengthFacet]; + //description.tagToken = XsdSchemaToken::Length; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MinLengthFacet]; + //description.tagToken = XsdSchemaToken::MinLength; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MaxLengthFacet]; + //description.tagToken = XsdSchemaToken::MaxLength; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::EnumerationFacet]; + //description.tagToken = XsdSchemaToken::Enumeration; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::WhiteSpaceFacet]; + //description.tagToken = XsdSchemaToken::WhiteSpace; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::PatternFacet]; + //description.tagToken = XsdSchemaToken::Pattern; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &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 &description = elementDescriptions[XsdTagScope::LocalComplexType]; + //description.tagToken = XsdSchemaToken::ComplexType; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Mixed); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::SimpleContent]; + //description.tagToken = XsdSchemaToken::SimpleContent; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::SimpleContentRestriction]; + //description.tagToken = XsdSchemaToken::Restriction; + description.requiredAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::SimpleContentExtension]; + //description.tagToken = XsdSchemaToken::Extension; + description.requiredAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::ComplexContent]; + //description.tagToken = XsdSchemaToken::ComplexContent; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Mixed); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::ComplexContentRestriction]; + //description.tagToken = XsdSchemaToken::Restriction; + description.requiredAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::ComplexContentExtension]; + //description.tagToken = XsdSchemaToken::Extension; + description.requiredAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::NamedGroup]; + //description.tagToken = XsdSchemaToken::Group; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &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 &description = elementDescriptions[XsdTagScope::All]; + //description.tagToken = XsdSchemaToken::All; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalAll]; + //description.tagToken = XsdSchemaToken::All; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs); + description.optionalAttributes.insert(XsdSchemaToken::MinOccurs); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Choice]; + //description.tagToken = XsdSchemaToken::Choice; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalChoice]; + //description.tagToken = XsdSchemaToken::Choice; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs); + description.optionalAttributes.insert(XsdSchemaToken::MinOccurs); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Sequence]; + //description.tagToken = XsdSchemaToken::Sequence; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalSequence]; + //description.tagToken = XsdSchemaToken::Sequence; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs); + description.optionalAttributes.insert(XsdSchemaToken::MinOccurs); + } + + { + ElementDescription &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 &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 &description = elementDescriptions[XsdTagScope::NamedAttributeGroup]; + //description.tagToken = XsdSchemaToken::AttributeGroup; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::ReferredAttributeGroup]; + //description.tagToken = XsdSchemaToken::AttributeGroup; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Ref); + } + + { + ElementDescription &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 &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 &description = elementDescriptions[XsdTagScope::Unique]; + //description.tagToken = XsdSchemaToken::Unique; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Key]; + //description.tagToken = XsdSchemaToken::Key; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::KeyRef]; + //description.tagToken = XsdSchemaToken::Keyref; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + description.requiredAttributes.insert(XsdSchemaToken::Refer); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Selector]; + //description.tagToken = XsdSchemaToken::Selector; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Xpath); + description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Field]; + //description.tagToken = XsdSchemaToken::Field; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Xpath); + description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace); + } + + { + ElementDescription &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 &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 &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 &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 &description = elementDescriptions[XsdTagScope::OpenContent]; + //description.tagToken = XsdSchemaToken::OpenContent; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Mode); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::DefaultOpenContent]; + //description.tagToken = XsdSchemaToken::DefaultOpenContent; + description.optionalAttributes.insert(XsdSchemaToken::AppliesToEmpty); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Mode); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Assert]; + //description.tagToken = XsdSchemaToken::Assert; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Test); + description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace); + } + + { + ElementDescription &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 0000000..616aff3 --- /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 + +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 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 + */ + class XsdSchemaParserContext : public QSharedData + { + public: + /** + * A smart pointer wrapping XsdSchemaParserContext instances. + */ + typedef QExplicitlySharedDataPointer 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::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::Hash setupElementDescriptions(); + + NamePool::Ptr m_namePool; + XsdSchema::Ptr m_schema; + XsdSchemaChecker::Ptr m_checker; + XsdSchemaResolver::Ptr m_resolver; + const ElementDescription::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 0000000..4c6910f --- /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 &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 &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 &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 visitedTypes; + for (int i = 0; i < simpleTypes.count(); ++i) { + resolveSimpleRestrictions(simpleTypes.at(i), visitedTypes); + } +} + +void XsdSchemaResolver::resolveSimpleRestrictions(const XsdSimpleType::Ptr &simpleType, QSet &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 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 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 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 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 &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 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 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 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 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 &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 ¤t, 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()); + } + + // 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()); + } + + 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()); + } +} + +void XsdSchemaResolver::resolveTermReference(const XsdParticle::Ptr &particle, QSet 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()); + 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()); + 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()); + complexType->setAttributeUses(uses); + complexType->setAttributeWildcard(wildcard); + } +} + +XsdAttributeUse::List XsdSchemaResolver::resolveAttributeTermReferences(const XsdAttributeUse::List &attributeUses, XsdWildcard::Ptr &wildcard, QSet 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 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 &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 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 >()->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 &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 0000000..1222619 --- /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 + +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 + */ + class XsdSchemaResolver : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer 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 &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 key or unique 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 &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 &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 &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 all 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 &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 &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 &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 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 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 &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 &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 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 elementNames; + QSourceLocation location; + }; + + class RedefinedGroups + { + public: + XsdModelGroup::Ptr redefinedGroup; + XsdModelGroup::Ptr group; + }; + + class RedefinedAttributeGroups + { + public: + XsdAttributeGroup::Ptr redefinedGroup; + XsdAttributeGroup::Ptr group; + }; + + QVector m_keyReferences; + QVector m_simpleRestrictionBases; + QVector m_simpleListTypes; + QVector m_simpleUnionTypes; + QVector m_elementTypes; + QVector m_complexBaseTypes; + QVector m_complexContentTypes; + QVector m_attributeTypes; + QVector m_alternativeTypes; + QVector m_alternativeTypeElements; + QVector m_substitutionGroupAffiliations; + QVector m_substitutionGroupTypes; + QVector m_redefinedGroups; + QVector m_redefinedAttributeGroups; + QHash m_enumerationFacetValues; + QSet m_allGroups; + + QExplicitlySharedDataPointer m_context; + QExplicitlySharedDataPointer m_checker; + NamePool::Ptr m_namePool; + XsdSchema::Ptr m_schema; + QHash 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 0000000..b527de6 --- /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 0000000..8cb1e76 --- /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 + +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 0000000..6cac0ff --- /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::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse))); + + const XsdFacet::Ptr minLengthFacet(new XsdFacet()); + minLengthFacet->setType(XsdFacet::MinimumLength); + minLengthFacet->setValue(DerivedInteger::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 0000000..4fcd5fb --- /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 +#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 + */ + 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 0000000..2e5b7f5 --- /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 0000000..9ba34b6 --- /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 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD simpleType object. + * + * This class represents the simpleType object of a XML schema as described + * here. + * + * It contains information from either a top-level simple type declaration (as child of a schema object) + * or a local simple type declaration (as descendant of an element or complexType object). + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSimpleType : public XsdUserSchemaType + { + public: + typedef QExplicitlySharedDataPointer 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 Base Type Definition + */ + 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 Context Definition + */ + 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 Primitive Type Definition + */ + 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 Item Type Definition + */ + 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 Member Types Definition + */ + 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 Facets Definition + */ + 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 Variety Definition + */ + 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 0000000..e40e55b --- /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 +XsdStateMachine::XsdStateMachine() + : m_counter(50) +{ +} + +template +XsdStateMachine::XsdStateMachine(const NamePool::Ptr &namePool) + : m_namePool(namePool) + , m_counter(50) +{ +} + +template +typename XsdStateMachine::StateId XsdStateMachine::addState(StateType type) +{ +#ifndef QT_NO_DEBUG + // make sure we don't have two start states + if (type == StartState) { + QHashIterator 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 +void XsdStateMachine::addTransition(StateId start, TransitionType transition, StateId end) +{ + QHash > &hash = m_transitions[start]; + QVector &states = hash[transition]; + if (!states.contains(end)) + states.append(end); +} + +template +void XsdStateMachine::addEpsilonTransition(StateId start, StateId end) +{ + QVector &states = m_epsilonTransitions[start]; + states.append(end); +} + +template +void XsdStateMachine::reset() +{ + // reset the machine to the start state + QHashIterator it(m_states); + while (it.hasNext()) { + it.next(); + if (it.value() == StartState || it.value() == StartEndState) { + m_currentState = it.key(); + return; + } + } + + Q_ASSERT(false); +} + +template +void XsdStateMachine::clear() +{ + m_states.clear(); + m_transitions.clear(); + m_epsilonTransitions.clear(); + m_currentState = -1; + m_counter = 50; +} + +template +bool XsdStateMachine::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 > &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 +template +bool XsdStateMachine::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 > &entry = m_transitions[m_currentState]; + QHashIterator > 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 +template +bool XsdStateMachine::inputEqualsTransition(InputType input, TransitionType transition) const +{ + return false; +} + +template +bool XsdStateMachine::inEndState() const +{ + // check if current state is an end state + return (m_states.value(m_currentState) == StartEndState || m_states.value(m_currentState) == EndState); +} + +template +TransitionType XsdStateMachine::lastTransition() const +{ + return m_lastTransition; +} + +template +typename XsdStateMachine::StateId XsdStateMachine::startState() const +{ + QHashIterator 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 +QString XsdStateMachine::transitionTypeToString(TransitionType type) const +{ + Q_UNUSED(type) + + return QString(); +} + +template +bool XsdStateMachine::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 > > it(m_transitions); + QHashIterator it3(m_states); + + s << "digraph " << graphName << " {\n"; + s << " mindist = 2.0\n"; + + // draw edges + while (it.hasNext()) { + it.next(); + + QHashIterator > 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 > it4(m_epsilonTransitions); + while (it4.hasNext()) { + it4.next(); + + const QVector states = it4.value(); + for (int i = 0; i < states.count(); ++i) + s << " " << it4.key() << " -> " << states.at(i) << " [label=\"ε\"]\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 XsdStateMachine::StateId XsdStateMachine::dfaStateForNfaState(QSet nfaState, + QList< QPair, StateId> > &stateTable, + XsdStateMachine &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 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, StateId>(nfaState, dfaState)); + + return dfaState; +} + + +template +QSet::StateId> XsdStateMachine::epsilonClosure(const QSet &input) const +{ + // every state can reach itself by epsilon transition, so include the input states + // in the result as well + QSet result = input; + + // add the input states to the list of to be processed states + QList 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 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 +QSet::StateId> XsdStateMachine::move(const QSet &states, TransitionType input) const +{ + QSet result; + + QSetIterator 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 > transitions = m_transitions.value(state); + + // get the target states for the given input + const QVector 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 +XsdStateMachine XsdStateMachine::toDFA() const +{ + XsdStateMachine dfa(m_namePool); + dfa.m_counter = 100; + QList< QPair< QSet, StateId> > table; + QList< QSet > isMarked; + + // search the start state as the algorithm starts with it... + StateId startState = -1; + QHashIterator 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 > workStates; + + // add the start state to the list of to processed state sets + workStates.append(epsilonClosure(QSet() << startState)); + + while (!workStates.isEmpty()) { // as long as there are state sets to process left + + // enqueue set of states + const QSet 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 input; + + { + QSetIterator 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 + //