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

xml/soap/webservice

开发平台:

C/C++

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