wsdlpull 1.23
Loading...
Searching...
No Matches
SchemaValidator.cpp
Go to the documentation of this file.
1/*
2 * wsdlpull - A C++ parser for WSDL (Web services description language)
3 * Copyright (C) 2005-2007 Vivek Krishna
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 *
20 */
21#include <sstream>
23using namespace std;
24
25namespace Schema {
26/*
27 This class validates an incoming Xml instance against a given type
28 whose schema has been processed by a given SchemaParser instance
29
30*/
32 std::ostream& os)
33 :ostr_(os),
34 sParser_(sp)
35{
36
37
38}
39
43
44
45/*
46 Main entry method for validation
47 Inputs
48 1. XmlStream ,xpp.getName() muct return the name of the type
49 which must be validated
50 2. typeId of the type against which this stream must be
51 validated against
52 3.An Input type container (default 0)
53*/
56 int typeId,
57 TypeContainer * ipTc)
58{
59 TypeContainer *t=0;
60
61 try{
62 string elemName = xpp->getName();
63 const SchemaParser * s1Parser = sParser_;
64 int typeId1= typeId;
65
66 if (!ipTc)
67 t = new TypeContainer(typeId, sParser_);
68 else
69 t = ipTc;
70
71
72
73 if (t->getTypeId() != typeId)
74 error("Fatal error ,container's type is not same as the validated type",xpp);
75
76 // a schema definition inside an instance
77 if (typeId == Schema::XSD_SCHEMA){
78
79 SchemaParser * ssParser_ = new SchemaParser(xpp);
80 if (!ssParser_->parseSchemaTag()){
81
82 delete ssParser_;
83 return 0;
84 }
85 delete ssParser_;
86 return t;
87 }
88
89 //ignore ANY
90 if (typeId == Schema::XSD_ANY){
91
92 xpp->skipSubTree();
93 return t;
94 }
95
96 // check if this type belongs to the current schema, if not we need to switch contexts
97 if (!sParser_->isBasicType(typeId)){
98
99 const XSDType * pType = sParser_->getType(typeId);
100
101 if (sParser_->isImported(pType->getNamespace())) {
102
103 sParser_ = sParser_->getImportedSchemaParser(pType->getNamespace());
104 typeId = const_cast<SchemaParser*>(sParser_)->getTypeId(pType->getQname());
105
106 t->sParser_ = sParser_;
107 t->typeId_ = (Schema::Type)typeId;
108
109 }
110 }
111
112
113 if (sParser_->getType(typeId) == 0
114 || sParser_->getType(typeId)->isSimple()) {
115
116 //simple type validation
117 string val;
118 xpp->nextToken();
119 if (xpp->getEventType() == XmlPullParser::TEXT ||
120 xpp->getEventType() == XmlPullParser::ENTITY_REF){
121
122 val = xpp->getText();
123
124 xpp->nextToken();
125 while (xpp->getEventType() == XmlPullParser::ENTITY_REF ||
126 xpp->getEventType() == XmlPullParser::TEXT){
127
128 val += xpp->getText();
129 xpp->nextToken();
130
131 }
132 validate(val, typeId, t,xpp);
133 }
134 else{
135 //text was probably empty,nevertheless create a type container
136 validate(val, typeId, t, xpp);
137 }
138 if (xpp->getEventType() == XmlPullParser::END_TAG)
139 {
140 if (xpp->getName() != elemName)
141 error("Syntax error "+elemName,xpp);
142 }
143 else
144 error("Expected a closing tag for " + elemName,xpp);
145 }
146 else {
147
148 /*
149 Perform Validation of Complex types
150 Check for
151 1.Is the tag name correct (this has to be right !!)
152 2.Attributes ,if any should be valid
153 3.Are there any mandatory (#required) attributes
154 4. Validate its content model
155 6.Return the type container which has the
156 correctly filled in values
157
158 */
159 const ComplexType *ct =
160 static_cast<const ComplexType *>(sParser_->getType(typeId));
161
162 const ComplexType * bt = 0;
163 TypeContainer * btCnt = 0;
164 if (ct->getBaseTypeId()!=Schema::XSD_ANYTYPE) {
165
166 bt = static_cast<const ComplexType*>
167 (sParser_->getType(ct->getBaseTypeId()));
168 btCnt = t->getBaseTypeContainer(true);
169 }
170
171 int attcnt = xpp->getAttributeCount();
172
173 for (int i = 0; i < attcnt; i++) {
174
175 std::string attName = xpp->getAttributeName(i);
176 std::string attVal = xpp->getAttributeValue("", attName);
177 std::string attNsp = xpp->getAttributeNamespace(i);
178 if (!attNsp.empty() && attNsp != sParser_->getNamespace())
179 continue;
180
181 const Attribute*at = 0;
182 TypeContainer *atCnt = 0;
183 at = ct->getAttribute(attName);
184
185 if (!at && bt){
186 at = bt->getAttribute(attName);
187 if (at)
188 atCnt = btCnt->getAttributeContainer(attName, true);
189 }
190 else{
191 atCnt = t->getAttributeContainer(attName, true);
192 }
193
194 if (!at)
195 error("Unknown attribute \"" + attName + "\"",xpp);
196
197 validate(attVal, at->getType(), atCnt, xpp);
198 }
199
200 //see if some required attributes are missing
201 checkAttributeOccurence(ct,xpp);
202 if (bt)
203 checkAttributeOccurence(bt,xpp);
204
205
206 if (ct->getContentModel() == Schema::Simple)
207 {
208 //complex types with a simple content model
209
210 string val;
211 xpp->nextToken();
212 if (xpp->getEventType() == xpp->TEXT){
213 val = xpp->getText();
214 validate(val, ct->getContentType(), t, xpp);
215 xpp->nextTag();
216 }
217 else{
218 //text was probably empty,nevertheless create a type container
219 validate(val, ct->getContentType(), t, xpp);
220 }
221
222 if (xpp->getEventType() == XmlPullParser::END_TAG)
223 {
224 if (xpp->getName() != elemName)
225 error("Syntax error",xpp);
226 }
227 else
228 error("Expected a closing tag for " + elemName,xpp);
229 }
230 else if (ct->getContentModel() == Schema::Complex){
231 //a complex type with complex content model
232 ContentModel* cm=ct->getContents();
233 ContentModel * bCm = 0;
234 if (bt)
235 bCm = bt ->getContents();
236 if(cm)
237 validateContentModel(xpp,
238 cm,
239 t->getChildContainer(cm,true),
240 elemName,
241 false,
242 btCnt);
243 else if (bCm)
244 validateContentModel(xpp,
245 bCm,
246 btCnt->getChildContainer(bCm,true),
247 elemName);
248 else
249 xpp->nextTag();
250 }
251 else{
252 // a complex type with mixed content model.no support yet
253 }
254 }
255 typeId = typeId1;
256 sParser_ = s1Parser;
257 return t;
258
259 }catch (SchemaParserException spe){
260
261 if (!ipTc && t) delete t;
262
263 if(xpp){
264
265 spe.line=xpp->getLineNumber();
266 spe.col=xpp->getColumnNumber();
267 throw spe;
268 }
269 }
270 return 0;
271}
272
274SchemaValidator::validateContentModel(XmlPullParser * xpp,
275 ContentModel* cm,
276 TypeContainer * ipTc,
277 const string & elemName,
278 bool nested,
279 TypeContainer * btCnt)
280{
281 ContentModel::ContentsIterator cit_b=cm->begin();
282 ContentModel::ContentsIterator cit_e=cm->end();
284
285 ContentModel::ContentsIterator bci;//base content model iterator
286 ContentModel * bCm=0;
287
288
289 for (ci=cit_b;ci!=cit_e;ci++){
290 if(ci->second==ContentModel::Particle)
291 ci->first.e->nOccurrences=0;
292 }
293 ci=cit_b;
294
295 if (btCnt) {
296 int t = btCnt->getTypeId();
297 const ComplexType* ct = static_cast<const ComplexType*>(btCnt->schemaParser()->getType(t));
298 bCm = ct->getContents();
299 bci =bCm->begin();
300 }
301
302 switch (cm->getCompositor()) {
303
304 case Schema::All:
305 {
306 do
307 {
308 if (!nested)
309 xpp->nextTag();
310 if (xpp->getEventType() == XmlPullParser::END_TAG)
311 {
312 if (xpp->getName() == elemName)
313 break;
314 while (xpp->getEventType() != XmlPullParser::START_TAG)
315 xpp->nextTag();
316 }
317 //All cannot have another content model inside like group/choice etc
318
319 if(!findElement(cit_b,cit_e,xpp->getName(),ci))
320 error("Could not find element " +xpp->getName()+" in "+elemName,xpp);
321 ci->first.e->nOccurrences++;
322
323 validate(xpp, ci->first.e->getType(),
324 ipTc->getChildContainer(ci->first.e->getName(), true));
325 //ipTc->getChildContainer(xpp->getName(), true));
326 }
327 while (true);
328
329 /*
330 check for occurrence constraints
331 */
332 for (ci=cit_b;ci!=cit_e;ci++){
333 if(ci->second==ContentModel::Particle &&
334 (ci->first.e->nOccurrences<ci->first.e->getMin()||
335 ci->first.e->nOccurrences>ci->first.e->getMax()))
336 error(ci->first.e->getName()+" did not meet occurrence constraints",xpp);
337 }
338
339 break;
340 }
341 case Schema::Sequence:
342 {
343 do
344 {
345 if (!nested)
346 xpp->nextTag();
347
348 if(xpp->getEventType() == XmlPullParser::END_TAG){
349
350 if (xpp->getName() == elemName)
351 break;
352 if(ci==cit_e)
353 break;
354
355 //position the xml parser to the next element
356 while ((xpp->getEventType() != XmlPullParser::START_TAG)&&
357 ((xpp->getEventType() != XmlPullParser::END_TAG)||
358 (xpp->getName() != elemName)))
359 xpp->nextTag();
360 }
361 //loop through all the contents inside
362 //the child elements in the content model must be in the same
363 //order as defined in the <sequence> tag of the schema
364
365 if(ci->second==ContentModel::Container){
366
367 if ((xpp->getEventType() == xpp->END_TAG)&&
368 (xpp->getName() == elemName))
369 break;
370 //nested content model
371 validateContentModel(xpp,ci->first.c,
372 ipTc->getChildContainer(ci->first.c,true),
373 elemName,true,btCnt);
374 ci++;
375 }
376 else{
377
378
379 if(cm->anyContents() ||
380 findElement(ci,cit_e,xpp->getName(), ci)){
381
382 ci->first.e->nOccurrences++;
383 validate(xpp,ci->first.e->getType(),
384 ipTc->getChildContainer(ci->first.e->getName(), true));
385
386 }else if (bCm && (bCm->anyContents() ||
387 findElement(bCm->begin(),bCm->end(),xpp->getName(), bci))){
388
389 TypeContainer * t = btCnt->getChildContainer(bCm,true);
390 validate(xpp,bci->first.e->getType(),t->getChildContainer(bci->first.e->getName(),true));
391
392 } else {
393
394 error("Could not find element " +xpp->getName()+" in "+elemName,xpp);
395 }
396
397 }
398 }
399 while (true);
400
401 /*
402 check for occurrence constraints
403 */
404 for (ci=cit_b;ci!=cit_e;ci++){
405 if(ci->second==ContentModel::Particle &&
406 (ci->first.e->nOccurrences<ci->first.e->getMin()||
407 ci->first.e->nOccurrences>ci->first.e->getMax()))
408 error(ci->first.e->getName()+" did not meet occurrence constraints",xpp);
409 }
410 break;
411 }
412 case Schema::Choice:
413 {
414
415 if (!nested)
416 xpp->nextTag();
417
418
419 if(findElement(ci,cit_e,xpp->getName(), ci)) {
420
421 std::string choiceElem = xpp->getName();
422 do {
423 //see if one of the choices is a particle and it occurs in the instance
424 ci->first.e->nOccurrences++;
425 validate(xpp, ci->first.e->getType(),
426 ipTc->getChildContainer(ci->first.e->getName(), true));
427 xpp->nextTag();
428 }while(xpp->getName() == choiceElem);
429 xpp->prevTag();
430 break;
431 }
432 else {
433 //its a choice which has a content model
434 ci++;
435 }
436 if (ci->second == ContentModel::Container){
437
438 try {
439 validateContentModel(xpp,ci->first.c,
440 ipTc->getChildContainer(ci->first.c,true),
441 elemName,true,btCnt);
442 }
443 catch (SchemaParserException spe){
444
445 ci++;
446 //try the other content model
447 validateContentModel(xpp,ci->first.c,
448 ipTc->getChildContainer(ci->first.c,true),
449 elemName,true,btCnt);
450 }
451 }
452 else{
453
454 error("Could not find element " +xpp->getName()+" in "+elemName,xpp);
455 }
456
457 /*
458 * Only one of the choices is allowed
459 */
460
461 /*
462 * check for occurrence constraints
463 */
464 if(ci->second==ContentModel::Particle &&
465 (ci->first.e->nOccurrences<ci->first.e->getMin()||
466 ci->first.e->nOccurrences>ci->first.e->getMax()))
467 error(ci->first.e->getName()+"did not meet occurrence constraints",xpp);
468
469 break;
470 }
471 }
472 /*
473 * reset occurence ocunters
474 */
475 for (ci=cit_b;ci!=cit_e;ci++){
476
477 if(ci->second==ContentModel::Particle)
478 ci->first.e->nOccurrences=0;
479 }
480 return ipTc;
481}
482
483
484
485/*
486 * This method validates all supported simple types
487 * Both native atomic types and schema defined
488 */
489
490TypeContainer *
492 int typeId,
493 TypeContainer * ipTc,
494 XmlPullParser * xpp)
495{
496
497 int basetype = sParser_->getBasicContentType(typeId);
498
499 const XSDType * pType = sParser_->getType(typeId);
500 if (pType && !pType->isSimple()){
501
502 return 0;
503 }
504 const SimpleType *st = static_cast<const SimpleType*>(pType);
505
506 //check for the validity of the value
507 //if available also check against restrictions in the schema
508
509 if (!ipTc)
510 ipTc = new TypeContainer(typeId, sParser_);
511
512 if (st && (st->isList() || st->isUnion())){
513
514 std::string val = *((std::string*)value);
515 ipTc->setValue(val,validateListOrUnion(st,val,xpp));
516 return ipTc;
517 }
518 switch (basetype)
519 {
521 case Schema::XSD_INT:
522 {
523 int x= *((int*)value);
524 if (!st) {
525 ipTc->setValue(x);
526 }
527 else{
528
529 ipTc->setValue(x,st->isValidInt(x));
530 }
531 break;
532 }
533 case Schema::XSD_BYTE:
534 {
535 char c= *((char*)value);
536 ipTc->setValue(c);
537 }
538 break;
540 {
541 float f = *((float*)value);
542 if (!st) {
543
544 ipTc->setValue(f);
545
546 }else{
547
548 ipTc->setValue(f,st->isValidFloat(f));
549 }
550 break;
551 }
554 {
555 double db = *((double*)value);
556 ipTc->setValue(db);
557 }
558 break;
559 case Schema::XSD_LONG:
560 {
561 long l = *((long*)value);
562 ipTc->setValue(l);
563 }
564 break;
567 {
568 unsigned long ul= *((unsigned long*)value);
569 ipTc->setValue(ul);
570 }
571 break;
573 {
574 bool b = *((bool*)value);
575 ipTc->setValue(b);
576 break;
577 }
579 {
580 Qname q = *((Qname* )value);
581 ipTc->setValue(q);
582 }
583 break;
585 default:
586 {
587 std::string val = *((std::string* )value);
588 if (!st) {
589
590 ipTc->setValue(val);
591 }
592 else{
593
594 ipTc->setValue(val,st->isValidString(val));
595 }
596 }
597 break;
598 }
599
600 return ipTc;
601}
602
603/*
604 * This method validates all supported simple types
605 * Both native atomic types and schema defined
606 */
607
609SchemaValidator::validate(const string & val,
610 int typeId,
611 TypeContainer *ipTc,
612 XmlPullParser * xpp)
613{
614
615 int basetype = sParser_->getBasicContentType(typeId);
616 if (basetype == Schema::XSD_INVALID) {
617
618 return 0;
619 }
620
621 const XSDType * pType = sParser_->getType(typeId);
622 if (pType &&
623 !pType->isSimple() &&
624 pType->getContentModel() != Schema::Simple){
625
626 return 0;
627 }
628
629 if (pType && !pType->isSimple() &&
630 pType->getContentModel() ==Schema::Simple) {
631 //this is a complex type but has a simple content model
632
633 const ComplexType * ct = static_cast<const ComplexType*>(pType);
634 int contentType = ct->getContentType();
635 return validate(val,contentType,ipTc,xpp);
636
637 }
638 const SimpleType *st = static_cast<const SimpleType*>(pType);
639
640 //check for the validity of the value
641 //if available also check against restrictions in the schema
642
643 if (!ipTc)
644 ipTc = new TypeContainer(typeId, sParser_);
645 ipTc->setValAsString(val);
646
647 while(ipTc->isValueValid()){
648
649 extractSimpleType(val, basetype, ipTc, st, xpp);
650
651
652 if(!st || (st && (st->isList() || st->isUnion()))){
653
654 break;
655 //if we validated an atomic type we are done
656 //if we just validated a list or union,there is no need
657 //to continue checking base types
658 }
659
660 if (!sParser_->isBasicType(st->getBaseTypeId())){
661
662 st=static_cast<const SimpleType*>(sParser_->getType(st->getBaseTypeId()));
663 }
664 else{
665 st = 0;
666 }
667 }
668 return ipTc;
669}
670
671
672void
673SchemaValidator::extractSimpleType(const std::string & val,
674 int basetype,
675 TypeContainer * ipTc,
676 const SimpleType * st,
677 XmlPullParser * xpp)
678{
679
680 if (st && (st->isList() || st->isUnion())){
681
682 ipTc->setValue(val,validateListOrUnion(st,val,xpp));
683 return;
684 }
685
686 istringstream istr(val);
687 int x;
688 double db;
689 long l;
690 char c;
691 unsigned long ul;
692 float f;
693
694 switch (basetype)
695 {
697 case Schema::XSD_INT:
698 {
699 istr >> x;
700 if (!st) {
701 ipTc->setValue(x,!istr.fail());
702 }
703 else{
704
705 ipTc->setValue(x,!istr.fail() && st->isValidInt(x));
706 }
707 break;
708 }
709 case Schema::XSD_BYTE:
710 istr >> c;
711 ipTc->setValue(c,!istr.fail());
712 break;
714 {
715 istr >> f;
716 if (!st) {
717 ipTc->setValue(f,!istr.fail());
718 }else{
719 ipTc->setValue(f,!istr.fail() && st->isValidFloat(f));
720 }
721 break;
722 }
725 istr >> db;
726 ipTc->setValue(db,!istr.fail());
727 break;
728 case Schema::XSD_LONG:
729 istr >> l;
730 ipTc->setValue(l,!istr.fail());
731 break;
734 istr >> ul;
735 ipTc->setValue(ul,!istr.fail());
736 break;
738 {
739
740 if(val=="true" ||
741 val=="yes" ||
742 val=="1")
743
744 ipTc->setValue(true);
745 else
746 ipTc->setValue(false);
747 break;
748 }
750 {
751 Qname q(val);
752 if (xpp)
753 q.setNamespace(xpp->getNamespace(q.getPrefix()));
754 ipTc->setValue(q);
755 break;
756 }
758 default:
759 {
760 if (!st) {
761
762 ipTc->setValue(val);
763 }
764 else{
765 if (basetype == Schema::XSD_STRING)
766 ipTc->setValue(val,st->isValidString(val));
767 else
768 ipTc->setValue(val);//other types such as date for which no validation is done
769 }
770 }
771 break;
772 }
773}
774
775/*
776 * This function validates a string as a list or union
777 * for the simple type
778 */
779
780bool
781SchemaValidator::validateListOrUnion(const SimpleType* st,
782 const std::string &val,
783 XmlPullParser * xpp)
784{
785 if (st->isList()){
786
787 size_t s = 0;
788
789 while(s < val.length()){
790 while(val[s]==' ')s++;
791 std::string t = val.substr(s,val.find(' ',s)-s);
792 TypeContainer * tc = validate(t,st->getBaseTypeId(),0,xpp);
793 if (!(tc && tc->isValueValid()))
794 return false;
795 s+=t.length()+1;
796 }
797 return true ;
798
799 }else if (st->isUnion()){
800
801 std::list<int>::const_iterator it= st->unionTypes()->begin();
802 while (it!=st->unionTypes()->end()){
803
804 TypeContainer * tc = validate(val,*it,0,xpp);
805
806 if (tc && tc->isValueValid())
807 return true;
808 it++;
809 }
810 return false;
811 }
812 else{
813 return false;
814 }
815}
816/*
817 * This function searches for a child element in a complex type
818 * The iterator pElem is set to point to the found element
819 * rewind controls whether a search is to be done by resetting pElem
820 * to the begining of the list
821 * Returns true if element is found else false
822 */
823
824bool
825SchemaValidator::findElement(ContentModel::ContentsIterator start,
827 std::string name,
829{
830 for (ContentModel::ContentsIterator ci=start;
831 ci!=end;
832 ci++){
833
834 if(ci->second==ContentModel::Particle){
835#ifdef LOGGING
836 std::cout<<"Looking for "<< name<<" found "<<ci->first.e->getName()<<std::endl;
837#endif
838 if(ci->first.e->getName()==name ||
839 ci->first.e->getName() == "*")//* is a hack for soap arrays
840 {
841 found=ci;
842 return true;
843 }
844 }
845 }
846 return false;
847}
848
849void SchemaValidator::error(const std::string& mesg,XmlPullParser* xpp)
850{
851
852 SchemaParserException spe(mesg + "\nError validating schema instance\n");
853 if(xpp){
854
855 spe.line=xpp->getLineNumber();
856 spe.col=xpp->getColumnNumber();
857 }
858 throw spe;
859}
860
861
862bool
863SchemaValidator::checkAttributeOccurence(const ComplexType* ct ,
864 XmlPullParser* xpp)
865{
866
867 if (ct->getNumAttributes() > 0)
868 {
869 for (int i = 0; i < ct->getNumAttributes(); i++)
870 {
871 const Attribute*at = ct->getAttribute(i);
872
873 /*
874 Check for the correctness of each attribute
875 */
876 string attVal = xpp->getAttributeValue("", at->getName());
877 if (attVal.empty())
878 {
879 if (at->isRequired())
880 error("Required attribute \"" + at->getName() +
881 "\" missing or empty",xpp);
882
883 else
884 continue;
885 }
886 }
887 }
888 return true;
889}
890
891
892
893bool
894SchemaValidator::instance(const std::string& tag,
895 Schema::Type type_id)
896
897{
898
899 //generate an instance of the given type
900 std::string nsp = sParser_->getNamespace();
901 xmlStream_ = new XmlSerializer(ostr_); //xml serializer
902
903 if (!nsp.empty())
904 xmlStream_->setPrefix("s",nsp);
905
906 xmlStream_->setPrefix("xsi",Schema::SchemaInstaceUri);
907 xmlStream_->startDocument("UTF-8",false);
908
909 return instance1(tag,type_id);
910}
911
912bool
913SchemaValidator::instance1(const std::string &tag,
914 Schema::Type type_id)
915{
916
917 std::string nsp = sParser_->getNamespace();
918 static bool first = false;
919 xmlStream_->startTag(nsp,tag);
920 if (!first){
921 xmlStream_->attribute("",
922 "xmlns",
923 nsp);
924 first = true;
925 }
926
927
928 // xmlStream_->attribute(Schema::SchemaInstaceUri,
929 // "type",
930 // "s:"+sParser_->getTypeName(type_id));
931 const XSDType * pType = sParser_->getType(type_id);
932
933 if ( pType== 0 ||
934 pType->isSimple()){
935
936 xmlStream_->text(""); //simple content types
937
938 }
939 else {
940
941 const ComplexType * ct =
942 static_cast<const ComplexType*>(pType);
943
944 //print attributes if any
945 if (ct->getNumAttributes() > 0) {
946
947 for (int i = 0; i < ct->getNumAttributes(); i++) {
948
949 const Attribute*at = ct->getAttribute(i);
950 xmlStream_->attribute(sParser_->getNamespace(),at->getName(),"");
951 }
952 }
953
954
955 if (ct->getContentModel() == Schema::Simple) {
956
957 xmlStream_->text("");
958 }
959 else{
960
961 ContentModel* cm=ct->getContents();
962 instanceCM(cm);
963
964 }
965 }
966 xmlStream_->endTag(nsp,tag);
967 return true;
968}
969
970
971
972
973void
974SchemaValidator::instanceCM(ContentModel *cm)
975
976{
977
978 ContentModel::ContentsIterator cit_b=cm->begin();
979 ContentModel::ContentsIterator cit_e=cm->end();
981
982 switch (cm->getCompositor())
983 {
984 case Schema::All:
985 case Schema::Sequence:
986 case Schema::Choice:
987 {
988 // a simple logic to start with
989 // not taking care of all,choice ,sequence as of now
990
991 for (ci=cit_b;ci!=cit_e;ci++){
992
993 if(ci->second==ContentModel::Particle &&
994 ci->first.e->getMax() > 0){
995
996 const SchemaParser* s1Parser = sParser_;
997 Schema::Type t=(Schema::Type)ci->first.e->getType();
998
999 if (!ci->first.e->getTypeNamespace().empty() &&
1000 sParser_->isImported(ci->first.e->getTypeNamespace()) &&
1001 sParser_->getNamespace() != ci->first.e->getTypeNamespace()) {
1002
1003 //here the type of the element is defined in another imported schemaparser
1004 //so try to get the pointer.
1005 t = (Schema::Type)sParser_->getType(t)->getTypeId();
1006 sParser_ = sParser_->getImportedSchemaParser(ci->first.e->getTypeNamespace());
1007 }
1008
1009 instance1(ci->first.e->getName(),t);
1010 sParser_ = s1Parser;
1011 }
1012 else if (ci->second==ContentModel::Container) {
1013
1014 //nested xsd:sequence inside choice..nested content models
1015 instanceCM(ci->first.c);
1016
1017 }
1018 else if (ci->second==ContentModel::ParticleGroup){
1019
1020 //xsd:group inside
1021 instanceCM(ci->first.g->getContents());
1022
1023 }
1024 }
1025 break;
1026 }
1027 }
1028}
1029
1030}
1031//TODO validation of <any>
1032//TODO validation of base64binary,hexBinary
1033//TODO validation of types derived by extension/restriction of complex types
Definition Qname.h:31
std::string getAttributeName(int index) const
int getContentType() const
ContentsIterator begin()
std::list< ContentHolder >::iterator ContentsIterator
bool instance(const std::string &tag, Schema::Type type_id)
SchemaValidator(const SchemaParser *sp, std::ostream &os=std::cout)
TypeContainer * validate(XmlPullParser *xpp, int typeId, TypeContainer *ipTc=0)
TypeContainer * getAttributeContainer(std::string attName, bool create=false)
XmlSerializer & startTag(std::string nsp, std::string name)
XmlSerializer & text(std::string txt)
void setPrefix(std::string prefix, std::string nsp)
void startDocument(std::string encoding, bool standalone)
XmlSerializer & attribute(std::string nsp, std::string name, std::string value)
XmlSerializer & endTag(std::string nsp, std::string name)
@ Sequence
Definition Schema.h:33
@ Choice
Definition Schema.h:34
@ All
Definition Schema.h:35
@ Simple
Definition Schema.h:46
@ Complex
Definition Schema.h:47
@ XSD_POSINT
Definition Schema.h:67
@ XSD_INVALID
Definition Schema.h:61
@ XSD_ANYTYPE
Definition Schema.h:88
@ XSD_DOUBLE
Definition Schema.h:75
@ XSD_LONG
Definition Schema.h:69
@ XSD_QNAME
Definition Schema.h:81
@ XSD_SCHEMA
Definition Schema.h:62
@ XSD_FLOAT
Definition Schema.h:74
@ XSD_DECIMAL
Definition Schema.h:73
@ XSD_BYTE
Definition Schema.h:66
@ XSD_ULONG
Definition Schema.h:70
@ XSD_INTEGER
Definition Schema.h:64
@ XSD_INT
Definition Schema.h:65
@ XSD_STRING
Definition Schema.h:63
@ XSD_BOOLEAN
Definition Schema.h:76
@ XSD_ANY
Definition Schema.h:87
const std::string SchemaInstaceUri
Definition Schema.h:93