XercesXPath.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:51k
源码类别:

词法分析

开发平台:

Visual 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) 1999, 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: XercesXPath.cpp,v $
  58.  * Revision 1.8  2003/05/18 14:02:09  knoaman
  59.  * Memory manager implementation: pass per instance manager.
  60.  *
  61.  * Revision 1.7  2003/05/16 21:43:22  knoaman
  62.  * Memory manager implementation: Modify constructors to pass in the memory manager.
  63.  *
  64.  * Revision 1.6  2003/05/15 18:59:34  knoaman
  65.  * Partial implementation of the configurable memory manager.
  66.  *
  67.  * Revision 1.5  2002/12/20 22:10:48  tng
  68.  * XML 1.1
  69.  *
  70.  * Revision 1.4  2002/12/04 18:21:23  knoaman
  71.  * Identity constraint fix.
  72.  *
  73.  * Revision 1.3  2002/11/04 14:47:42  tng
  74.  * C++ Namespace Support.
  75.  *
  76.  * Revision 1.2  2002/10/30 21:52:01  tng
  77.  * [Bug 13641] compiler-generated copy-constructor for QName doesn't do the right thing.
  78.  *
  79.  * Revision 1.1.1.1  2002/02/01 22:22:51  peiyongz
  80.  * sane_include
  81.  *
  82.  * Revision 1.3  2001/11/15 17:10:19  knoaman
  83.  * Particle derivation checking support.
  84.  *
  85.  * Revision 1.2  2001/11/07 14:25:36  knoaman
  86.  * Fix compliation error on Unix.
  87.  *
  88.  * Revision 1.1  2001/11/02 14:08:40  knoaman
  89.  * Add support for identity constraints.
  90.  *
  91.  */
  92. // ---------------------------------------------------------------------------
  93. //  Includes
  94. // ---------------------------------------------------------------------------
  95. #include <xercesc/validators/schema/identity/XercesXPath.hpp>
  96. #include <xercesc/validators/schema/identity/XPathSymbols.hpp>
  97. #include <xercesc/validators/schema/identity/XPathException.hpp>
  98. #include <xercesc/validators/schema/NamespaceScope.hpp>
  99. #include <xercesc/util/StringPool.hpp>
  100. #include <xercesc/util/Janitor.hpp>
  101. #include <xercesc/framework/XMLBuffer.hpp>
  102. #include <xercesc/internal/XMLReader.hpp>
  103. #include <xercesc/util/RuntimeException.hpp>
  104. XERCES_CPP_NAMESPACE_BEGIN
  105. // ---------------------------------------------------------------------------
  106. //  Static data
  107. // ---------------------------------------------------------------------------
  108. const XMLByte XPathScanner::fASCIICharMap[128] =
  109. {
  110.     0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  2,  0,  0,
  111.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  112.     2,  3,  4,  1,  5,  1,  1,  4,  6,  7,  8,  9, 10, 11, 12, 13,
  113.     14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,  1, 16, 17, 18,  1,
  114.     19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
  115.     20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,  1, 22,  1, 23,
  116.     1, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
  117.     20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  1, 24,  1,  1,  1
  118. };
  119. // ---------------------------------------------------------------------------
  120. //  XercesNodeTest: Constructors and Destructor
  121. // ---------------------------------------------------------------------------
  122. XercesNodeTest::XercesNodeTest(const short aType,
  123.                                MemoryManager* const manager)
  124.     : fType(aType)
  125.     , fName(new (manager) QName(manager))
  126. {
  127. }
  128. XercesNodeTest::XercesNodeTest(const QName* const qName)
  129.     : fType(QNAME)
  130.     , fName(new (qName->getMemoryManager()) QName(*qName))
  131. {
  132. }
  133. XercesNodeTest::XercesNodeTest(const XMLCh* const prefix,
  134.                                const unsigned int uriId,
  135.                                MemoryManager* const manager)
  136.     : fType(NAMESPACE)
  137.     , fName(new (manager) QName(manager))
  138. {
  139.     fName->setURI(uriId);
  140.     fName->setPrefix(prefix);
  141. }
  142. XercesNodeTest::XercesNodeTest(const XercesNodeTest& other)
  143.     : fType(other.fType)
  144.     , fName(new ((other.fName)->getMemoryManager())QName(*other.fName))
  145. {
  146. }
  147. // ---------------------------------------------------------------------------
  148. //  XercesNodeTest: Operators
  149. // ---------------------------------------------------------------------------
  150. XercesNodeTest& XercesNodeTest::operator=(const XercesNodeTest& other)
  151. {
  152.     if (this == &other)
  153.         return *this;
  154.     fType = other.fType;
  155.     fName->setValues(*(other.fName));
  156.     return *this;
  157. }
  158. bool XercesNodeTest::operator ==(const XercesNodeTest& other) const {
  159.     if (this == &other)
  160.         return true;
  161.     if (fType != other.fType)
  162.         return false;
  163.     return (*fName == *(other.fName));
  164. }
  165. bool XercesNodeTest::operator !=(const XercesNodeTest& other) const {
  166.     return !operator==(other);
  167. }
  168. // ---------------------------------------------------------------------------
  169. //  XercesStep: Constructors and Destructor
  170. // ---------------------------------------------------------------------------
  171. XercesStep::XercesStep(const unsigned short axisType, XercesNodeTest* const nodeTest)
  172.     : fAxisType(axisType)
  173.     , fNodeTest(nodeTest)
  174. {
  175. }
  176. XercesStep::XercesStep(const XercesStep& other)
  177.     : fAxisType(other.fAxisType)
  178.     , fNodeTest(0)
  179. {
  180.     fNodeTest = new (other.fNodeTest->getName()->getMemoryManager()) XercesNodeTest(*(other.fNodeTest));
  181. }
  182. // ---------------------------------------------------------------------------
  183. //  XercesStep: Operators
  184. // ---------------------------------------------------------------------------
  185. XercesStep& XercesStep::operator=(const XercesStep& other)
  186. {
  187.     if (this == &other)
  188.         return *this;
  189.     fAxisType = other.fAxisType;
  190.     *fNodeTest = *(other.fNodeTest);
  191.     return *this;
  192. }
  193. bool XercesStep::operator==(const XercesStep& other) const {
  194.     if (this == &other)
  195.         return true;
  196.     if (fAxisType != other.fAxisType)
  197.         return false;
  198.     if (fAxisType == XercesStep::CHILD ||
  199.         fAxisType == XercesStep::ATTRIBUTE) {
  200.         return (*fNodeTest == *(other.fNodeTest));
  201.     }
  202.     return true;
  203. }
  204. bool XercesStep::operator!=(const XercesStep& other) const {
  205.     return !operator==(other);
  206. }
  207. // ---------------------------------------------------------------------------
  208. //  XercesLocationPath: Constructors and Destructor
  209. // ---------------------------------------------------------------------------
  210. XercesLocationPath::XercesLocationPath(RefVectorOf<XercesStep>* const steps)
  211.     : fSteps(steps)
  212. {
  213. }
  214. // ---------------------------------------------------------------------------
  215. //  XercesLocationPath: Operators
  216. // ---------------------------------------------------------------------------
  217. bool XercesLocationPath::operator==(const XercesLocationPath& other) const {
  218.     unsigned int stepsSize = fSteps->size();
  219.     if (stepsSize != other.fSteps->size())
  220.         return false;
  221.     for (unsigned int i=0; i < stepsSize; i++) {
  222.         if (*(fSteps->elementAt(i)) != *(other.fSteps->elementAt(i)))
  223.             return false;
  224.     }
  225.     return true;
  226. }
  227. bool XercesLocationPath::operator!=(const XercesLocationPath& other) const {
  228.     return !operator==(other);
  229. }
  230. // ---------------------------------------------------------------------------
  231. //  XercesPath: Constructors and Destructor
  232. // ---------------------------------------------------------------------------
  233. XercesXPath::XercesXPath(const XMLCh* const xpathExpr,
  234.                          XMLStringPool* const stringPool,
  235.                          NamespaceScope* const scopeContext,
  236.                          const unsigned int emptyNamespaceId,
  237.                          const bool isSelector,
  238.                          MemoryManager* const manager)
  239.     : fEmptyNamespaceId(emptyNamespaceId)
  240.     , fExpression(0)
  241.     , fLocationPaths(0)
  242.     , fMemoryManager(manager)
  243. {
  244.     try
  245.     {
  246.         fExpression = XMLString::replicate(xpathExpr, fMemoryManager);
  247.         parseExpression(stringPool, scopeContext);
  248.         if (isSelector) {
  249.             checkForSelectedAttributes();
  250.         }
  251.     }
  252.     catch(...) {
  253.         cleanUp();
  254.         throw;
  255.     }
  256. }
  257. XercesXPath::~XercesXPath() {
  258.     cleanUp();
  259. }
  260. // ---------------------------------------------------------------------------
  261. //  XercesXPath: Operators
  262. // ---------------------------------------------------------------------------
  263. bool XercesXPath::operator==(const XercesXPath& other) const {
  264.     unsigned int locPathSize = fLocationPaths->size();
  265.     if (locPathSize != other.fLocationPaths->size())
  266.         return false;
  267.     for (unsigned int i=0; i < locPathSize; i++) {
  268.         if (*(fLocationPaths->elementAt(i)) != *(other.fLocationPaths->elementAt(i)))
  269.             return false;
  270.     }
  271.     return true;
  272. }
  273. bool XercesXPath::operator!=(const XercesXPath& other) const {
  274.     return !operator==(other);
  275. }
  276. // ---------------------------------------------------------------------------
  277. //  XercesPath: Helper methods
  278. // ---------------------------------------------------------------------------
  279. void XercesXPath::cleanUp() {
  280.     fMemoryManager->deallocate(fExpression);//delete [] fExpression;
  281.     delete fLocationPaths;
  282. }
  283. void XercesXPath::checkForSelectedAttributes() {
  284.     // verify that an attribute is not selected
  285.     unsigned int locSize = (fLocationPaths) ? fLocationPaths->size() : 0;
  286.     for (unsigned int i = 0; i < locSize; i++) {
  287.         XercesLocationPath* locPath = fLocationPaths->elementAt(i);
  288.         unsigned int stepSize = locPath->getStepSize();
  289.         if (stepSize) {
  290.             if (locPath->getStep(stepSize - 1)->getAxisType() == XercesStep::ATTRIBUTE) {
  291.                 ThrowXML(XPathException, XMLExcepts::XPath_NoAttrSelector);
  292.             }
  293. }
  294.     }
  295. }
  296. void XercesXPath::parseExpression(XMLStringPool* const stringPool,
  297.                                   NamespaceScope* const scopeContext) {
  298.     unsigned int length = XMLString::stringLen(fExpression);
  299.     if (!length) {
  300.         return;
  301.     }
  302.     ValueVectorOf<int>                tokens(16, fMemoryManager);
  303.     XPathScannerForSchema             scanner(stringPool);
  304.     bool                              success = scanner.scanExpression(fExpression, 0, length, &tokens);
  305.     bool                              firstTokenOfLocationPath=true;
  306.     unsigned int                      tokenCount = tokens.size();
  307.     RefVectorOf<XercesStep>*          stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
  308.     Janitor<RefVectorOf<XercesStep> > janSteps(stepsVector);
  309.     if (tokenCount) {
  310.         fLocationPaths = new (fMemoryManager) RefVectorOf<XercesLocationPath>(8, true, fMemoryManager);
  311.     }
  312.     for (unsigned int i = 0; i < tokenCount; i++) {
  313.         int  aToken = tokens.elementAt(i);
  314.         bool isNamespace=false;
  315.         switch (aToken) {
  316.         case  XercesXPath::EXPRTOKEN_OPERATOR_UNION:
  317.             {
  318.                 if (i == 0) {
  319.                     ThrowXML(XPathException, XMLExcepts::XPath_NoUnionAtStart);
  320.                 }
  321.                 int stepsSize = stepsVector->size();
  322.                 if (stepsSize == 0) {
  323.                     ThrowXML(XPathException, XMLExcepts::XPath_NoMultipleUnion);
  324.                 }
  325.                 fLocationPaths->addElement(new (fMemoryManager) XercesLocationPath(stepsVector));
  326.                 janSteps.orphan();
  327.                 stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
  328.                 janSteps.reset(stepsVector);
  329.                 firstTokenOfLocationPath = true;
  330.             }
  331.             break;
  332.         case XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE:
  333.             {
  334.                 // consume "::" token and drop through
  335.                 i++;
  336.             }
  337.         case XercesXPath::EXPRTOKEN_ATSIGN:
  338.             {
  339.                 // consume QName token
  340.                 if (i == tokenCount - 1) {
  341.                     ThrowXML(XPathException, XMLExcepts::XPath_MissingAttr);
  342.                 }
  343.                 aToken = tokens.elementAt(++i);
  344.                 if (aToken != XercesXPath::EXPRTOKEN_NAMETEST_QNAME
  345.                     && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_ANY
  346.                     && aToken!= XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE) {
  347.                         ThrowXML(XPathException, XMLExcepts::XPath_ExpectedToken1);
  348.                 }
  349.                 bool isNamespaceAtt=false;
  350.                 switch (aToken) {
  351.                 case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
  352.                     {
  353.                         XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::WILDCARD, fMemoryManager);
  354.                         XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::ATTRIBUTE, nodeTest);
  355.                         stepsVector->addElement(step);
  356.                         break;
  357.                     }
  358.                 case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
  359.                     {
  360.                         isNamespaceAtt = true;
  361.                     }
  362.                 case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
  363.                     {
  364.                         aToken = tokens.elementAt(++i);
  365.                         const XMLCh* prefix = XMLUni::fgZeroLenString;
  366.                         unsigned int uri = fEmptyNamespaceId;
  367.                         if (scopeContext && aToken != -1) {
  368.                             prefix = stringPool->getValueForId(aToken);
  369.                             uri = scopeContext->getNamespaceForPrefix(prefix);
  370.                         }
  371.                         if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
  372.                             ThrowXML1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix);
  373.                         }
  374.                         if (isNamespaceAtt) {
  375.                             // build step
  376.                             XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager);
  377.                             XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::ATTRIBUTE, nodeTest);
  378.                             stepsVector->addElement(step);
  379.                             break;
  380.                         }
  381.                         aToken = tokens.elementAt(++i);
  382.                         const XMLCh* localPart = stringPool->getValueForId(aToken);
  383.                         QName aQName(prefix, localPart, uri, fMemoryManager);
  384.                         // build step
  385.                         XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
  386.                         XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::ATTRIBUTE, nodeTest);
  387.                         stepsVector->addElement(step);
  388.                         break;
  389.                     }
  390. }
  391.                 firstTokenOfLocationPath=false;
  392.                 break;
  393.             }
  394.         case XercesXPath::EXPRTOKEN_DOUBLE_COLON:
  395.             {
  396.                 // should never have a bare double colon
  397.                 ThrowXML(XPathException, XMLExcepts::XPath_NoDoubleColon);
  398.             }
  399.         case XercesXPath::EXPRTOKEN_AXISNAME_CHILD:
  400.             {
  401.                 // consume "::" token and drop through
  402.                 i++;
  403.                 if (i == tokenCount - 1) {
  404.                     ThrowXML(XPathException, XMLExcepts::XPath_ExpectedStep1);
  405.                 }
  406.                 firstTokenOfLocationPath=false;
  407.                 break;
  408.             }
  409.         case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
  410.             {
  411.                 XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::WILDCARD, fMemoryManager);
  412.                 XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::CHILD, nodeTest);
  413.                 stepsVector->addElement(step);
  414.                 firstTokenOfLocationPath = false;
  415.                 break;
  416.             }
  417.         case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
  418.             {
  419.                 isNamespace=true;
  420.             }
  421.         case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
  422.             {
  423.                 // consume QName token
  424.                 aToken = tokens.elementAt(++i);
  425.                 const XMLCh* prefix = XMLUni::fgZeroLenString;
  426.                 unsigned int uri = fEmptyNamespaceId;
  427.                 if (scopeContext && aToken != -1) {
  428.                     prefix = stringPool->getValueForId(aToken);
  429.                     uri = scopeContext->getNamespaceForPrefix(prefix);
  430.                 }
  431.                 if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
  432.                     ThrowXML1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix);
  433.                 }
  434.                 if (isNamespace) {
  435.                     // build step
  436.                     XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager);
  437.                     XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::CHILD, nodeTest);
  438.                     stepsVector->addElement(step);
  439.                     break;
  440.                 }
  441.                 aToken = tokens.elementAt(++i);
  442.                 const XMLCh* localPart = stringPool->getValueForId(aToken);
  443.                 QName aQName(prefix, localPart, uri, fMemoryManager);
  444.                 // build step
  445.                 XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
  446.                 XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::CHILD, nodeTest);
  447.                 stepsVector->addElement(step);
  448.                 firstTokenOfLocationPath = false;
  449.                 break;
  450.             }
  451.         case XercesXPath::EXPRTOKEN_PERIOD:
  452.             {
  453.                 // build step
  454.                 XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NODE, fMemoryManager);
  455.                 XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::SELF, nodeTest);
  456.                 stepsVector->addElement(step);
  457.                 if (firstTokenOfLocationPath && i+1 < tokenCount) {
  458.                     aToken = tokens.elementAt(i+1);
  459.                     if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH){
  460.                         if (++i == tokenCount - 1) {
  461.                             ThrowXML(XPathException, XMLExcepts::XPath_ExpectedStep2);
  462.                         }
  463.                         if (i+1 < tokenCount) {
  464.                             aToken = tokens.elementAt(i+1);
  465.                             if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH) {
  466.                                 ThrowXML(XPathException, XMLExcepts::XPath_NoForwardSlash);
  467.                             }
  468.                         }
  469.                         // build step
  470.                         nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NODE, fMemoryManager);
  471.                         step = new (fMemoryManager) XercesStep(XercesStep::DESCENDANT, nodeTest);
  472.                         stepsVector->addElement(step);
  473.                     }
  474.                 }
  475.                 firstTokenOfLocationPath=false;
  476.                 break;
  477.             }
  478.         case XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH:
  479.             {
  480.                 ThrowXML(XPathException, XMLExcepts::XPath_NoDoubleForwardSlash);
  481.             }
  482.         case XercesXPath::EXPRTOKEN_OPERATOR_SLASH:
  483.             {
  484.                 if (i == 0) {
  485.                     ThrowXML(XPathException, XMLExcepts::XPath_NoForwardSlashAtStart);
  486.                 }
  487.                 // keep on truckin'
  488.                 if (firstTokenOfLocationPath) {
  489.                     ThrowXML(XPathException, XMLExcepts::XPath_NoSelectionOfRoot);
  490.                 }
  491.                 if (i == tokenCount - 1) {
  492.                     ThrowXML(XPathException, XMLExcepts::XPath_ExpectedStep3);
  493.                 }
  494.                 firstTokenOfLocationPath=false;
  495.                 break;
  496.             }
  497.         default:
  498.             firstTokenOfLocationPath=false;
  499.         }
  500.     }
  501.     int stepsSize = stepsVector->size();
  502.     if (stepsSize == 0) {
  503.         if (!fLocationPaths || fLocationPaths->size() == 0) {
  504.             ThrowXML(XPathException, XMLExcepts::XPath_EmptyExpr);
  505.         }
  506.         else {
  507.             ThrowXML(XPathException, XMLExcepts::XPath_NoUnionAtEnd);
  508.         }
  509.     }
  510.     fLocationPaths->addElement(new (fMemoryManager) XercesLocationPath(stepsVector));
  511.     janSteps.orphan();
  512. }
  513. // ---------------------------------------------------------------------------
  514. //  XPathScanner: Constructors and Destructor
  515. // ---------------------------------------------------------------------------
  516. XPathScanner::XPathScanner(XMLStringPool* const stringPool)
  517.     : fAndSymbol (0)
  518.     , fOrSymbol(0)
  519.     , fModSymbol(0)
  520.     , fDivSymbol(0)
  521.     , fCommentSymbol(0)
  522.     , fTextSymbol(0)
  523.     , fPISymbol(0)
  524.     , fNodeSymbol(0)
  525.     , fAncestorSymbol(0)
  526.     , fAncestorOrSelfSymbol(0)
  527.     , fAttributeSymbol(0)
  528.     , fChildSymbol(0)
  529.     , fDescendantSymbol(0)
  530.     , fDescendantOrSelfSymbol(0)
  531.     , fFollowingSymbol(0)
  532.     , fFollowingSiblingSymbol(0)
  533.     , fNamespaceSymbol(0)
  534.     , fParentSymbol(0)
  535.     , fPrecedingSymbol(0)
  536.     , fPrecedingSiblingSymbol(0)
  537.     , fSelfSymbol(0)
  538.     , fStringPool(stringPool)
  539. {
  540.     init();
  541. }
  542. // ---------------------------------------------------------------------------
  543. //  XPathScanner: Helper methods
  544. // ---------------------------------------------------------------------------
  545. void XPathScanner::init() {
  546.     fAndSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_AND);
  547.     fOrSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_OR);
  548.     fModSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_MOD);
  549.     fDivSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DIV);
  550.     fCommentSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_COMMENT);
  551.     fTextSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_TEXT);
  552.     fPISymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PI);
  553.     fNodeSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_NODE);
  554.     fAncestorSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ANCESTOR);
  555.     fAncestorOrSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ANCESTOR_OR_SELF);
  556.     fAttributeSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_ATTRIBUTE);
  557.     fChildSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_CHILD);
  558.     fDescendantSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DESCENDANT);
  559.     fDescendantOrSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_DESCENDANT_OR_SELF);
  560.     fFollowingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_FOLLOWING);
  561.     fFollowingSiblingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_FOLLOWING_SIBLING);
  562.     fNamespaceSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_NAMESPACE);
  563.     fParentSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PARENT);
  564.     fPrecedingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PRECEDING);
  565.     fPrecedingSiblingSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_PRECEDING_SIBLING);
  566.     fSelfSymbol = fStringPool->addOrFind(XPathSymbols::fgSYMBOL_SELF);
  567. }
  568. // ---------------------------------------------------------------------------
  569. //  XPathScanner: Scan methods
  570. // ---------------------------------------------------------------------------
  571. bool XPathScanner::scanExpression(const XMLCh* const data,
  572.                                   int currentOffset,
  573.                                   const int endOffset,
  574.                                   ValueVectorOf<int>* const tokens) {
  575.     bool      starIsMultiplyOperator = false;
  576.     int       nameOffset = -1;
  577.     int       nameHandle = -1;
  578.     int       prefixHandle = -1;
  579.     XMLCh     ch;
  580.     XMLBuffer dataBuffer(128, tokens->getMemoryManager());
  581.     while (true) {
  582.         if (currentOffset == endOffset) {
  583.             break;
  584.         }
  585.         ch = data[currentOffset];
  586.         while (XMLChar1_0::isWhitespace(ch)) {
  587.             if (++currentOffset == endOffset) {
  588.                 break;
  589.             }
  590.             ch = data[currentOffset];
  591.         }
  592.         if (currentOffset == endOffset) {
  593.             break;
  594.         }
  595.         //
  596.         // [28] ExprToken ::= '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | '::'
  597.         //                  | NameTest | NodeType | Operator | FunctionName
  598.         //                  | AxisName | Literal | Number | VariableReference
  599.         //
  600.         XMLByte chartype = (ch >= 0x80) ? CHARTYPE_NONASCII : fASCIICharMap[ch];
  601.         switch (chartype) {
  602.         case CHARTYPE_OPEN_PAREN:       // '('
  603.             addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_PAREN);
  604.             starIsMultiplyOperator = false;
  605.             ++currentOffset;
  606.             break;
  607.         case CHARTYPE_CLOSE_PAREN:      // ')'
  608.             addToken(tokens, XercesXPath::EXPRTOKEN_CLOSE_PAREN);
  609.             starIsMultiplyOperator = true;
  610.             ++currentOffset;
  611.             break;
  612.         case CHARTYPE_OPEN_BRACKET:     // '['
  613.             addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_BRACKET);
  614.             starIsMultiplyOperator = false;
  615.             ++currentOffset;
  616.             break;
  617.         case CHARTYPE_CLOSE_BRACKET:    // ']'
  618.             addToken(tokens, XercesXPath::EXPRTOKEN_CLOSE_BRACKET);
  619.             starIsMultiplyOperator = true;
  620.             ++currentOffset;
  621.             break;
  622.                 //
  623.                 // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
  624.                 //                                         ^^^^^^^^^^
  625.                 //
  626.         case CHARTYPE_PERIOD:           // '.', '..' or '.' Digits
  627.             if (currentOffset + 1 == endOffset) {
  628.                 addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
  629.                 starIsMultiplyOperator = true;
  630.                 currentOffset++;
  631.                 break;
  632.             }
  633.             ch = data[currentOffset + 1];
  634.             if (ch == chPeriod) {            // '..'
  635.                 addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_PERIOD);
  636.                 starIsMultiplyOperator = true;
  637.                 currentOffset += 2;
  638.             } else if (ch >= chDigit_0 && ch <= chDigit_9) {
  639.                 addToken(tokens, XercesXPath::EXPRTOKEN_NUMBER);
  640.                 starIsMultiplyOperator = true;
  641.                 currentOffset = scanNumber(data, endOffset, currentOffset, tokens);
  642.             } else if (ch == chForwardSlash) {
  643.                 addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
  644.                 starIsMultiplyOperator = true;
  645.                 currentOffset++;
  646.             } else if (ch == chPipe) { // '|'
  647.                 addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
  648.                 starIsMultiplyOperator = true;
  649.                 currentOffset++;
  650.             } else if (XMLChar1_0::isWhitespace(ch)) {
  651.                 do {
  652.                     if (++currentOffset == endOffset)
  653.                         break;
  654.                     ch = data[currentOffset];
  655.                 } while (XMLChar1_0::isWhitespace(ch));
  656.                 if (currentOffset == endOffset || ch == chPipe) {
  657.     addToken(tokens, XercesXPath::EXPRTOKEN_PERIOD);
  658.                     starIsMultiplyOperator = true;
  659.                     break;
  660.                 }
  661.             } else {
  662.                 ThrowXML(XPathException, XMLExcepts::XPath_InvalidChar);
  663.             }
  664.             break;
  665.         case CHARTYPE_ATSIGN:           // '@'
  666.             addToken(tokens, XercesXPath::EXPRTOKEN_ATSIGN);
  667.             starIsMultiplyOperator = false;
  668.             ++currentOffset;
  669.             break;
  670.         case CHARTYPE_COMMA:            // ','
  671.             addToken(tokens, XercesXPath::EXPRTOKEN_COMMA);
  672.             starIsMultiplyOperator = false;
  673.             ++currentOffset;
  674.             break;
  675.         case CHARTYPE_COLON:            // '::'
  676.             if (++currentOffset == endOffset) {
  677.                 return false; // REVISIT
  678.             }
  679.             ch = data[currentOffset];
  680.             if (ch != chColon) {
  681.                 return false; // REVISIT
  682.             }
  683.             addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_COLON);
  684.             starIsMultiplyOperator = false;
  685.             ++currentOffset;
  686.             break;
  687.         case CHARTYPE_SLASH:            // '/' and '//'
  688.             if (++currentOffset == endOffset) {
  689.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_SLASH);
  690.                 starIsMultiplyOperator = false;
  691.                 break;
  692.             }
  693.             ch = data[currentOffset];
  694.             if (ch == chForwardSlash) { // '//'
  695.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH);
  696.                 starIsMultiplyOperator = false;
  697.                 ++currentOffset;
  698.             } else {
  699.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_SLASH);
  700.                 starIsMultiplyOperator = false;
  701.             }
  702.             break;
  703.         case CHARTYPE_UNION:            // '|'
  704.             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_UNION);
  705.             starIsMultiplyOperator = false;
  706.             ++currentOffset;
  707.             break;
  708.         case CHARTYPE_PLUS:             // '+'
  709.             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_PLUS);
  710.             starIsMultiplyOperator = false;
  711.             ++currentOffset;
  712.             break;
  713.         case CHARTYPE_MINUS:            // '-'
  714.             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MINUS);
  715.             starIsMultiplyOperator = false;
  716.             ++currentOffset;
  717.             break;
  718.         case CHARTYPE_EQUAL:            // '='
  719.             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_EQUAL);
  720.             starIsMultiplyOperator = false;
  721.             ++currentOffset;
  722.             break;
  723.         case CHARTYPE_EXCLAMATION:      // '!='
  724.             if (++currentOffset == endOffset) {
  725.                 return false; // REVISIT
  726.             }
  727.             ch = data[currentOffset];
  728.             if (ch != chEqual) {
  729.                 return false; // REVISIT
  730.             }
  731.             addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_NOT_EQUAL);
  732.             starIsMultiplyOperator = false;
  733.             ++currentOffset;
  734.             break;
  735.         case CHARTYPE_LESS: // '<' and '<='
  736.             if (++currentOffset == endOffset) {
  737.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS);
  738.                 starIsMultiplyOperator = false;
  739.                 break;
  740.             }
  741.             ch = data[currentOffset];
  742.             if (ch == chEqual) { // '<='
  743.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS_EQUAL);
  744.                 starIsMultiplyOperator = false;
  745.                 ++currentOffset;
  746.             } else {
  747.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_LESS);
  748.                 starIsMultiplyOperator = false;
  749.             }
  750.             break;
  751.         case CHARTYPE_GREATER: // '>' and '>='
  752.             if (++currentOffset == endOffset) {
  753.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER);
  754.                 starIsMultiplyOperator = false;
  755.                 break;
  756.             }
  757.             ch = data[currentOffset];
  758.             if (ch == chEqual) { // '>='
  759.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER_EQUAL);
  760.                 starIsMultiplyOperator = false;
  761.                 ++currentOffset;
  762.             } else {
  763.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_GREATER);
  764.                 starIsMultiplyOperator = false;
  765.             }
  766.             break;
  767.         //
  768.         // [29] Literal ::= '"' [^"]* '"' | "'" [^']* "'"
  769.         //
  770.         case CHARTYPE_QUOTE:            // '"' or '''
  771.             {
  772.                 XMLCh qchar = ch;
  773.                 if (++currentOffset == endOffset) {
  774.                     return false; // REVISIT
  775.                 }
  776.                 ch = data[currentOffset];
  777.                 int litOffset = currentOffset;
  778.                 while (ch != qchar) {
  779.                     if (++currentOffset == endOffset) {
  780.                         return false; // REVISIT
  781.                     }
  782.                     ch = data[currentOffset];
  783.                 }
  784.                 addToken(tokens, XercesXPath::EXPRTOKEN_LITERAL);
  785.                 starIsMultiplyOperator = true;
  786.                 dataBuffer.set(data + litOffset, currentOffset - litOffset);
  787.                 tokens->addElement(fStringPool->addOrFind(dataBuffer.getRawBuffer()));
  788.                 ++currentOffset;
  789.                 break;
  790.             }
  791.         //
  792.         // [30] Number ::= Digits ('.' Digits?)? | '.' Digits
  793.         // [31] Digits ::= [0-9]+
  794.         //
  795.         case CHARTYPE_DIGIT:
  796.             addToken(tokens, XercesXPath::EXPRTOKEN_NUMBER);
  797.             starIsMultiplyOperator = true;
  798.             currentOffset = scanNumber(data, endOffset, currentOffset, tokens);
  799.             break;
  800.         //
  801.         // [36] VariableReference ::= '$' QName
  802.         //
  803.         case CHARTYPE_DOLLAR:
  804.             if (++currentOffset == endOffset) {
  805.                 return false; // REVISIT
  806.             }
  807.             nameOffset = currentOffset;
  808.             currentOffset = scanNCName(data, endOffset, currentOffset);
  809.             if (currentOffset == nameOffset) {
  810.                 return false; // REVISIT
  811.             }
  812.             if (currentOffset < endOffset) {
  813.                 ch = data[currentOffset];
  814.             }
  815.             else {
  816.                 ch = 0;
  817.             }
  818.             dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
  819.             nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
  820.             prefixHandle = -1;
  821.             if (ch == chColon) {
  822.                 prefixHandle = nameHandle;
  823.                 if (++currentOffset == endOffset) {
  824.                     return false; // REVISIT
  825.                 }
  826.                 nameOffset = currentOffset;
  827.                 currentOffset = scanNCName(data, endOffset, currentOffset);
  828.                 if (currentOffset == nameOffset) {
  829.                     return false; // REVISIT
  830.                 }
  831.                 dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
  832.                 nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
  833.             }
  834.             addToken(tokens, XercesXPath::EXPRTOKEN_VARIABLE_REFERENCE);
  835.             starIsMultiplyOperator = true;
  836.             tokens->addElement(prefixHandle);
  837.             tokens->addElement(nameHandle);
  838.             break;
  839.         //
  840.         // [37] NameTest ::= '*' | NCName ':' '*' | QName
  841.         // [34] MultiplyOperator ::= '*'
  842.         //
  843.         case CHARTYPE_STAR:             // '*'
  844.             //
  845.             // 3.7 Lexical Structure
  846.             //
  847.             //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
  848.             //  an Operator, then a * must be recognized as a MultiplyOperator.
  849.             //
  850.             // Otherwise, the token must not be recognized as a MultiplyOperator.
  851.             //
  852.             if (starIsMultiplyOperator) {
  853.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MULT);
  854.                 starIsMultiplyOperator = false;
  855.             } else {
  856.                 addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_ANY);
  857.                 starIsMultiplyOperator = true;
  858.             }
  859.             ++currentOffset;
  860.             break;
  861.         //
  862.         // NCName, QName and non-terminals
  863.         //
  864.         case CHARTYPE_NONASCII: // possibly a valid non-ascii 'Letter' (BaseChar | Ideographic)
  865.         case CHARTYPE_LETTER:
  866.         case CHARTYPE_UNDERSCORE:
  867.             //
  868.             // 3.7 Lexical Structure
  869.             //
  870.             //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
  871.             //  an Operator, then an NCName must be recognized as an OperatorName.
  872.             //
  873.             //  If the character following an NCName (possibly after intervening ExprWhitespace) is (,
  874.             //  then the token must be recognized as a NodeType or a FunctionName.
  875.             //
  876.             //  If the two characters following an NCName (possibly after intervening ExprWhitespace)
  877.             //  are ::, then the token must be recognized as an AxisName.
  878.             //
  879.             //  Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
  880.             //  FunctionName, or an AxisName.
  881.             //
  882.             // [33] OperatorName ::= 'and' | 'or' | 'mod' | 'div'
  883.             // [38] NodeType ::= 'comment' | 'text' | 'processing-instruction' | 'node'
  884.             // [35] FunctionName ::= QName - NodeType
  885.             // [6] AxisName ::= (see above)
  886.             //
  887.             // [37] NameTest ::= '*' | NCName ':' '*' | QName
  888.             // [5] NCName ::= (Letter | '_') (NCNameChar)*
  889.             // [?] NCNameChar ::= Letter | Digit | '.' | '-' | '_'  (ascii subset of 'NCNameChar')
  890.             // [?] QName ::= (NCName ':')? NCName
  891.             // [?] Letter ::= [A-Za-z]                              (ascii subset of 'Letter')
  892.             // [?] Digit ::= [0-9]                                  (ascii subset of 'Digit')
  893.             //
  894.             nameOffset = currentOffset;
  895.             currentOffset = scanNCName(data, endOffset, currentOffset);
  896.             if (currentOffset == nameOffset) {
  897.                 return false; // REVISIT
  898. }
  899.             if (currentOffset < endOffset) {
  900.                 ch = data[currentOffset];
  901.             }
  902.             else {
  903.                 ch = 0;
  904.             }
  905.             dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
  906.             nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
  907.             bool isNameTestNCName = false;
  908.             bool isAxisName = false;
  909.             prefixHandle = -1;
  910.             if (ch == chColon) {
  911.                 if (++currentOffset == endOffset) {
  912.                     return false; // REVISIT
  913.                 }
  914.                 ch = data[currentOffset];
  915.                 if (ch == chAsterisk) {
  916.                     if (++currentOffset < endOffset) {
  917.                         ch = data[currentOffset];
  918.                     }
  919.                     isNameTestNCName = true;
  920.                 } else if (ch == chColon) {
  921.                     if (++currentOffset < endOffset) {
  922.                         ch = data[currentOffset];
  923.                     }
  924.                     isAxisName = true;
  925.                 } else {
  926.                     prefixHandle = nameHandle;
  927.                     nameOffset = currentOffset;
  928.                     currentOffset = scanNCName(data, endOffset, currentOffset);
  929.                     if (currentOffset == nameOffset) {
  930.                         return false; // REVISIT
  931.                     }
  932.                     if (currentOffset < endOffset) {
  933.                         ch = data[currentOffset];
  934.                     }
  935.                     else {
  936.                         ch = 0;
  937.                     }
  938.                     dataBuffer.set(data + nameOffset, currentOffset - nameOffset);
  939.                     nameHandle = fStringPool->addOrFind(dataBuffer.getRawBuffer());
  940.                 }
  941.             }
  942.             //
  943.             // [39] ExprWhitespace ::= S
  944.             //
  945.             while (XMLChar1_0::isWhitespace(ch)) {
  946.                 if (++currentOffset == endOffset) {
  947.                     break;
  948.                 }
  949.                 ch = data[currentOffset];
  950.             }
  951.             //
  952.             //  If there is a preceding token and the preceding token is not one of @, ::, (, [, , or
  953.             //  an Operator, then an NCName must be recognized as an OperatorName.
  954.             //
  955.             if (starIsMultiplyOperator) {
  956.                 if (nameHandle == fAndSymbol) {
  957.                     addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_AND);
  958.                     starIsMultiplyOperator = false;
  959.                 } else if (nameHandle == fOrSymbol) {
  960.                     addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_OR);
  961.                     starIsMultiplyOperator = false;
  962.                 } else if (nameHandle == fModSymbol) {
  963.                     addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_MOD);
  964.                     starIsMultiplyOperator = false;
  965.                 } else if (nameHandle == fDivSymbol) {
  966.                     addToken(tokens, XercesXPath::EXPRTOKEN_OPERATOR_DIV);
  967.                     starIsMultiplyOperator = false;
  968.                 } else {
  969.                     return false; // REVISIT
  970.                 }
  971.                 if (isNameTestNCName) {
  972.                     return false; // REVISIT - NCName:* where an OperatorName is required
  973.                 } else if (isAxisName) {
  974.                     return false; // REVISIT - AxisName:: where an OperatorName is required
  975.                 }
  976.                 break;
  977.             }
  978.             //
  979.             //  If the character following an NCName (possibly after intervening ExprWhitespace) is (,
  980.             //  then the token must be recognized as a NodeType or a FunctionName.
  981.             //
  982.             if (ch == chOpenParen && !isNameTestNCName && !isAxisName) {
  983.                 if (nameHandle == fCommentSymbol) {
  984.                     addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_COMMENT);
  985.                 } else if (nameHandle == fTextSymbol) {
  986.                     addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_TEXT);
  987.                 } else if (nameHandle == fPISymbol) {
  988.                     addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_PI);
  989.                 } else if (nameHandle == fNodeSymbol) {
  990.                     addToken(tokens, XercesXPath::EXPRTOKEN_NODETYPE_NODE);
  991.                 } else {
  992.                     addToken(tokens, XercesXPath::EXPRTOKEN_FUNCTION_NAME);
  993.                     tokens->addElement(prefixHandle);
  994.                     tokens->addElement(nameHandle);
  995.                 }
  996.                 addToken(tokens, XercesXPath::EXPRTOKEN_OPEN_PAREN);
  997.                 starIsMultiplyOperator = false;
  998.                 ++currentOffset;
  999.                 break;
  1000.             }
  1001.             //
  1002.             //  If the two characters following an NCName (possibly after intervening ExprWhitespace)
  1003.             //  are ::, then the token must be recognized as an AxisName.
  1004.             //
  1005.             if (isAxisName ||
  1006.                 (ch == chColon && currentOffset + 1 < endOffset &&
  1007.                  data[currentOffset + 1] == chColon)) {
  1008.                 if (nameHandle == fAncestorSymbol) {
  1009.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ANCESTOR);
  1010.                 } else if (nameHandle == fAncestorOrSelfSymbol) {
  1011.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ANCESTOR_OR_SELF);
  1012.                 } else if (nameHandle == fAttributeSymbol) {
  1013.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE);
  1014.                 } else if (nameHandle == fChildSymbol) {
  1015.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_CHILD);
  1016.                 } else if (nameHandle == fDescendantSymbol) {
  1017.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_DESCENDANT);
  1018.                 } else if (nameHandle == fDescendantOrSelfSymbol) {
  1019.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_DESCENDANT_OR_SELF);
  1020.                 } else if (nameHandle == fFollowingSymbol) {
  1021.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_FOLLOWING);
  1022.                 } else if (nameHandle == fFollowingSiblingSymbol) {
  1023.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_FOLLOWING_SIBLING);
  1024.                 } else if (nameHandle == fNamespaceSymbol) {
  1025.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_NAMESPACE);
  1026.                 } else if (nameHandle == fParentSymbol) {
  1027.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PARENT);
  1028.                 } else if (nameHandle == fPrecedingSymbol) {
  1029.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PRECEDING);
  1030.                 } else if (nameHandle == fPrecedingSiblingSymbol) {
  1031.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_PRECEDING_SIBLING);
  1032.                 } else if (nameHandle == fSelfSymbol) {
  1033.                     addToken(tokens, XercesXPath::EXPRTOKEN_AXISNAME_SELF);
  1034.                 } else {
  1035.                     return false; // REVISIT
  1036.                 }
  1037.                 if (isNameTestNCName) {
  1038.                     return false; // REVISIT - "NCName:* ::" where "AxisName ::" is required
  1039.                 }
  1040.                 addToken(tokens, XercesXPath::EXPRTOKEN_DOUBLE_COLON);
  1041.                 starIsMultiplyOperator = false;
  1042.                 if (!isAxisName) {
  1043.                     currentOffset += 2;
  1044.                 }
  1045.                 break;
  1046.             }
  1047.             //
  1048.             //  Otherwise, the token must not be recognized as an OperatorName, a NodeType, a
  1049.             //  FunctionName, or an AxisName.
  1050.             //
  1051.             if (isNameTestNCName) {
  1052.                 addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE);
  1053.                 tokens->addElement(nameHandle);
  1054.             } else {
  1055.                 addToken(tokens, XercesXPath::EXPRTOKEN_NAMETEST_QNAME);
  1056.                 tokens->addElement(prefixHandle);
  1057.                 tokens->addElement(nameHandle);
  1058.             }
  1059.             starIsMultiplyOperator = true;
  1060.             break;
  1061.         }
  1062.     }
  1063.     return true;
  1064. }
  1065. int XPathScanner::scanNCName(const XMLCh* const data,
  1066.                              const int endOffset,
  1067.                              int currentOffset) {
  1068.     XMLCh ch = data[currentOffset];
  1069.     if (!XMLChar1_0::isXMLLetter(ch) && ch != chUnderscore) {
  1070.         return currentOffset;
  1071.     }
  1072.     while (++currentOffset < endOffset) {
  1073.         ch = data[currentOffset];
  1074.         if (ch == chColon || !XMLChar1_0::isNameChar(ch)) {
  1075.             break;
  1076.         }
  1077.     }
  1078.     return currentOffset;
  1079. }
  1080. int XPathScanner::scanNumber(const XMLCh* const data,
  1081.                              const int endOffset,
  1082.                              int currentOffset,
  1083.                              ValueVectorOf<int>* const tokens) {
  1084.     XMLCh ch = data[currentOffset];
  1085.     int   whole = 0;
  1086.     int   part = 0;
  1087.     while (ch >= chDigit_0 && ch <= chDigit_9) {
  1088.         whole = (whole * 10) + (ch - chDigit_0);
  1089.         if (++currentOffset == endOffset) {
  1090.             break;
  1091.         }
  1092.         ch = data[currentOffset];
  1093.     }
  1094.     if (ch == chPeriod) {
  1095.         if (++currentOffset < endOffset) {
  1096.             int start = currentOffset;
  1097.             ch = data[currentOffset];
  1098.             while (ch >= chDigit_0 && ch <= chDigit_9) {
  1099.                 part = (part * 10) + (ch - chDigit_0);
  1100.                 if (++currentOffset == endOffset) {
  1101.                     break;
  1102.                 }
  1103.                 ch = data[currentOffset];
  1104.             }
  1105.             if (part != 0) {
  1106.                 ThrowXML(RuntimeException, XMLExcepts::XPath_FindSolution);
  1107.             }
  1108.         }
  1109.     }
  1110.     tokens->addElement(whole);
  1111.     tokens->addElement(part);
  1112.     return currentOffset;
  1113. }
  1114. // ---------------------------------------------------------------------------
  1115. //  XPathScannerForSchema: Constructors and Destructor
  1116. // ---------------------------------------------------------------------------
  1117. XPathScannerForSchema::XPathScannerForSchema(XMLStringPool* const stringPool)
  1118.     : XPathScanner(stringPool)
  1119. {
  1120. }
  1121. // ---------------------------------------------------------------------------
  1122. //  XPathScannerForSchema: Helper methods
  1123. // ---------------------------------------------------------------------------
  1124. void XPathScannerForSchema::addToken(ValueVectorOf<int>* const tokens,
  1125.                                      const int aToken) {
  1126.     if (aToken == XercesXPath::EXPRTOKEN_ATSIGN ||
  1127.         aToken == XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE ||
  1128.         aToken == XercesXPath::EXPRTOKEN_AXISNAME_CHILD ||
  1129.         //token == XercesXPath::EXPRTOKEN_AXISNAME_SELF ||
  1130.         aToken == XercesXPath::EXPRTOKEN_DOUBLE_COLON ||
  1131.         aToken == XercesXPath::EXPRTOKEN_NAMETEST_QNAME ||
  1132.         //token == XercesXPath::EXPRTOKEN_NODETYPE_NODE ||
  1133.         aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH ||
  1134.         aToken == XercesXPath::EXPRTOKEN_PERIOD ||
  1135.         aToken == XercesXPath::EXPRTOKEN_NAMETEST_ANY ||
  1136.         aToken == XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE ||
  1137.         aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH ||
  1138.         aToken == XercesXPath::EXPRTOKEN_OPERATOR_UNION) {
  1139.         tokens->addElement(aToken);
  1140.         return;
  1141.     }
  1142.     ThrowXML(XPathException, XMLExcepts::XPath_TokenNotSupported);
  1143. }
  1144. XERCES_CPP_NAMESPACE_END
  1145. /**
  1146.   * End of file XercesPath.cpp
  1147.   */