wsdlpull  1.23
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>
23 using namespace std;
24 
25 namespace 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 */
31 SchemaValidator::SchemaValidator(const SchemaParser * sp,
32  std::ostream& os)
33  :ostr_(os),
34  sParser_(sp)
35 {
36 
37 
38 }
39 
41 {
42 }
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 ||
121 
122  val = xpp->getText();
123 
124  xpp->nextToken();
125  while (xpp->getEventType() == XmlPullParser::ENTITY_REF ||
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 
274 SchemaValidator::validateContentModel(XmlPullParser * xpp,
275  ContentModel* cm,
276  TypeContainer * ipTc,
277  const string & elemName,
278  bool nested,
279  TypeContainer * btCnt)
280 {
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 
490 TypeContainer *
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  {
520  case Schema::XSD_INTEGER:
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;
539  case Schema::XSD_FLOAT:
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  }
552  case Schema::XSD_DOUBLE:
553  case Schema::XSD_DECIMAL:
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;
565  case Schema::XSD_POSINT:
566  case Schema::XSD_ULONG:
567  {
568  unsigned long ul= *((unsigned long*)value);
569  ipTc->setValue(ul);
570  }
571  break;
572  case Schema::XSD_BOOLEAN:
573  {
574  bool b = *((bool*)value);
575  ipTc->setValue(b);
576  break;
577  }
578  case Schema::XSD_QNAME:
579  {
580  Qname q = *((Qname* )value);
581  ipTc->setValue(q);
582  }
583  break;
584  case Schema::XSD_STRING:
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 
609 SchemaValidator::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 
672 void
673 SchemaValidator::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  {
696  case Schema::XSD_INTEGER:
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;
713  case Schema::XSD_FLOAT:
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  }
723  case Schema::XSD_DOUBLE:
724  case Schema::XSD_DECIMAL:
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;
732  case Schema::XSD_POSINT:
733  case Schema::XSD_ULONG:
734  istr >> ul;
735  ipTc->setValue(ul,!istr.fail());
736  break;
737  case Schema::XSD_BOOLEAN:
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  }
749  case Schema::XSD_QNAME:
750  {
751  Qname q(val);
752  if (xpp)
753  q.setNamespace(xpp->getNamespace(q.getPrefix()));
754  ipTc->setValue(q);
755  break;
756  }
757  case Schema::XSD_STRING:
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 
780 bool
781 SchemaValidator::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 
824 bool
825 SchemaValidator::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 
849 void 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 
862 bool
863 SchemaValidator::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 
893 bool
894 SchemaValidator::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 
912 bool
913 SchemaValidator::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 
973 void
974 SchemaValidator::instanceCM(ContentModel *cm)
975 
976 {
977 
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
std::string getPrefix(void) const
Definition: Qname.h:83
std::string getAttributeNamespace(int index)
std::string getAttributeName(int index)
int getNumAttributes() const
Definition: ComplexType.h:118
int getType() const
Definition: Attribute.h:90
const std::list< int > * unionTypes() const
Definition: SimpleType.h:180
int getTypeId() const
void setNamespace(std::string uri)
Definition: Qname.h:97
int getLineNumber()
Definition: XmlPullParser.h:64
XmlSerializer & attribute(std::string nsp, std::string name, std::string value)
bool instance(const std::string &tag, Schema::Type type_id)
int getColumnNumber()
Definition: XmlPullParser.h:68
TypeContainer * getChildContainer(std::string elemName, bool create=false)
std::string getName() const
Definition: Attribute.h:83
const std::string SchemaInstaceUri
Definition: Schema.h:93
bool isValueValid() const
void startDocument(std::string encoding, bool standalone)
std::string getText()
STL namespace.
std::string getNamespace(std::string prefix)
Qname getQname() const
Definition: XSDType.h:155
const SchemaParser * schemaParser() const
void setValue(const std::string &sValue, bool valid=true)
XmlSerializer & endTag(std::string nsp, std::string name)
virtual bool isSimple() const =0
const XSDType * getType(const Qname &type, bool checkImports=true)
std::string getAttributeValue(int index)
std::string getNamespace(void) const
Definition: Qname.h:30
int getBasicContentType(int typeId) const
XmlSerializer & text(std::string txt)
const Attribute * getAttribute(const std::string &name) const
Definition: ComplexType.cpp:80
bool isImported(const std::string &ns) const
Definition: SchemaParser.h:423
XmlSerializer & startTag(std::string nsp, std::string name)
bool isRequired() const
Definition: Attribute.h:97
bool anyContents() const
Definition: ContentModel.h:145
bool isValidFloat(float val) const
Definition: SimpleType.cpp:242
int getAttributeCount()
Definition: XmlPullParser.h:88
Schema::Compositor getCompositor() const
Definition: ContentModel.h:84
int getContentType() const
Definition: ComplexType.h:104
void setPrefix(std::string prefix, std::string nsp)
void setValAsString(const std::string &v)
bool isUnion() const
Definition: SimpleType.h:148
int getTypeId() const
Definition: XSDType.h:171
ContentsIterator begin()
Definition: ContentModel.h:91
TypeContainer * getAttributeContainer(std::string attName, bool create=false)
std::list< ContentHolder >::iterator ContentsIterator
Definition: ContentModel.h:55
Type
Definition: Schema.h:59
const SchemaParser * getImportedSchemaParser(const std::string &ns) const
Definition: SchemaParser.h:429
std::string getName()
Definition: XmlPullParser.h:79
ContentsIterator end()
Definition: ContentModel.h:98
ContentModel * getContents() const
Definition: ComplexType.h:155
bool isValidInt(int val) const
Definition: SimpleType.cpp:172
Schema::ContentModelType getContentModel() const
Definition: XSDType.h:164
TypeContainer * getBaseTypeContainer(bool create=false)
bool isList() const
Definition: SimpleType.h:141
int getBaseTypeId() const
Definition: XSDType.h:185
bool isBasicType(int sType) const
bool isValidString(std::string val) const
Definition: SimpleType.cpp:251
TypeContainer * validate(XmlPullParser *xpp, int typeId, TypeContainer *ipTc=0)
std::string getNamespace() const
Definition: XSDType.h:236