SchemaValidator.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:36k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 2001, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Log: SchemaValidator.cpp,v $
  58.  * Revision 1.26  2001/11/21 18:05:09  tng
  59.  * Schema Fix: Check both XMLAttDef::Fixed and XMLAttDef::Required_And_Fixed for default values.
  60.  *
  61.  * Revision 1.25  2001/11/21 14:30:13  knoaman
  62.  * Fix for UPA checking.
  63.  *
  64.  * Revision 1.24  2001/11/20 20:32:52  knoaman
  65.  * Bypass validating element's simple content if it's empty and element is nillable.
  66.  *
  67.  * Revision 1.23  2001/11/13 13:25:08  tng
  68.  * Deprecate function XMLValidator::checkRootElement.
  69.  *
  70.  * Revision 1.22  2001/11/09 18:10:58  tng
  71.  * Schema Fix: should concatenate all characters for validation.
  72.  *
  73.  * Revision 1.21  2001/10/23 13:35:36  tng
  74.  * Schema fix: Resolve notation prefix to an URI.
  75.  *
  76.  * Revision 1.20  2001/10/12 20:44:01  tng
  77.  * Schema Fix: Notation Uri Binding.
  78.  *
  79.  * Revision 1.19  2001/10/04 15:08:56  knoaman
  80.  * Add support for circular import.
  81.  *
  82.  * Revision 1.18  2001/09/10 14:06:22  tng
  83.  * Schema: AnyAttribute support in Scanner and Validator.
  84.  *
  85.  * Revision 1.17  2001/09/05 20:49:11  knoaman
  86.  * Fix for complexTypes with mixed content model.
  87.  *
  88.  * Revision 1.16  2001/08/30 15:47:46  tng
  89.  * Schema: xsi:type fixes
  90.  *
  91.  * Revision 1.15  2001/08/29 20:52:35  tng
  92.  * Schema: xsi:type support
  93.  *
  94.  * Revision 1.14  2001/08/28 19:20:54  tng
  95.  * Schema: xsi:type support
  96.  *
  97.  * Revision 1.13  2001/08/21 16:06:11  tng
  98.  * Schema: Unique Particle Attribution Constraint Checking.
  99.  *
  100.  * Revision 1.12  2001/08/09 15:23:16  knoaman
  101.  * add support for <anyAttribute> declaration.
  102.  *
  103.  * Revision 1.11  2001/07/26 17:04:11  tng
  104.  * Schema: Process should stop after fatal error, and user throws need to be rethrown.
  105.  *
  106.  * Revision 1.10  2001/07/24 21:23:40  tng
  107.  * Schema: Use DatatypeValidator for ID/IDREF/ENTITY/ENTITIES/NOTATION.
  108.  *
  109.  * Revision 1.9  2001/07/11 21:39:58  peiyongz
  110.  * fix to normalizeWhiteSpace: synchronize fDatatypeBuffer with toFill.
  111.  *
  112.  * Revision 1.8  2001/05/17 18:14:32  tng
  113.  * Schema Fix: if nillable, it's an error to have default value
  114.  *
  115.  * Revision 1.7  2001/05/11 15:17:46  tng
  116.  * Schema: Nillable fixes.
  117.  *
  118.  * Revision 1.6  2001/05/11 13:27:37  tng
  119.  * Copyright update.
  120.  *
  121.  * Revision 1.5  2001/05/10 17:49:42  tng
  122.  * Schema: SchemaValidator fixes
  123.  *
  124.  * Revision 1.4  2001/05/03 20:34:44  tng
  125.  * Schema: SchemaValidator update
  126.  *
  127.  * Revision 1.3  2001/04/19 18:17:39  tng
  128.  * Schema: SchemaValidator update, and use QName in Content Model
  129.  *
  130.  * Revision 1.2  2001/03/30 16:35:19  tng
  131.  * Schema: Whitespace normalization.
  132.  *
  133.  * Revision 1.1  2001/03/21 21:56:33  tng
  134.  * Schema: Add Schema Grammar, Schema Validator, and split the DTDValidator into DTDValidator, DTDScanner, and DTDGrammar.
  135.  *
  136.  */
  137. // ---------------------------------------------------------------------------
  138. //  Includes
  139. // ---------------------------------------------------------------------------
  140. #include <util/Janitor.hpp>
  141. #include <util/KVStringPair.hpp>
  142. #include <framework/XMLDocumentHandler.hpp>
  143. #include <internal/XMLReader.hpp>
  144. #include <internal/XMLScanner.hpp>
  145. #include <validators/datatype/DatatypeValidatorFactory.hpp>
  146. #include <validators/datatype/InvalidDatatypeValueException.hpp>
  147. #include <validators/datatype/InvalidDatatypeFacetException.hpp>
  148. #include <validators/datatype/ListDatatypeValidator.hpp>
  149. #include <validators/datatype/UnionDatatypeValidator.hpp>
  150. #include <validators/datatype/ENTITYDatatypeValidator.hpp>
  151. #include <validators/datatype/IDDatatypeValidator.hpp>
  152. #include <validators/datatype/IDREFDatatypeValidator.hpp>
  153. #include <validators/schema/SchemaSymbols.hpp>
  154. #include <validators/schema/SchemaValidator.hpp>
  155. #include <validators/schema/SubstitutionGroupComparator.hpp>
  156. // ---------------------------------------------------------------------------
  157. //  SchemaValidator: Constructors and Destructor
  158. // ---------------------------------------------------------------------------
  159. SchemaValidator::SchemaValidator(XMLErrorReporter* const errReporter) :
  160.     XMLValidator(errReporter)
  161.     , fGrammarResolver(0)
  162.     , fSchemaGrammar(0)
  163.     , fTrailing(false)
  164.     , fXsiType(0)
  165.     , fXsiTypeValidator(0)
  166.     , fNil(false)
  167. {
  168. }
  169. SchemaValidator::~SchemaValidator()
  170. {
  171.     delete fXsiType;
  172. }
  173. // ---------------------------------------------------------------------------
  174. //  SchemaValidator: Implementation of the XMLValidator interface
  175. // ---------------------------------------------------------------------------
  176. int SchemaValidator::checkContent (XMLElementDecl* const elemDecl
  177.                                  , QName** const         children
  178.                                  , const unsigned int    childCount)
  179. {
  180.     //
  181.     //  Look up the element id in our element decl pool. This will get us
  182.     //  the element decl in our own way of looking at them.
  183.     //
  184.     if (!elemDecl)
  185.         ThrowXML(RuntimeException, XMLExcepts::Val_InvalidElemId);
  186.     //
  187.     //  Get the content spec type of this element. This will tell us what
  188.     //  to do to validate it.
  189.     //
  190.     const SchemaElementDecl::ModelTypes modelType = ((SchemaElementDecl*) elemDecl)->getModelType();
  191.     if (modelType == SchemaElementDecl::Empty)
  192.     {
  193.         //
  194.         //  We can do this one here. It cannot have any children. If it does
  195.         //  we return 0 as the index of the first bad child.
  196.         //
  197.         if (childCount)
  198.             return 0;
  199.     }
  200.     else if (modelType == SchemaElementDecl::Any)
  201.     {
  202.         // We pass no judgement on this one, anything goes
  203.     }
  204.     else if ((modelType == SchemaElementDecl::Mixed_Simple)
  205.          ||  (modelType == SchemaElementDecl::Mixed_Complex)
  206.          ||  (modelType == SchemaElementDecl::Children))
  207.     {
  208.         // if nillable, it's an error to have value
  209.         // XML Schema REC: Validation Rule: Element Locally Valid (Element)
  210.         // 3.2.1 The element information item must have no
  211.         // character or element information item [children].
  212.         //
  213.         if (fNil) {
  214.             if (childCount > 0 || XMLString::compareString(fDatatypeBuffer.getRawBuffer(), XMLUni::fgZeroLenString))
  215.                 emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
  216.         }
  217.         else {
  218.             // Get the element's content model or fault it in
  219.             XMLContentModel* elemCM = elemDecl->getContentModel();
  220.             // Ask it to validate and return its return
  221.             unsigned int emptyNS = getScanner()->getEmptyNamespaceId();
  222.             int result = elemCM->validateContent(children, childCount, emptyNS);
  223.             if (result != -1) {
  224.                 result = elemCM->validateContentSpecial(children
  225.                                                       , childCount
  226.                                                       , emptyNS
  227.                                                       , fGrammarResolver
  228.                                                       , getScanner()->getURIStringPool());
  229.             }
  230.             return result;
  231.         }
  232.     }
  233.     else if (modelType == SchemaElementDecl::Simple)
  234.     {
  235.         if (childCount > 0) {
  236.             emitError(XMLValid::SimpleTypeHasChild, elemDecl->getFullName());
  237.         } else {
  238.             try {
  239.                 DatatypeValidator* fCurrentDV = ((SchemaElementDecl*)elemDecl)->getDatatypeValidator();
  240.                 // If there is xsi:type validator, substitute it.
  241.                 if (fXsiTypeValidator) {
  242.                     fCurrentDV = fXsiTypeValidator;
  243.                     fXsiTypeValidator = 0;
  244.                 }
  245.                 if (!fCurrentDV) {
  246.                     emitError(XMLValid::NoDatatypeValidatorForSimpleType, elemDecl->getFullName());
  247.                 } else {
  248.                     XMLCh* value = fDatatypeBuffer.getRawBuffer();
  249.                     XMLCh* elemDefaultValue = ((SchemaElementDecl*) elemDecl)->getDefaultValue();
  250.                     if (elemDefaultValue) {
  251.                         // a default value was specified
  252.                         // if nillable, it's an error to have default value
  253.                         if (fNil)
  254.                             emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
  255.                         if (!XMLString::compareString(value, XMLUni::fgZeroLenString)) {
  256.                             // if this element didn't specified any value
  257.                             // use default value
  258.                             getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false);
  259.                         }
  260.                         else {
  261.                             // this element has specified some value
  262.                             // if the flag is FIXED, then this value must be same as default value
  263.                             if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() == SchemaSymbols::FIXED) != 0) {
  264.                                 if (fCurrentDV->compare(value, elemDefaultValue) != 0 )
  265.                                     emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName());
  266.                             }
  267.                             // if nillable, it's an error to have value
  268.                             if (fNil)
  269.                                 emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
  270.                             else
  271.                                fCurrentDV->validate(value);
  272.                         }
  273.                     }
  274.                     else {
  275.                         // no default value, then check nillable
  276.                         if (!XMLString::compareString(value, XMLUni::fgZeroLenString)) {
  277.                             if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::NILLABLE) == 0)
  278.                                 fCurrentDV->validate(value);
  279.                         }
  280.                         else if (fNil) {
  281.                             emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
  282.                         }
  283.                         else
  284.                             fCurrentDV->validate(value);
  285.                     }
  286.                 }
  287.             } catch (InvalidDatatypeValueException idve) {
  288.                 emitError (XMLValid::DatatypeError, idve.getType(), idve.getMessage());
  289.             }
  290.             catch (InvalidDatatypeFacetException idve) {
  291.                 emitError (XMLValid::DatatypeError, idve.getType(), idve.getMessage());
  292.             }
  293.             catch (...) {
  294.                 emitError(XMLValid::GenericError);
  295.                 throw;
  296.             }
  297.         }
  298.     }
  299.      else
  300.     {
  301.         ThrowXML(RuntimeException, XMLExcepts::CM_UnknownCMType);
  302.     }
  303.     fDatatypeBuffer.reset();
  304.     fNil = false;
  305.     fTrailing=false;
  306.     // Went ok, so return success
  307.     return -1;
  308. }
  309. void SchemaValidator::faultInAttr (XMLAttr&    toFill, const XMLAttDef&  attDef)   const
  310. {
  311.     //
  312.     //  At this level, we cannot set the URI id. So we just set it to zero
  313.     //  and leave it at that. The scanner, who called us, will look at the
  314.     //  prefix we stored (if any), resolve it, and store the URL id if any.
  315.     //
  316.     SchemaAttDef* schemaAttDef = (SchemaAttDef*) &attDef;
  317.     QName* attName = schemaAttDef->getAttName();
  318.     toFill.set
  319.     (
  320.           attName->getURI()
  321.         , attName->getLocalPart()
  322.         , attName->getPrefix()
  323.         , schemaAttDef->getValue()
  324.         , schemaAttDef->getType()
  325.     );
  326. }
  327. void SchemaValidator::reset()
  328. {
  329.     fTrailing = false;
  330.     delete fXsiType;
  331.     fXsiType = 0;
  332.     fXsiTypeValidator = 0;
  333.     fNil = false;
  334.     fDatatypeBuffer.reset();
  335. }
  336. bool SchemaValidator::requiresNamespaces() const
  337. {
  338.     return true;
  339. }
  340. void SchemaValidator::validateAttrValue (const   XMLAttDef* attDef
  341.                                        , const XMLCh* const attrValue)
  342. {
  343.     //
  344.     //  Get quick refs to lot of the stuff in the passed objects in
  345.     //  order to simplify the code below, which will reference them very
  346.     //  often.
  347.     //
  348.     XMLAttDef::AttTypes            type      = attDef->getType();
  349.     const XMLAttDef::DefAttTypes   defType   = attDef->getDefaultType();
  350.     const XMLCh* const             fullName  = attDef->getFullName();
  351.     //
  352.     //  If the default type is fixed, then make sure the passed value maps
  353.     //  to the fixed value.
  354.     //
  355.     if (defType == XMLAttDef::Fixed || defType == XMLAttDef::Required_And_Fixed)
  356.     {
  357.         const XMLCh* const valueText = attDef->getValue();
  358.         if (XMLString::compareString(attrValue, valueText))
  359.             emitError(XMLValid::NotSameAsFixedValue, fullName, attrValue, valueText);
  360.     }
  361.     // An empty string cannot be valid for non_CDATA any of the other types
  362.     if (!attrValue[0] && type != XMLAttDef::Simple)
  363.     {
  364.         emitError(XMLValid::InvalidEmptyAttValue, fullName);
  365.         return;
  366.     }
  367.     DatatypeValidator* attDefDV = ((SchemaAttDef*) attDef)->getDatatypeValidator();
  368.     if (!attDefDV) {
  369.         emitError(XMLValid::NoDatatypeValidatorForAttribute, fullName);
  370.     }
  371.     else {
  372.         try {
  373.             DatatypeValidator::ValidatorType attDefDVType = attDefDV->getType();
  374.             // set up the entitydeclpool in ENTITYDatatypeValidator
  375.             // and the idreflist in ID/IDREFDatatypeValidator
  376.             if (attDefDVType == DatatypeValidator::List) {
  377.                 DatatypeValidator* itemDTV = ((ListDatatypeValidator*)attDefDV)->getItemTypeDTV();
  378.                 DatatypeValidator::ValidatorType itemDTVType = itemDTV->getType();
  379.                 if (itemDTVType == DatatypeValidator::ENTITY)
  380.                     ((ENTITYDatatypeValidator*)itemDTV)->setEntityDeclPool(getScanner()->getEntityDeclPool());
  381.                 else if (itemDTVType == DatatypeValidator::ID)
  382.                     ((IDDatatypeValidator*)itemDTV)->setIDRefList(getScanner()->getIDRefList());
  383.                 else if (itemDTVType == DatatypeValidator::IDREF)
  384.                     ((IDREFDatatypeValidator*)itemDTV)->setIDRefList(getScanner()->getIDRefList());
  385.             }
  386.             else if (attDefDVType == DatatypeValidator::Union) {
  387.                 RefVectorOf<DatatypeValidator>* memberDTV = ((UnionDatatypeValidator*)attDefDV)->getMemberTypeValidators();
  388.                 unsigned int memberTypeNumber = memberDTV->size();
  389.                 for ( unsigned int memberIndex = 0; memberIndex < memberTypeNumber; ++memberIndex)
  390.                 {
  391.                     DatatypeValidator::ValidatorType memberDTVType = memberDTV->elementAt(memberIndex)->getType();
  392.                     if (memberDTVType == DatatypeValidator::ENTITY)
  393.                         ((ENTITYDatatypeValidator*)memberDTV->elementAt(memberIndex))->setEntityDeclPool(getScanner()->getEntityDeclPool());
  394.                     else if (memberDTVType == DatatypeValidator::ID)
  395.                         ((IDDatatypeValidator*)memberDTV->elementAt(memberIndex))->setIDRefList(getScanner()->getIDRefList());
  396.                     else if (memberDTVType == DatatypeValidator::IDREF)
  397.                         ((IDREFDatatypeValidator*)memberDTV->elementAt(memberIndex))->setIDRefList(getScanner()->getIDRefList());
  398.                 }
  399.             }
  400.             else if (attDefDVType == DatatypeValidator::ENTITY)
  401.                 ((ENTITYDatatypeValidator*)attDefDV)->setEntityDeclPool(getScanner()->getEntityDeclPool());
  402.             else if (attDefDVType == DatatypeValidator::ID)
  403.                 ((IDDatatypeValidator*)attDefDV)->setIDRefList(getScanner()->getIDRefList());
  404.             else if (attDefDVType == DatatypeValidator::IDREF)
  405.                 ((IDREFDatatypeValidator*)attDefDV)->setIDRefList(getScanner()->getIDRefList());
  406.             // now validate the attribute value
  407.             // if notation, need to bind URI to notation first
  408.             if (attDefDVType == DatatypeValidator::NOTATION)
  409.             {
  410.                 //
  411.                 //  Make sure that this value maps to one of the
  412.                 //  notation values in the enumList parameter. We don't have to
  413.                 //  look it up in the notation pool (if a notation) because we
  414.                 //  will look up the enumerated values themselves. If they are in
  415.                 //  the notation pool (after the Grammar is parsed), then obviously
  416.                 //  this value will be legal since it matches one of them.
  417.                 //
  418.                 XMLBuffer nameBuf(XMLString::stringLen(attrValue)+1);
  419.                 XMLBuffer prefixBuf(XMLString::stringLen(attrValue)+1);
  420.                 XMLBuffer notationBuf;
  421.                 unsigned int uriId = getScanner()->resolveQName(attrValue, nameBuf, prefixBuf, ElemStack::Mode_Element);
  422.                 notationBuf.set(getScanner()->getURIText(uriId));
  423.                 notationBuf.append(chColon);
  424.                 notationBuf.append(nameBuf.getRawBuffer());
  425.                 attDefDV->validate(notationBuf.getRawBuffer());
  426.             }
  427.             else
  428.                 attDefDV->validate(attrValue);
  429.         } catch (InvalidDatatypeValueException idve) {
  430.             emitError (XMLValid::DatatypeError, idve.getType(), idve.getMessage());
  431.         }
  432.         catch (InvalidDatatypeFacetException idve) {
  433.             emitError (XMLValid::DatatypeError, idve.getType(), idve.getMessage());
  434.         }
  435.         catch (...) {
  436.             emitError(XMLValid::GenericError);
  437.             throw;
  438.         }
  439.     }
  440.     fDatatypeBuffer.reset();
  441.     fTrailing = false;
  442. }
  443. void SchemaValidator::validateElement(const   XMLElementDecl*  elemDef)
  444. {
  445.     if (fXsiType) {
  446.         // handle "xsi:type" right here
  447.         unsigned int uri = fXsiType->getURI();
  448.         const XMLCh* localPart = fXsiType->getLocalPart();
  449.         if (uri != XMLElementDecl::fgInvalidElemId || uri != XMLElementDecl::fgPCDataElemId) {
  450.             // retrieve Grammar for the uri
  451.             const XMLCh* uriStr = getScanner()->getURIText(uri);
  452.             SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uriStr);
  453.             if (!sGrammar || sGrammar->getGrammarType() != Grammar::SchemaGrammarType) {
  454.                 // Grammar not found
  455.                 emitError(XMLValid::GrammarNotFound, uriStr);
  456.             }
  457.             else {
  458.                 // retrieve complexType registry and DatatypeValidator registry
  459.                 RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar->getComplexTypeRegistry();
  460.                 DatatypeValidatorFactory* dataTypeReg = fGrammarResolver->getDatatypeRegistry();
  461.                 if (!complexTypeRegistry || !dataTypeReg)
  462.                     emitError(XMLValid::BadXsiType, fXsiType->getRawName());
  463.                 else {
  464.                     // retrieve the typeInfo specified in xsi:type
  465.                     XMLBuffer aBuffer;
  466.                     aBuffer.set(uriStr);
  467.                     aBuffer.append(chComma);
  468.                     aBuffer.append(localPart);
  469.                     ComplexTypeInfo* typeInfo = complexTypeRegistry->get(aBuffer.getRawBuffer());
  470.                     if (typeInfo) {
  471.                         // typeInfo is found
  472.                         bool error = false;
  473.                         if (typeInfo->getAbstract()) {
  474.                             emitError(XMLValid::NoAbstractInXsiType, aBuffer.getRawBuffer());
  475.                             error = true;
  476.                         }
  477.                         ComplexTypeInfo* destType = ((SchemaElementDecl*)elemDef)->getComplexTypeInfo();
  478.                         ComplexTypeInfo* tempType = typeInfo;
  479.                         if (destType) {
  480.                             while (tempType) {
  481.                                 if (!XMLString::compareString(tempType->getTypeName(), destType->getTypeName()))
  482.                                     break;
  483.                                 tempType = tempType->getBaseComplexTypeInfo();
  484.                             }
  485.                             if (!tempType) {
  486.                                 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
  487.                                 error = true;
  488.                             }
  489.                             else {
  490.                                 int derivationMethod = typeInfo->getDerivedBy();
  491.                                 if ((((SchemaElementDecl*)elemDef)->getBlockSet() & derivationMethod) != 0) {
  492.                                     emitError(XMLValid::NoSubforBlock, fXsiType->getRawName(), elemDef->getFullName());
  493.                                     error = true;
  494.                                 }
  495.                             }
  496.                         }
  497.                         else {
  498.                             // if the original type is a simple type, check derivation ok.
  499.                             DatatypeValidator* ancestorValidator = ((SchemaElementDecl*)elemDef)->getDatatypeValidator();
  500.                             if (ancestorValidator && !ancestorValidator->isSubstitutableBy(fXsiTypeValidator)) {
  501.                                 // the type is not derived from ancestor
  502.                                 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
  503.                                 error = true;
  504.                             }
  505.                         }
  506.                         if (!error)
  507.                             ((SchemaElementDecl*)elemDef)->setXsiComplexTypeInfo(typeInfo);
  508.                     }
  509.                     else {
  510.                         // typeInfo not found
  511.                         if (!XMLString::compareString(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA))
  512.                             fXsiTypeValidator = dataTypeReg->getDatatypeValidator(localPart);
  513.                         else
  514.                             fXsiTypeValidator = dataTypeReg->getDatatypeValidator(aBuffer.getRawBuffer());
  515.                         if (!fXsiTypeValidator)
  516.                             emitError(XMLValid::BadXsiType, fXsiType->getRawName());
  517.                         else {
  518.                             DatatypeValidator* ancestorValidator = ((SchemaElementDecl*)elemDef)->getDatatypeValidator();
  519.                             if (ancestorValidator && !ancestorValidator->isSubstitutableBy(fXsiTypeValidator)) {
  520.                                 // the type is not derived from ancestor
  521.                                 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
  522.                             }
  523.                             else {
  524.                                 // the type is derived from ancestor
  525.                                 if (((SchemaElementDecl*)elemDef)->getBlockSet() == SchemaSymbols::RESTRICTION)
  526.                                     emitError(XMLValid::NoSubforBlock, fXsiType->getRawName(), elemDef->getFullName());
  527.                                 if (elemDef->hasAttDefs()) {
  528.                                     // if we have an attribute but xsi:type's type is simple, we have a problem...
  529.                                     emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
  530.                                 }
  531.                             }
  532.                         }
  533.                     }
  534.                 }
  535.             }
  536.         }
  537.         delete fXsiType;
  538.         fXsiType = 0;
  539.     }
  540.     else {
  541.         //
  542.         // xsi:type was not specified...
  543.         // If the corresponding type is abstract, detect an error
  544.         //
  545.         ComplexTypeInfo* typeInfo = ((SchemaElementDecl*)elemDef)->getComplexTypeInfo();
  546.         if (typeInfo) {
  547.             if (typeInfo->getAbstract()) {
  548.                 emitError(XMLValid::NoUseAbstractType, elemDef->getFullName());
  549.             }
  550.         }
  551.     }
  552.     //
  553.     // Check whether this element is abstract.  If so, an error
  554.     //
  555.     int miscFlags = ((SchemaElementDecl*)elemDef)->getMiscFlags();
  556.     if ((miscFlags & SchemaSymbols::ABSTRACT) != 0) {
  557.         emitError(XMLValid::NoDirectUseAbstractElement, elemDef->getFullName());
  558.     }
  559.     //
  560.     // Check whether this element allows Nillable
  561.     //
  562.     if (fNil && (miscFlags & SchemaSymbols::NILLABLE) == 0 ) {
  563.         fNil = false;
  564.         emitError(XMLValid::NillNotAllowed, elemDef->getFullName());
  565.     }
  566.     fDatatypeBuffer.reset();
  567.     fTrailing = false;
  568. }
  569. void SchemaValidator::preContentValidation(bool reuseGrammar)
  570. {
  571.     //  Lets go through all the grammar in the GrammarResolver
  572.     //    and validate those that has not been validated yet
  573.     //
  574.     //  Lets enumerate all of the elements in the element decl pool
  575.     //    and put out an error for any that did not get declared.
  576.     //    We also check all of the attributes as well.
  577.     //
  578.     //  And enumerate all the complextype info in the grammar
  579.     //    and do Unique Particle Attribution Checking
  580.     RefHashTableOfEnumerator<Grammar> grammarEnum = fGrammarResolver->getGrammarEnumerator();
  581.     while (grammarEnum.hasMoreElements())
  582.     {
  583.         SchemaGrammar& sGrammar = (SchemaGrammar&) grammarEnum.nextElement();
  584.         if (sGrammar.getGrammarType() != Grammar::SchemaGrammarType || sGrammar.getUPAChecked())
  585.              continue;
  586.         sGrammar.setUPAChecked(true);
  587.         RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = sGrammar.getElemEnumerator();
  588.         while (elemEnum.hasMoreElements())
  589.         {
  590.             SchemaElementDecl& curElem = elemEnum.nextElement();
  591.             //  First check if declared or not
  592.             //
  593.             //  See if this element decl was ever marked as declared. If
  594.             //  not, then put out an error. In some cases its just
  595.             //  a warning, such as being referenced in a content model.
  596.             //
  597.             const SchemaElementDecl::CreateReasons reason = curElem.getCreateReason();
  598.             if (reason != XMLElementDecl::Declared)
  599.             {
  600.                 if (reason == XMLElementDecl::AttList)
  601.                 {
  602.                     getScanner()->emitError
  603.                     (
  604.                         XMLErrs::UndeclaredElemInAttList
  605.                         , curElem.getFullName()
  606.                     );
  607.                 }
  608.                  else if (reason == XMLElementDecl::AsRootElem)
  609.                 {
  610.                     emitError
  611.                     (
  612.                         XMLValid::UndeclaredElemInDocType
  613.                         , curElem.getFullName()
  614.                     );
  615.                 }
  616.                  else if (reason == XMLElementDecl::InContentModel)
  617.                 {
  618.                     getScanner()->emitError
  619.                     (
  620.                         XMLErrs::UndeclaredElemInCM
  621.                         , curElem.getFullName()
  622.                     );
  623.                 }
  624.                 else
  625.                 {
  626.                 }
  627.             }
  628.             //
  629.             //  Then check all of the attributes of the current element.
  630.             //  We check for:
  631.             //
  632.             //  1) Multiple ID attributes
  633.             //  2) That all of the default values of attributes are
  634.             //      valid for their type.
  635.             //  3) That for any notation types, that their lists
  636.             //      of possible values refer to declared notations.
  637.             //
  638.             if (curElem.hasAttDefs()) {
  639.                 XMLAttDefList& attDefList = curElem.getAttDefList();
  640.                 bool seenId = false;
  641.                 while (attDefList.hasMoreElements())
  642.                 {
  643.                     const XMLAttDef& curAttDef = attDefList.nextElement();
  644.                     if (curAttDef.getType() == XMLAttDef::ID)
  645.                     {
  646.                         if (seenId)
  647.                         {
  648.                             emitError
  649.                             (
  650.                                 XMLValid::MultipleIdAttrs
  651.                                 , curElem.getFullName()
  652.                             );
  653.                             break;
  654.                         }
  655.                         seenId = true;
  656.                     }
  657.                      else if (curAttDef.getType() == XMLAttDef::Notation)
  658.                     {
  659.                         //
  660.                         //  We need to verify that all of its possible values
  661.                         //  (in the enum list) refer to valid notations.
  662.                         //
  663.                         XMLCh* list = XMLString::replicate(curAttDef.getEnumeration());
  664.                         ArrayJanitor<XMLCh> janList(list);
  665.                         //
  666.                         //  Search forward for a space or a null. If a null,
  667.                         //  we are done. If a space, cap it and look it up.
  668.                         //
  669.                         bool    breakFlag = false;
  670.                         XMLCh*  listPtr = list;
  671.                         XMLCh*  lastPtr = listPtr;
  672.                         while (true)
  673.                         {
  674.                             while (*listPtr && (*listPtr != chSpace))
  675.                                 listPtr++;
  676.                             //
  677.                             //  If at the end, indicate we need to break after
  678.                             //  this one. Else, cap it off here.
  679.                             //
  680.                             if (!*listPtr)
  681.                                 breakFlag = true;
  682.                             else
  683.                                 *listPtr = chNull;
  684.                             if (!sGrammar.getNotationDecl(lastPtr))
  685.                             {
  686.                                 emitError
  687.                                 (
  688.                                     XMLValid::UnknownNotRefAttr
  689.                                     , curAttDef.getFullName()
  690.                                     , lastPtr
  691.                                 );
  692.                             }
  693.                             // Break out if we hit the end last time
  694.                             if (breakFlag)
  695.                                 break;
  696.                             // Else move upwards and try again
  697.                             listPtr++;
  698.                             lastPtr = listPtr;
  699.                         }
  700.                     }
  701.                     // If it has a default/fixed value, then validate it
  702.                     if (curAttDef.getValue())
  703.                     {
  704.                         validateAttrValue
  705.                         (
  706.                             &curAttDef
  707.                             , curAttDef.getValue()
  708.                         );
  709.                     }
  710.                 }
  711.             }
  712.         }
  713.         //  For each complex type info, check the Unique Particle Attribution
  714.         if (getScanner()->getValidationSchemaFullChecking()) {
  715.             RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar.getComplexTypeRegistry();
  716.             RefHashTableOfEnumerator<ComplexTypeInfo> complexTypeEnum(complexTypeRegistry);
  717.             while (complexTypeEnum.hasMoreElements())
  718.             {
  719.                 ComplexTypeInfo& curTypeInfo = complexTypeEnum.nextElement();
  720.                 curTypeInfo.checkUniqueParticleAttribution(&sGrammar, fGrammarResolver, getScanner()->getURIStringPool(), this);
  721.             }
  722.         }
  723.     }
  724. }
  725. void SchemaValidator::postParseValidation()
  726. {
  727.     //
  728.     //  At this time, there is nothing to do here. The scanner itself handles
  729.     //  ID/IDREF validation, since that is the same no matter what kind of
  730.     //  validator.
  731.     //
  732. }
  733. // ---------------------------------------------------------------------------
  734. //  SchemaValidator: Validator method
  735. // ---------------------------------------------------------------------------
  736. // Do Schema Normalization depends on the WhiteSpace Facet
  737. // preserve : No normalization is done
  738. // replace  : All occurrences of #x9 (tab), #xA (linefeed) and #xD (carriage return)
  739. //            are replaced with #x20 (space).
  740. // collapse : Subsequent to the replacements specified above under replace,
  741. //            contiguous sequences of #x20s are collapsed to a single #x20,
  742. //            and initial and/or final #x20s are deleted.
  743. //
  744. void SchemaValidator::normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* const value, XMLBuffer& toFill)
  745. {
  746.     short fWhiteSpace = DatatypeValidator::PRESERVE;
  747.     if (dV)
  748.         fWhiteSpace = dV->getWSFacet();
  749.     enum States
  750.     {
  751.         InWhitespace
  752.         , InContent
  753.     };
  754.     States curState = InContent;
  755.     toFill.reset();
  756.     //
  757.     //  Loop through the chars of the source value and normalize it according
  758.     //  to the whitespace facet
  759.     //
  760.     bool firstNonWS = false;
  761.     XMLCh nextCh;
  762.     const XMLCh* srcPtr = value;
  763.     if ((fWhiteSpace==DatatypeValidator::COLLAPSE) && fTrailing)
  764.         toFill.append(chSpace);
  765.     while (*srcPtr)
  766.     {
  767.         nextCh = *srcPtr;
  768.         if (fWhiteSpace == DatatypeValidator::PRESERVE)
  769.         {
  770.             // do nothing
  771.         }
  772.         else if (fWhiteSpace == DatatypeValidator::REPLACE)
  773.         {
  774.             if (XMLReader::isWhitespace(nextCh))
  775.                 nextCh = chSpace;
  776.         }
  777.         else // COLLAPSE case
  778.         {
  779.             if (curState == InWhitespace)
  780.             {
  781.                 if (!XMLReader::isWhitespace(nextCh))
  782.                 {
  783.                     if (firstNonWS)
  784.                         toFill.append(chSpace);
  785.                     curState = InContent;
  786.                     firstNonWS = true;
  787.                 }
  788.                  else
  789.                 {
  790.                     srcPtr++;
  791.                     continue;
  792.                 }
  793.             }
  794.              else if (curState == InContent)
  795.             {
  796.                 if (XMLReader::isWhitespace(nextCh))
  797.                 {
  798.                     curState = InWhitespace;
  799.                     srcPtr++;
  800.                     continue;
  801.                 }
  802.                 firstNonWS = true;
  803.             }
  804.         }
  805.         // Add this char to the target buffer
  806.         toFill.append(nextCh);
  807.         // stored the content for validation later
  808.         //fDatatypeBuffer.append(nextCh);
  809.         // And move up to the next character in the source
  810.         srcPtr++;
  811.     }
  812.     srcPtr--;
  813.     nextCh = *srcPtr;
  814.     if (XMLReader::isWhitespace(nextCh))
  815.         fTrailing = true;
  816.     fDatatypeBuffer.append(toFill.getRawBuffer());
  817. }