GME  13
XercesXPath.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: XercesXPath.cpp 903997 2010-01-28 08:28:06Z borisk $
00020  */
00021 
00022 // ---------------------------------------------------------------------------
00023 //  Includes
00024 // ---------------------------------------------------------------------------
00025 #include <xercesc/validators/schema/identity/XercesXPath.hpp>
00026 #include <xercesc/validators/schema/identity/XPathSymbols.hpp>
00027 #include <xercesc/validators/schema/identity/XPathException.hpp>
00028 #include <xercesc/validators/schema/NamespaceScope.hpp>
00029 #include <xercesc/util/StringPool.hpp>
00030 #include <xercesc/util/Janitor.hpp>
00031 #include <xercesc/framework/XMLBuffer.hpp>
00032 #include <xercesc/internal/XMLReader.hpp>
00033 #include <xercesc/util/RuntimeException.hpp>
00034 #include <xercesc/util/OutOfMemoryException.hpp>
00035 
00036 #include <xercesc/internal/XTemplateSerializer.hpp>
00037 
00038 XERCES_CPP_NAMESPACE_BEGIN
00039 
00040 
00041 // ---------------------------------------------------------------------------
00042 //  Static data
00043 // ---------------------------------------------------------------------------
00044 const XMLByte XPathScanner::fASCIICharMap[128] =
00045 {
00046     0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  2,  0,  0,
00047     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
00048     2,  3,  4,  1,  5,  1,  1,  4,  6,  7,  8,  9, 10, 11, 12, 13,
00049     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,  1, 16, 17, 18,  1,
00050     19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
00051     20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,  1, 22,  1, 23,
00052     1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
00053     20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  1, 24,  1,  1,  1
00054 };
00055 
00056 
00057 // ---------------------------------------------------------------------------
00058 //  XercesNodeTest: Constructors and Destructor
00059 // ---------------------------------------------------------------------------
00060 XercesNodeTest::XercesNodeTest(const short aType,
00061                                MemoryManager* const manager)
00062     : fType(aType)
00063     , fName(new (manager) QName(manager))
00064 {
00065 }
00066 
00067 XercesNodeTest::XercesNodeTest(const QName* const qName)
00068     : fType(NodeType_QNAME)
00069     , fName(new (qName->getMemoryManager()) QName(*qName))
00070 {
00071 }
00072 
00073 XercesNodeTest::XercesNodeTest(const XMLCh* const prefix,
00074                                const unsigned int uriId,
00075                                MemoryManager* const manager)
00076     : fType(NodeType_NAMESPACE)
00077     , fName(new (manager) QName(manager))
00078 {
00079     fName->setURI(uriId);
00080     fName->setPrefix(prefix);
00081 }
00082 
00083 XercesNodeTest::XercesNodeTest(const XercesNodeTest& other)
00084     : XSerializable(other)
00085     , XMemory(other)
00086     , fType(other.fType)
00087     , fName(new ((other.fName)->getMemoryManager()) QName(*other.fName))
00088 {
00089 }
00090 
00091 /***
00092  * Support for Serialization/De-serialization
00093  ***/
00094 
00095 IMPL_XSERIALIZABLE_TOCREATE(XercesNodeTest)
00096 
00097 void XercesNodeTest::serialize(XSerializeEngine& serEng)
00098 {
00099 
00100     if (serEng.isStoring())
00101     {
00102         serEng<<fType;
00103         serEng<<fName;
00104     }
00105     else
00106     {
00107         serEng>>fType;
00108         serEng>>fName;
00109     }
00110 }
00111 
00112 XercesNodeTest::XercesNodeTest(MemoryManager* const)
00113 :fType(NodeType_UNKNOWN)
00114 ,fName(0)
00115 {
00116 }
00117 
00118 // ---------------------------------------------------------------------------
00119 //  XercesNodeTest: Operators
00120 // ---------------------------------------------------------------------------
00121 XercesNodeTest& XercesNodeTest::operator=(const XercesNodeTest& other)
00122 {
00123     if (this == &other)
00124         return *this;
00125 
00126     fType = other.fType;
00127     fName->setValues(*(other.fName));
00128     return *this;
00129 }
00130 
00131 bool XercesNodeTest::operator ==(const XercesNodeTest& other) const {
00132 
00133     if (this == &other)
00134         return true;
00135 
00136     if (fType != other.fType)
00137         return false;
00138 
00139     return (*fName == *(other.fName));
00140 }
00141 
00142 
00143 bool XercesNodeTest::operator !=(const XercesNodeTest& other) const {
00144 
00145     return !operator==(other);
00146 }
00147 
00148 // ---------------------------------------------------------------------------
00149 //  XercesStep: Constructors and Destructor
00150 // ---------------------------------------------------------------------------
00151 XercesStep::XercesStep(const unsigned short axisType, XercesNodeTest* const nodeTest)
00152     : fAxisType(axisType)
00153     , fNodeTest(nodeTest)
00154 {
00155 }
00156 
00157 XercesStep::XercesStep(const XercesStep& other)
00158     : XSerializable(other)
00159     , XMemory(other)
00160     , fAxisType(other.fAxisType)
00161     , fNodeTest(0)
00162 {
00163     fNodeTest = new (other.fNodeTest->getName()->getMemoryManager()) XercesNodeTest(*(other.fNodeTest));
00164 }
00165 
00166 
00167 // ---------------------------------------------------------------------------
00168 //  XercesStep: Operators
00169 // ---------------------------------------------------------------------------
00170 XercesStep& XercesStep::operator=(const XercesStep& other)
00171 {
00172     if (this == &other)
00173         return *this;
00174 
00175     fAxisType = other.fAxisType;
00176     *fNodeTest = *(other.fNodeTest);
00177     return *this;
00178 }
00179 
00180 bool XercesStep::operator==(const XercesStep& other) const {
00181 
00182     if (this == &other)
00183         return true;
00184 
00185     if (fAxisType != other.fAxisType)
00186         return false;
00187 
00188     if (fAxisType == XercesStep::AxisType_CHILD ||
00189         fAxisType == XercesStep::AxisType_ATTRIBUTE) {
00190         return (*fNodeTest == *(other.fNodeTest));
00191     }
00192 
00193     return true;
00194 }
00195 
00196 bool XercesStep::operator!=(const XercesStep& other) const {
00197 
00198     return !operator==(other);
00199 }
00200 
00201 /***
00202  * Support for Serialization/De-serialization
00203  ***/
00204 
00205 IMPL_XSERIALIZABLE_TOCREATE(XercesStep)
00206 
00207 void XercesStep::serialize(XSerializeEngine& serEng)
00208 {
00209     if (serEng.isStoring())
00210     {
00211         serEng<<(int)fAxisType;
00212         serEng<<fNodeTest;
00213     }
00214     else
00215     {
00216         int i;
00217         serEng>>i;
00218         fAxisType = (unsigned short) i;
00219 
00220         serEng>>fNodeTest;
00221     }
00222 }
00223 
00224 XercesStep::XercesStep(MemoryManager* const)
00225 :fAxisType(AxisType_UNKNOWN)
00226 ,fNodeTest(0)
00227 {
00228 }
00229 
00230 // ---------------------------------------------------------------------------
00231 //  XercesLocationPath: Constructors and Destructor
00232 // ---------------------------------------------------------------------------
00233 XercesLocationPath::XercesLocationPath(RefVectorOf<XercesStep>* const steps)
00234     : fSteps(steps)
00235 {
00236 }
00237 
00238 // ---------------------------------------------------------------------------
00239 //  XercesLocationPath: Operators
00240 // ---------------------------------------------------------------------------
00241 bool XercesLocationPath::operator==(const XercesLocationPath& other) const {
00242 
00243     XMLSize_t stepsSize = fSteps->size();
00244 
00245     if (stepsSize != other.fSteps->size())
00246         return false;
00247 
00248     for (XMLSize_t i=0; i < stepsSize; i++) {
00249         if (*(fSteps->elementAt(i)) != *(other.fSteps->elementAt(i)))
00250             return false;
00251     }
00252 
00253     return true;
00254 }
00255 
00256 bool XercesLocationPath::operator!=(const XercesLocationPath& other) const {
00257 
00258     return !operator==(other);
00259 }
00260 
00261 /***
00262  * Support for Serialization/De-serialization
00263  ***/
00264 
00265 IMPL_XSERIALIZABLE_TOCREATE(XercesLocationPath)
00266 
00267 void XercesLocationPath::serialize(XSerializeEngine& serEng)
00268 {
00269     if (serEng.isStoring())
00270     {
00271         /***
00272          * Serialize RefVectorOf<XercesStep>* fSteps;
00273          ***/
00274         XTemplateSerializer::storeObject(fSteps, serEng);
00275     }
00276     else
00277     {
00278         /***
00279          * Deserialize RefVectorOf<XercesStep>* fSteps;
00280          ***/
00281         XTemplateSerializer::loadObject(&fSteps, 8, true, serEng);
00282     }
00283 }
00284 
00285 XercesLocationPath::XercesLocationPath(MemoryManager* const)
00286 :fSteps(0)
00287 {
00288 }
00289 
00290 typedef JanitorMemFunCall<XercesXPath>  CleanupType;
00291 
00292 // ---------------------------------------------------------------------------
00293 //  XercesPath: Constructors and Destructor
00294 // ---------------------------------------------------------------------------
00295 XercesXPath::XercesXPath(const XMLCh* const xpathExpr,
00296                          XMLStringPool* const stringPool,
00297                          XercesNamespaceResolver* const scopeContext,
00298                          const unsigned int emptyNamespaceId,
00299                          const bool isSelector,
00300                          MemoryManager* const manager)
00301     : fEmptyNamespaceId(emptyNamespaceId)
00302     , fExpression(0)
00303     , fLocationPaths(0)
00304     , fMemoryManager(manager)
00305 {
00306     CleanupType cleanup(this, &XercesXPath::cleanUp);
00307 
00308     try
00309     {
00310         fExpression = XMLString::replicate(xpathExpr, fMemoryManager);
00311         parseExpression(stringPool, scopeContext);
00312 
00313         if (isSelector) {
00314             checkForSelectedAttributes();
00315         }
00316     }
00317     catch(const OutOfMemoryException&)
00318     {
00319         cleanup.release();
00320 
00321         throw;
00322     }
00323 
00324     cleanup.release();
00325 }
00326 
00327 XercesXPath::~XercesXPath() {
00328     cleanUp();
00329 }
00330 
00331 
00332 // ---------------------------------------------------------------------------
00333 //  XercesXPath: Operators
00334 // ---------------------------------------------------------------------------
00335 bool XercesXPath::operator==(const XercesXPath& other) const {
00336 
00337     XMLSize_t locPathSize = fLocationPaths->size();
00338 
00339     if (locPathSize != other.fLocationPaths->size())
00340         return false;
00341 
00342     for (XMLSize_t i=0; i < locPathSize; i++) {
00343         if (*(fLocationPaths->elementAt(i)) != *(other.fLocationPaths->elementAt(i)))
00344             return false;
00345     }
00346 
00347     return true;
00348 }
00349 
00350 bool XercesXPath::operator!=(const XercesXPath& other) const {
00351 
00352     return !operator==(other);
00353 }
00354 
00355 // ---------------------------------------------------------------------------
00356 //  XercesPath: Helper methods
00357 // ---------------------------------------------------------------------------
00358 void XercesXPath::cleanUp() {
00359 
00360     fMemoryManager->deallocate(fExpression);//delete [] fExpression;
00361     delete fLocationPaths;
00362 }
00363 
00364 void XercesXPath::checkForSelectedAttributes() {
00365 
00366     // verify that an attribute is not selected
00367     XMLSize_t locSize = (fLocationPaths) ? fLocationPaths->size() : 0;
00368 
00369     for (XMLSize_t i = 0; i < locSize; i++) {
00370 
00371         XercesLocationPath* locPath = fLocationPaths->elementAt(i);
00372         XMLSize_t stepSize = locPath->getStepSize();
00373 
00374         if (stepSize) {
00375             if (locPath->getStep(stepSize - 1)->getAxisType() == XercesStep::AxisType_ATTRIBUTE) {
00376                 ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoAttrSelector, fMemoryManager);
00377             }
00378                 }
00379     }
00380 }
00381 
00382 void XercesXPath::parseExpression(XMLStringPool* const stringPool,
00383                                   XercesNamespaceResolver* const scopeContext) {
00384 
00385     XMLSize_t length = XMLString::stringLen(fExpression);
00386 
00387     if (!length) {
00388         return;
00389     }
00390 
00391     ValueVectorOf<int>                tokens(16, fMemoryManager);
00392     XPathScannerForSchema             scanner(stringPool);
00393     if(!scanner.scanExpression(fExpression, 0, length, &tokens))
00394         ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_TokenNotSupported, fMemoryManager);
00395 
00396     bool                              firstTokenOfLocationPath=true;
00397     XMLSize_t                         tokenCount = tokens.size();
00398     RefVectorOf<XercesStep>*          stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
00399     Janitor<RefVectorOf<XercesStep> > janSteps(stepsVector);
00400 
00401     if (tokenCount) {
00402         fLocationPaths = new (fMemoryManager) RefVectorOf<XercesLocationPath>(8, true, fMemoryManager);
00403     }
00404 
00405     for (XMLSize_t i = 0; i < tokenCount; i++) {
00406 
00407         int  aToken = tokens.elementAt(i);
00408         bool isNamespace=false;
00409 
00410         switch (aToken) {
00411         case  XercesXPath::EXPRTOKEN_OPERATOR_UNION:
00412             {
00413                 if (i == 0) {
00414                     ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtStart, fMemoryManager);
00415                 }
00416 
00417                 XMLSize_t stepsSize = stepsVector->size();
00418 
00419                 if (stepsSize == 0) {
00420                     ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoMultipleUnion, fMemoryManager);
00421                 }
00422 
00423                 if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF)
00424                 {
00425                     // prepend ./
00426                     XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
00427                     XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
00428                     stepsVector->insertElementAt(step, 0);
00429                 }
00430                 XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector);
00431                 janSteps.orphan();
00432                 bool bFound=false;
00433                 for(XMLSize_t i=0;i<fLocationPaths->size();i++)
00434                     if((*(fLocationPaths->elementAt(i)))==(*newPath))
00435                     {
00436                         bFound=true;
00437                         break;
00438                     }
00439                 if(bFound)
00440                     delete newPath;
00441                 else
00442                     fLocationPaths->addElement(newPath);
00443                 stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
00444                 janSteps.reset(stepsVector);
00445                 firstTokenOfLocationPath = true;
00446             }
00447             break;
00448         case XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE:
00449             {
00450                 // consume "::" token and drop through
00451                 i++;
00452             }
00453         case XercesXPath::EXPRTOKEN_ATSIGN:
00454             {
00455                 // consume QName token
00456                 if (i == tokenCount - 1) {
00457                     ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_MissingAttr, fMemoryManager);
00458                 }
00459 
00460                 aToken = tokens.elementAt(++i);
00461 
00462                 if (aToken != XercesXPath::EXPRTOKEN_NAMETEST_QNAME
00463                     && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_ANY
00464                     && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE) {
00465                         ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedToken1, fMemoryManager);
00466                 }
00467 
00468                 bool isNamespaceAtt=false;
00469 
00470                 switch (aToken) {
00471 
00472                 case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
00473                     {
00474                         XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, fMemoryManager);
00475                         XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
00476                         stepsVector->addElement(step);
00477                         break;
00478                     }
00479                 case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
00480                     {
00481                         isNamespaceAtt = true;
00482                     }
00483                 case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
00484                     {
00485                         aToken = tokens.elementAt(++i);
00486 
00487                         const XMLCh* prefix = XMLUni::fgZeroLenString;
00488                         unsigned int uri = fEmptyNamespaceId;
00489 
00490                         if (scopeContext && aToken != -1) {
00491 
00492                             prefix = stringPool->getValueForId(aToken);
00493                             uri = scopeContext->getNamespaceForPrefix(prefix);
00494                         }
00495 
00496                         if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
00497                             ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager);
00498                         }
00499 
00500                         if (isNamespaceAtt) {
00501 
00502                             // build step
00503                             XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager);
00504                             XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
00505                             stepsVector->addElement(step);
00506                             break;
00507                         }
00508 
00509                         aToken = tokens.elementAt(++i);
00510 
00511                         const XMLCh* localPart = stringPool->getValueForId(aToken);
00512                         QName aQName(prefix, localPart, uri, fMemoryManager);
00513 
00514                         // build step
00515                         XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
00516                         XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
00517                         stepsVector->addElement(step);
00518                         break;
00519                     }
00520                                 }
00521 
00522                 firstTokenOfLocationPath=false;
00523                 break;
00524             }
00525         case XercesXPath::EXPRTOKEN_DOUBLE_COLON:
00526             {
00527                 // should never have a bare double colon
00528                 ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleColon, fMemoryManager);
00529             }
00530         case XercesXPath::EXPRTOKEN_AXISNAME_CHILD:
00531             {
00532                 // consume "::" token and drop through
00533                 i++;
00534 
00535                 if (i == tokenCount - 1) {
00536                     ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep1, fMemoryManager);
00537                 }
00538 
00539                 firstTokenOfLocationPath=false;
00540                 break;
00541             }
00542         case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
00543             {
00544                 XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, fMemoryManager);
00545                 XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
00546                 stepsVector->addElement(step);
00547                 firstTokenOfLocationPath = false;
00548                 break;
00549             }
00550         case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
00551             {
00552                 isNamespace=true;
00553             }
00554         case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
00555             {
00556                 // consume QName token
00557                 aToken = tokens.elementAt(++i);
00558 
00559                 const XMLCh* prefix = XMLUni::fgZeroLenString;
00560                 unsigned int uri = fEmptyNamespaceId;
00561 
00562                 if (scopeContext && aToken != -1) {
00563 
00564                     prefix = stringPool->getValueForId(aToken);
00565                     uri = scopeContext->getNamespaceForPrefix(prefix);
00566                 }
00567 
00568                 if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
00569                     ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager);
00570                 }
00571 
00572                 if (isNamespace) {
00573 
00574                     // build step
00575                     XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager);
00576                     XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
00577                     stepsVector->addElement(step);
00578                     break;
00579                 }
00580 
00581                 aToken = tokens.elementAt(++i);
00582                 const XMLCh* localPart = stringPool->getValueForId(aToken);
00583                 QName aQName(prefix, localPart, uri, fMemoryManager);
00584 
00585                 // build step
00586                 XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
00587                 XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
00588                 stepsVector->addElement(step);
00589                 firstTokenOfLocationPath = false;
00590                 break;
00591             }
00592         case XercesXPath::EXPRTOKEN_PERIOD:
00593             {
00594                 // build step
00595                 XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
00596                 XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
00597                 stepsVector->addElement(step);
00598 
00599                 if (firstTokenOfLocationPath && i+1 < tokenCount) {
00600 
00601                     aToken = tokens.elementAt(i+1);
00602 
00603                     if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH){
00604 
00605                         if (++i == tokenCount - 1) {
00606                             ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep2, fMemoryManager);
00607                         }
00608 
00609                         if (i+1 < tokenCount)   {
00610 
00611                             aToken = tokens.elementAt(i+1);
00612 
00613                             if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH) {
00614                                 ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlash, fMemoryManager);
00615                             }
00616                         }
00617                         // build step
00618                         nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
00619                         step = new (fMemoryManager) XercesStep(XercesStep::AxisType_DESCENDANT, nodeTest);
00620                         stepsVector->addElement(step);
00621                     }
00622                 }
00623                 firstTokenOfLocationPath=false;
00624                 break;
00625             }
00626         case XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH:
00627             {
00628                 ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleForwardSlash, fMemoryManager);
00629             }
00630         case XercesXPath::EXPRTOKEN_OPERATOR_SLASH:
00631             {
00632                 if (i == 0) {
00633                     ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlashAtStart, fMemoryManager);
00634                 }
00635 
00636                 // keep on truckin'
00637                 if (firstTokenOfLocationPath) {
00638                     ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoSelectionOfRoot, fMemoryManager);
00639                 }
00640 
00641                 if (i == tokenCount - 1) {
00642                     ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager);
00643                 }
00644 
00645                 aToken = tokens.elementAt(i+1);
00646                 if(aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_UNION)
00647                     ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager);
00648 
00649                 firstTokenOfLocationPath=false;
00650                 break;
00651             }
00652         default:
00653             firstTokenOfLocationPath=false;
00654         }
00655     }
00656 
00657     XMLSize_t stepsSize = stepsVector->size();
00658 
00659     if (stepsSize == 0) {
00660         if (!fLocationPaths || fLocationPaths->size() == 0) {
00661             ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_EmptyExpr, fMemoryManager);
00662         }
00663         else {
00664             ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtEnd, fMemoryManager);
00665         }
00666     }
00667 
00668     if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF)
00669     {
00670         // prepend ./
00671         XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
00672         XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
00673         stepsVector->insertElementAt(step, 0);
00674     }
00675     XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector);
00676     janSteps.orphan();
00677     bool bFound=false;
00678     for(XMLSize_t j=0;j<fLocationPaths->size();j++)
00679         if((*(fLocationPaths->elementAt(j)))==(*newPath))
00680         {
00681             bFound=true;
00682             break;
00683         }
00684     if(bFound)
00685         delete newPath;
00686     else
00687         fLocationPaths->addElement(newPath);
00688 }
00689 
00690 /***
00691  * Support for Serialization/De-serialization
00692  ***/
00693 
00694 IMPL_XSERIALIZABLE_TOCREATE(XercesXPath)
00695 
00696 void XercesXPath::serialize(XSerializeEngine& serEng)
00697 {
00698 
00699     if (serEng.isStoring())
00700     {
00701         serEng<<fEmptyNamespaceId;
00702         serEng.writeString(fExpression);
00703 
00704         /***
00705          * Serialize RefVectorOf<XercesLocationPath>* fLocationPaths;
00706          ***/
00707         XTemplateSerializer::storeObject(fLocationPaths, serEng);
00708     }
00709     else
00710     {
00711         serEng>>fEmptyNamespaceId;
00712         serEng.readString(fExpression);
00713 
00714         /***
00715          * Deserialize RefVectorOf<XercesLocationPath>* fLocationPaths;
00716          ***/
00717         XTemplateSerializer::loadObject(&fLocationPaths, 8, true, serEng);
00718     }
00719 }
00720 
00721 XercesXPath::XercesXPath(MemoryManager* const manager)
00722 :fEmptyNamespaceId(0)
00723 ,fExpression(0)
00724 ,fLocationPaths(0)
00725 ,fMemoryManager(manager)
00726 {
00727 }
00728 
00729 // ---------------------------------------------------------------------------
00730 //  XPathScanner: Constructors and Destructor
00731 // ---------------------------------------------------------------------------
00732 XPathScanner::XPathScanner(XMLStringPool* const stringPool)
00733     : fAndSymbol (0)
00734     , fOrSymbol(0)
00735     , fModSymbol(0)
00736     , fDivSymbol(0)
00737     , fCommentSymbol(0)
00738     , fTextSymbol(0)
00739     , fPISymbol(0)
00740     , fNodeSymbol(0)
00741     , fAncestorSymbol(0)
00742     , fAncestorOrSelfSymbol(0)
00743     , fAttributeSymbol(0)
00744     , fChildSymbol(0)
00745     , fDescendantSymbol(0)
00746     , fDescendantOrSelfSymbol(0)
00747     , fFollowingSymbol(0)
00748     , fFollowingSiblingSymbol(0)
00749     , fNamespaceSymbol(0)
00750     , fParentSymbol(0)
00751     , fPrecedingSymbol(0)
00752     , fPrecedingSiblingSymbol(0)
00753     , fSelfSymbol(0)
00754     , fStringPool(stringPool)
00755 {
00756     init();
00757 }
00758 
00759 // ---------------------------------------------------------------------------
00760 //  XPathScanner: Helper methods
00761 // ---------------------------------------------------------------------------
00762 void XPathScanner::init() {
00763 
00764     fAndSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_AND);
00765     fOrSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_OR);
00766     fModSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_MOD);
00767     fDivSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DIV);
00768     fCommentSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_COMMENT);
00769     fTextSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_TEXT);
00770     fPISymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PI);
00771     fNodeSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_NODE);
00772     fAncestorSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ANCESTOR);
00773     fAncestorOrSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ANCESTOR_OR_SELF);
00774     fAttributeSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ATTRIBUTE);
00775     fChildSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_CHILD);
00776     fDescendantSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DESCENDANT);
00777     fDescendantOrSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DESCENDANT_OR_SELF);
00778     fFollowingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_FOLLOWING);
00779     fFollowingSiblingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_FOLLOWING_SIBLING);
00780     fNamespaceSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_NAMESPACE);
00781     fParentSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PARENT);
00782     fPrecedingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PRECEDING);
00783     fPrecedingSiblingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PRECEDING_SIBLING);
00784     fSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_SELF);
00785 }
00786 
00787 
00788 // ---------------------------------------------------------------------------
00789 //  XPathScanner: Scan methods
00790 // ---------------------------------------------------------------------------
00791 bool XPathScanner::scanExpression(const XMLCh* const data,
00792                                   XMLSize_t currentOffset,
00793                                   const XMLSize_t endOffset,
00794                                   ValueVectorOf<int>* const tokens) {
00795 
00796     bool      starIsMultiplyOperator = false;
00797     XMLSize_t nameOffset = 0;
00798     int       nameHandle = -1;
00799     int       prefixHandle = -1;
00800     XMLCh     ch;
00801     XMLBuffer dataBuffer(128, tokens->getMemoryManager());
00802 
00803     while (currentOffset != endOffset) {
00804 
00805         ch = data[currentOffset];
00806 
00807         while (XMLChar1_0::isWhitespace(ch)) {
00808 
00809             if (++currentOffset == endOffset) {
00810                 break;
00811             }
00812 
00813             ch = data[currentOffset];
00814         }
00815 
00816         if (currentOffset == endOffset) {
00817             break;
00818         }
00819         //
00820         // [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
00821         //                  | NameTest | NodeType | Operator | FunctionName
00822         //                  | AxisName | Literal | Number | VariableReference
00823         //
00824         XMLByte chartype = (ch >= 0x80) ? (XMLByte)CHARTYPE_NONASCII : fASCIICharMap[ch];
00825 
00826         switch (chartype) {
00827         case CHARTYPE_OPEN_PAREN:       // '('
00828             addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_PAREN);
00829             starIsMultiplyOperator = false;
00830             ++currentOffset;
00831             break;
00832         case CHARTYPE_CLOSE_PAREN:      // ')'
00833             addToken(tokens, XercesXPath::EXPRTOKEN_CLOSE_PAREN);
00834             starIsMultiplyOperator = true;
00835             ++currentOffset;
00836             break;
00837         case CHARTYPE_OPEN_BRACKET:     // '['
00838             addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_BRACKET);
00839             starIsMultiplyOperator = false;
00840             ++currentOffset;
00841             break;
00842         case CHARTYPE_CLOSE_BRACKET:    // ']'
00843             addToken(tokens, XercesXPath::EXPRTOKEN_CLOSE_BRACKET);
00844             starIsMultiplyOperator = true;
00845             ++currentOffset;
00846             break;
00847                 //
00848                 // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
00849                 //                                         ^^^^^^^^^^
00850                 //
00851         case CHARTYPE_PERIOD:           // '.', '..' or '.' Digits
00852             if (currentOffset + 1 == endOffset) {
00853                 addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
00854                 starIsMultiplyOperator = true;
00855                 currentOffset++;
00856                 break;
00857             }
00858 
00859             ch = data[currentOffset + 1];
00860 
00861             if (ch == chPeriod) {            // '..'
00862                 addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_PERIOD);
00863                 starIsMultiplyOperator = true;
00864                 currentOffset += 2;
00865             } else if (ch >= chDigit_0 && ch <= chDigit_9) {
00866                 addToken(tokens, XercesXPath::EXPRTOKEN_NUMBER);
00867                 starIsMultiplyOperator = true;
00868                 currentOffset = scanNumber(data, endOffset, currentOffset, tokens);
00869             } else if (ch == chForwardSlash) {
00870                 addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
00871                 starIsMultiplyOperator = true;
00872                 currentOffset++;
00873             } else if (ch == chPipe) { // '|'
00874                 addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
00875                 starIsMultiplyOperator = true;
00876                 currentOffset++;
00877             } else if (XMLChar1_0::isWhitespace(ch)) {
00878                 do {
00879                     if (++currentOffset == endOffset)
00880                         break;
00881 
00882                     ch = data[currentOffset];
00883                 } while (XMLChar1_0::isWhitespace(ch));
00884 
00885                 if (currentOffset == endOffset || ch == chPipe || ch == chForwardSlash) {
00886                                     addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
00887                     starIsMultiplyOperator = true;
00888                     break;
00889                 }
00890             } else {
00891                 XMLCh str[2]= {ch, 0 };
00892                 ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_InvalidChar, str, tokens->getMemoryManager());
00893             }
00894 
00895             break;
00896         case CHARTYPE_ATSIGN:           // '@'
00897             addToken(tokens, XercesXPath::EXPRTOKEN_ATSIGN);
00898             starIsMultiplyOperator = false;
00899             ++currentOffset;
00900             break;
00901         case CHARTYPE_COMMA:            // ','
00902             addToken(tokens, XercesXPath::EXPRTOKEN_COMMA);
00903             starIsMultiplyOperator = false;
00904             ++currentOffset;
00905             break;
00906         case CHARTYPE_COLON:            // '::'
00907             if (++currentOffset == endOffset) {
00908                 return false; // REVISIT
00909             }
00910             ch = data[currentOffset];
00911 
00912             if (ch != chColon) {
00913                 return false; // REVISIT
00914             }
00915             addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_COLON);
00916             starIsMultiplyOperator = false;
00917             ++currentOffset;
00918             break;
00919         case CHARTYPE_SLASH:            // '/' and '//'
00920             if (++currentOffset == endOffset) {
00921                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_SLASH);
00922                 starIsMultiplyOperator = false;
00923                 break;
00924             }
00925 
00926             ch = data[currentOffset];
00927 
00928             if (ch == chForwardSlash) { // '//'
00929                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH);
00930                 starIsMultiplyOperator = false;
00931                 ++currentOffset;
00932             } else {
00933                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_SLASH);
00934                 starIsMultiplyOperator = false;
00935             }
00936             break;
00937         case CHARTYPE_UNION:            // '|'
00938             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_UNION);
00939             starIsMultiplyOperator = false;
00940             ++currentOffset;
00941             break;
00942         case CHARTYPE_PLUS:             // '+'
00943             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_PLUS);
00944             starIsMultiplyOperator = false;
00945             ++currentOffset;
00946             break;
00947         case CHARTYPE_MINUS:            // '-'
00948             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MINUS);
00949             starIsMultiplyOperator = false;
00950             ++currentOffset;
00951             break;
00952         case CHARTYPE_EQUAL:            // '='
00953             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_EQUAL);
00954             starIsMultiplyOperator = false;
00955             ++currentOffset;
00956             break;
00957         case CHARTYPE_EXCLAMATION:      // '!='
00958             if (++currentOffset == endOffset) {
00959                 return false; // REVISIT
00960             }
00961 
00962             ch = data[currentOffset];
00963 
00964             if (ch != chEqual) {
00965                 return false; // REVISIT
00966             }
00967 
00968             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_NOT_EQUAL);
00969             starIsMultiplyOperator = false;
00970             ++currentOffset;
00971             break;
00972         case CHARTYPE_LESS: // '<' and '<='
00973             if (++currentOffset == endOffset) {
00974                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS);
00975                 starIsMultiplyOperator = false;
00976                 break;
00977             }
00978 
00979             ch = data[currentOffset];
00980 
00981             if (ch == chEqual) { // '<='
00982                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS_EQUAL);
00983                 starIsMultiplyOperator = false;
00984                 ++currentOffset;
00985             } else {
00986                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS);
00987                 starIsMultiplyOperator = false;
00988             }
00989             break;
00990         case CHARTYPE_GREATER: // '>' and '>='
00991             if (++currentOffset == endOffset) {
00992                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER);
00993                 starIsMultiplyOperator = false;
00994                 break;
00995             }
00996 
00997             ch = data[currentOffset];
00998 
00999             if (ch == chEqual) { // '>='
01000                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER_EQUAL);
01001                 starIsMultiplyOperator = false;
01002                 ++currentOffset;
01003             } else {
01004                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER);
01005                 starIsMultiplyOperator = false;
01006             }
01007             break;
01008         //
01009         // [29] Literal ::= '"' [^"]* '"' | "'" [^']* "'"
01010         //
01011         case CHARTYPE_QUOTE:            // '\"' or '\''
01012             {
01013                 XMLCh qchar = ch;
01014                 if (++currentOffset == endOffset) {
01015                     return false; // REVISIT
01016                 }
01017 
01018                 ch = data[currentOffset];
01019 
01020                 XMLSize_t litOffset = currentOffset;
01021                 while (ch != qchar) {
01022                     if (++currentOffset == endOffset) {
01023                         return false; // REVISIT
01024                     }
01025 
01026                     ch = data[currentOffset];
01027                 }
01028 
01029                 addToken(tokens, XercesXPath::EXPRTOKEN_LITERAL);
01030                 starIsMultiplyOperator = true;
01031 
01032                 dataBuffer.set(data + litOffset, currentOffset - litOffset);
01033                 tokens->addElement(fStringPool->addOrFind(dataBuffer.getRawBuffer()));
01034                 ++currentOffset;
01035                 break;
01036             }
01037         //
01038         // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
01039         // [31] Digits ::= [0-9]+
01040         //
01041         case CHARTYPE_DIGIT:
01042             addToken(tokens, XercesXPath::EXPRTOKEN_NUMBER);
01043             starIsMultiplyOperator = true;
01044             currentOffset = scanNumber(data, endOffset, currentOffset, tokens);
01045             break;
01046         //
01047         // [36] VariableReference ::= '$' QName
01048         //
01049         case CHARTYPE_DOLLAR:
01050             if (++currentOffset == endOffset) {
01051                 return false; // REVISIT
01052             }
01053             nameOffset = currentOffset;
01054             currentOffset = scanNCName(data, endOffset, currentOffset);
01055 
01056             if (currentOffset == nameOffset) {
01057                 return false; // REVISIT
01058             }
01059 
01060             if (currentOffset < endOffset) {
01061                 ch = data[currentOffset];
01062             }
01063             else {
01064                 ch = 0;
01065             }
01066 
01067             dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
01068             nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
01069             prefixHandle = -1;
01070 
01071             if (ch == chColon) {
01072 
01073                 prefixHandle = nameHandle;
01074                 if (++currentOffset == endOffset) {
01075                     return false; // REVISIT
01076                 }
01077                 nameOffset = currentOffset;
01078                 currentOffset = scanNCName(data, endOffset, currentOffset);
01079 
01080                 if (currentOffset == nameOffset) {
01081                     return false; // REVISIT
01082                 }
01083 
01084                 dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
01085                 nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
01086             }
01087             addToken(tokens, XercesXPath::EXPRTOKEN_VARIABLE_REFERENCE);
01088             starIsMultiplyOperator = true;
01089             tokens->addElement(prefixHandle);
01090             tokens->addElement(nameHandle);
01091             break;
01092         //
01093         // [37] NameTest ::= '*' | NCName ':' '*' | QName
01094         // [34] MultiplyOperator ::= '*'
01095         //
01096         case CHARTYPE_STAR:             // '*'
01097             //
01098             // 3.7 Lexical Structure
01099             //
01100             //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
01101             //  an Operator, then a * must be recognized as a MultiplyOperator.
01102             //
01103             // Otherwise, the token must not be recognized as a MultiplyOperator.
01104             //
01105             if (starIsMultiplyOperator) {
01106                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MULT);
01107                 starIsMultiplyOperator = false;
01108             } else {
01109                 addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_ANY);
01110                 starIsMultiplyOperator = true;
01111             }
01112 
01113             ++currentOffset;
01114             break;
01115         //
01116         // NCName, QName and non-terminals
01117         //
01118         case CHARTYPE_NONASCII: // possibly a valid non-ascii 'Letter' (BaseChar | Ideographic)
01119         case CHARTYPE_LETTER:
01120         case CHARTYPE_UNDERSCORE:
01121             {
01122             //
01123             // 3.7 Lexical Structure
01124             //
01125             //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
01126             //  an Operator, then an NCName must be recognized as an OperatorName.
01127             //
01128             //  If the character following an NCName (possibly after intervening ExprWhitespace) is (,
01129             //  then the token must be recognized as a NodeType or a FunctionName.
01130             //
01131             //  If the two characters following an NCName (possibly after intervening ExprWhitespace)
01132             //  are ::, then the token must be recognized as an AxisName.
01133             //
01134             //  Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
01135             //  FunctionName, or an AxisName.
01136             //
01137             // [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
01138             // [38] NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node'
01139             // [35] FunctionName ::= QName - NodeType
01140             // [6] AxisName ::= (see above)
01141             //
01142             // [37] NameTest ::= '*' | NCName ':' '*' | QName
01143             // [5] NCName ::= (Letter | '_') (NCNameChar)*
01144             // [?] NCNameChar ::= Letter | Digit | '.' | '-' | '_'  (ascii subset of 'NCNameChar')
01145             // [?] QName ::= (NCName ':')? NCName
01146             // [?] Letter ::= [A-Za-z]                              (ascii subset of 'Letter')
01147             // [?] Digit ::= [0-9]                                  (ascii subset of 'Digit')
01148             //
01149             nameOffset = currentOffset;
01150             currentOffset = scanNCName(data, endOffset, currentOffset);
01151             if (currentOffset == nameOffset) {
01152                 return false; // REVISIT
01153                         }
01154 
01155             if (currentOffset < endOffset) {
01156                 ch = data[currentOffset];
01157             }
01158             else {
01159                 ch = 0;
01160             }
01161 
01162             dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
01163             nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
01164 
01165             bool isNameTestNCName = false;
01166             bool isAxisName = false;
01167             prefixHandle = -1;
01168 
01169             if (ch == chColon) {
01170 
01171                 if (++currentOffset == endOffset) {
01172                     return false; // REVISIT
01173                 }
01174 
01175                 ch = data[currentOffset];
01176 
01177                 if (ch == chAsterisk) {
01178                     if (++currentOffset < endOffset) {
01179                         ch = data[currentOffset];
01180                     }
01181 
01182                     isNameTestNCName = true;
01183                 } else if (ch == chColon) {
01184                     if (++currentOffset < endOffset) {
01185                         ch = data[currentOffset];
01186                     }
01187 
01188                     isAxisName = true;
01189                 } else {
01190                     prefixHandle = nameHandle;
01191                     nameOffset = currentOffset;
01192                     currentOffset = scanNCName(data, endOffset, currentOffset);
01193                     if (currentOffset == nameOffset) {
01194                         return false; // REVISIT
01195                     }
01196                     if (currentOffset < endOffset) {
01197                         ch = data[currentOffset];
01198                     }
01199                     else {
01200                         ch = 0;
01201                     }
01202 
01203                     dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
01204                     nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
01205                 }
01206             }
01207             //
01208             // [39] ExprWhitespace ::= S
01209             //
01210             while (XMLChar1_0::isWhitespace(ch)) {
01211                 if (++currentOffset == endOffset) {
01212                     break;
01213                 }
01214                 ch = data[currentOffset];
01215             }
01216 
01217             //
01218             //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
01219             //  an Operator, then an NCName must be recognized as an OperatorName.
01220             //
01221             if (starIsMultiplyOperator) {
01222                 if (nameHandle == fAndSymbol) {
01223                     addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_AND);
01224                     starIsMultiplyOperator = false;
01225                 } else if (nameHandle == fOrSymbol) {
01226                     addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_OR);
01227                     starIsMultiplyOperator = false;
01228                 } else if (nameHandle == fModSymbol) {
01229                     addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MOD);
01230                     starIsMultiplyOperator = false;
01231                 } else if (nameHandle == fDivSymbol) {
01232                     addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_DIV);
01233                     starIsMultiplyOperator = false;
01234                 } else {
01235                     return false; // REVISIT
01236                 }
01237 
01238                 if (isNameTestNCName) {
01239                     return false; // REVISIT - NCName:* where an OperatorName is required
01240                 } else if (isAxisName) {
01241                     return false; // REVISIT - AxisName:: where an OperatorName is required
01242                 }
01243                 break;
01244             }
01245             //
01246             //  If the character following an NCName (possibly after intervening ExprWhitespace) is (,
01247             //  then the token must be recognized as a NodeType or a FunctionName.
01248             //
01249             if (ch == chOpenParen && !isNameTestNCName && !isAxisName) {
01250                 if (nameHandle == fCommentSymbol) {
01251                     addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_COMMENT);
01252                 } else if (nameHandle == fTextSymbol) {
01253                     addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_TEXT);
01254                 } else if (nameHandle == fPISymbol) {
01255                     addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_PI);
01256                 } else if (nameHandle == fNodeSymbol) {
01257                     addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_NODE);
01258                 } else {
01259                     addToken(tokens, XercesXPath::EXPRTOKEN_FUNCTION_NAME);
01260                     tokens->addElement(prefixHandle);
01261                     tokens->addElement(nameHandle);
01262                 }
01263                 addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_PAREN);
01264                 starIsMultiplyOperator = false;
01265                 ++currentOffset;
01266                 break;
01267             }
01268 
01269             //
01270             //  If the two characters following an NCName (possibly after intervening ExprWhitespace)
01271             //  are ::, then the token must be recognized as an AxisName.
01272             //
01273             if (isAxisName ||
01274                 (ch == chColon && currentOffset + 1 < endOffset &&
01275                  data[currentOffset + 1] == chColon)) {
01276 
01277                 if (nameHandle == fAncestorSymbol) {
01278                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ANCESTOR);
01279                 } else if (nameHandle == fAncestorOrSelfSymbol) {
01280                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF);
01281                 } else if (nameHandle == fAttributeSymbol) {
01282                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE);
01283                 } else if (nameHandle == fChildSymbol) {
01284                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_CHILD);
01285                 } else if (nameHandle == fDescendantSymbol) {
01286                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_DESCENDANT);
01287                 } else if (nameHandle == fDescendantOrSelfSymbol) {
01288                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF);
01289                 } else if (nameHandle == fFollowingSymbol) {
01290                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_FOLLOWING);
01291                 } else if (nameHandle == fFollowingSiblingSymbol) {
01292                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING);
01293                 } else if (nameHandle == fNamespaceSymbol) {
01294                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_NAMESPACE);
01295                 } else if (nameHandle == fParentSymbol) {
01296                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PARENT);
01297                 } else if (nameHandle == fPrecedingSymbol) {
01298                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PRECEDING);
01299                 } else if (nameHandle == fPrecedingSiblingSymbol) {
01300                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PRECEDING_SIBLING);
01301                 } else if (nameHandle == fSelfSymbol) {
01302                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_SELF);
01303                 } else {
01304                     return false; // REVISIT
01305                 }
01306 
01307                 if (isNameTestNCName) {
01308                     return false; // REVISIT - "NCName:* ::" where "AxisName ::" is required
01309                 }
01310 
01311                 addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_COLON);
01312                 starIsMultiplyOperator = false;
01313                 if (!isAxisName) {
01314                     currentOffset += 2;
01315                 }
01316                 break;
01317             }
01318             //
01319             //  Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
01320             //  FunctionName, or an AxisName.
01321             //
01322             if (isNameTestNCName) {
01323                 addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE);
01324                 tokens->addElement(nameHandle);
01325             } else {
01326                 addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_QNAME);
01327                 tokens->addElement(prefixHandle);
01328                 tokens->addElement(nameHandle);
01329             }
01330 
01331             starIsMultiplyOperator = true;
01332             break;
01333             }
01334         default:
01335             {
01336             XMLCh str[2]= {ch, 0 };
01337             ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_InvalidChar, str, tokens->getMemoryManager());
01338             break;
01339             }
01340         }
01341     }
01342 
01343     return true;
01344 }
01345 
01346 
01347 XMLSize_t XPathScanner::scanNCName(const XMLCh* const data,
01348                              const XMLSize_t endOffset,
01349                              XMLSize_t currentOffset) {
01350 
01351     XMLCh ch = data[currentOffset];
01352 
01353     if (!XMLChar1_0::isFirstNCNameChar(ch)) {
01354         return currentOffset;
01355     }
01356 
01357     while (++currentOffset < endOffset) {
01358 
01359         ch = data[currentOffset];
01360 
01361         if (!XMLChar1_0::isNCNameChar(ch)) {
01362             break;
01363         }
01364     }
01365 
01366     return currentOffset;
01367 }
01368 
01369 
01370 XMLSize_t XPathScanner::scanNumber(const XMLCh* const data,
01371                              const XMLSize_t endOffset,
01372                              XMLSize_t currentOffset,
01373                              ValueVectorOf<int>* const tokens) {
01374 
01375     XMLCh ch = data[currentOffset];
01376     int   whole = 0;
01377     int   part = 0;
01378 
01379     while (ch >= chDigit_0 && ch <= chDigit_9) {
01380 
01381         whole = (whole * 10) + (ch - chDigit_0);
01382 
01383         if (++currentOffset == endOffset) {
01384             break;
01385         }
01386 
01387         ch = data[currentOffset];
01388     }
01389 
01390     if (ch == chPeriod) {
01391 
01392         if (++currentOffset < endOffset) {
01393 
01394             ch = data[currentOffset];
01395 
01396             while (ch >= chDigit_0 && ch <= chDigit_9) {
01397 
01398                 part = (part * 10) + (ch - chDigit_0);
01399 
01400                 if (++currentOffset == endOffset) {
01401                     break;
01402                 }
01403 
01404                 ch = data[currentOffset];
01405             }
01406 
01407             if (part != 0) {
01408                 ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::XPath_FindSolution, tokens->getMemoryManager());
01409             }
01410         }
01411     }
01412 
01413     tokens->addElement(whole);
01414     tokens->addElement(part);
01415 
01416     return currentOffset;
01417 }
01418 
01419 
01420 // ---------------------------------------------------------------------------
01421 //  XPathScannerForSchema: Constructors and Destructor
01422 // ---------------------------------------------------------------------------
01423 XPathScannerForSchema::XPathScannerForSchema(XMLStringPool* const stringPool)
01424     : XPathScanner(stringPool)
01425 {
01426 }
01427 
01428 
01429 // ---------------------------------------------------------------------------
01430 //  XPathScannerForSchema: Helper methods
01431 // ---------------------------------------------------------------------------
01432 void XPathScannerForSchema::addToken(ValueVectorOf<int>* const tokens,
01433                                      const int aToken) {
01434 
01435     if (aToken == XercesXPath::EXPRTOKEN_ATSIGN ||
01436         aToken == XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE ||
01437         aToken == XercesXPath::EXPRTOKEN_AXISNAME_CHILD ||
01438         //token == XercesXPath::EXPRTOKEN_AXISNAME_SELF ||
01439         aToken == XercesXPath::EXPRTOKEN_DOUBLE_COLON ||
01440         aToken == XercesXPath::EXPRTOKEN_NAMETEST_QNAME ||
01441         //token == XercesXPath::EXPRTOKEN_NODETYPE_NODE ||
01442         aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH ||
01443         aToken == XercesXPath::EXPRTOKEN_PERIOD ||
01444         aToken == XercesXPath::EXPRTOKEN_NAMETEST_ANY ||
01445         aToken == XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE ||
01446         aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH ||
01447         aToken == XercesXPath::EXPRTOKEN_OPERATOR_UNION) {
01448 
01449         tokens->addElement(aToken);
01450         return;
01451     }
01452 
01453     ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_TokenNotSupported, tokens->getMemoryManager());
01454 }
01455 
01456 XERCES_CPP_NAMESPACE_END
01457