in src/xercesc/validators/schema/identity/XercesXPath.cpp [382:688]
void XercesXPath::parseExpression(XMLStringPool* const stringPool,
XercesNamespaceResolver* const scopeContext) {
XMLSize_t length = XMLString::stringLen(fExpression);
if (!length) {
return;
}
ValueVectorOf<int> tokens(16, fMemoryManager);
XPathScannerForSchema scanner(stringPool);
if(!scanner.scanExpression(fExpression, 0, length, &tokens))
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_TokenNotSupported, fMemoryManager);
bool firstTokenOfLocationPath=true;
XMLSize_t tokenCount = tokens.size();
RefVectorOf<XercesStep>* stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
Janitor<RefVectorOf<XercesStep> > janSteps(stepsVector);
if (tokenCount) {
fLocationPaths = new (fMemoryManager) RefVectorOf<XercesLocationPath>(8, true, fMemoryManager);
}
for (XMLSize_t i = 0; i < tokenCount; i++) {
int aToken = tokens.elementAt(i);
bool isNamespace=false;
switch (aToken) {
case XercesXPath::EXPRTOKEN_OPERATOR_UNION:
{
if (i == 0) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtStart, fMemoryManager);
}
XMLSize_t stepsSize = stepsVector->size();
if (stepsSize == 0) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoMultipleUnion, fMemoryManager);
}
if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF)
{
// prepend ./
XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
stepsVector->insertElementAt(step, 0);
}
XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector);
janSteps.orphan();
bool bFound=false;
for(XMLSize_t i=0;i<fLocationPaths->size();i++)
if((*(fLocationPaths->elementAt(i)))==(*newPath))
{
bFound=true;
break;
}
if(bFound)
delete newPath;
else
fLocationPaths->addElement(newPath);
stepsVector = new (fMemoryManager) RefVectorOf<XercesStep>(16, true, fMemoryManager);
janSteps.reset(stepsVector);
firstTokenOfLocationPath = true;
}
break;
case XercesXPath::EXPRTOKEN_AXISNAME_ATTRIBUTE:
{
// consume "::" token and drop through
i++;
}
case XercesXPath::EXPRTOKEN_ATSIGN:
{
// consume QName token
if (i == tokenCount - 1) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_MissingAttr, fMemoryManager);
}
aToken = tokens.elementAt(++i);
if (aToken != XercesXPath::EXPRTOKEN_NAMETEST_QNAME
&& aToken!= XercesXPath::EXPRTOKEN_NAMETEST_ANY
&& aToken!= XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedToken1, fMemoryManager);
}
bool isNamespaceAtt=false;
switch (aToken) {
case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
{
XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, fMemoryManager);
XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
stepsVector->addElement(step);
break;
}
case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
{
isNamespaceAtt = true;
}
case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
{
aToken = tokens.elementAt(++i);
const XMLCh* prefix = XMLUni::fgZeroLenString;
unsigned int uri = fEmptyNamespaceId;
if (scopeContext && aToken != -1) {
prefix = stringPool->getValueForId(aToken);
uri = scopeContext->getNamespaceForPrefix(prefix);
}
if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager);
}
if (isNamespaceAtt) {
// build step
XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager);
XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
stepsVector->addElement(step);
break;
}
aToken = tokens.elementAt(++i);
const XMLCh* localPart = stringPool->getValueForId(aToken);
QName aQName(prefix, localPart, uri, fMemoryManager);
// build step
XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_ATTRIBUTE, nodeTest);
stepsVector->addElement(step);
break;
}
}
firstTokenOfLocationPath=false;
break;
}
case XercesXPath::EXPRTOKEN_DOUBLE_COLON:
{
// should never have a bare double colon
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleColon, fMemoryManager);
}
case XercesXPath::EXPRTOKEN_AXISNAME_CHILD:
{
// consume "::" token and drop through
i++;
if (i == tokenCount - 1) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep1, fMemoryManager);
}
firstTokenOfLocationPath=false;
break;
}
case XercesXPath::EXPRTOKEN_NAMETEST_ANY:
{
XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_WILDCARD, fMemoryManager);
XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
stepsVector->addElement(step);
firstTokenOfLocationPath = false;
break;
}
case XercesXPath::EXPRTOKEN_NAMETEST_NAMESPACE:
{
isNamespace=true;
}
case XercesXPath::EXPRTOKEN_NAMETEST_QNAME:
{
// consume QName token
aToken = tokens.elementAt(++i);
const XMLCh* prefix = XMLUni::fgZeroLenString;
unsigned int uri = fEmptyNamespaceId;
if (scopeContext && aToken != -1) {
prefix = stringPool->getValueForId(aToken);
uri = scopeContext->getNamespaceForPrefix(prefix);
}
if (aToken != -1 && scopeContext && uri == fEmptyNamespaceId) {
ThrowXMLwithMemMgr1(XPathException, XMLExcepts::XPath_PrefixNoURI, prefix, fMemoryManager);
}
if (isNamespace) {
// build step
XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(prefix, uri, fMemoryManager);
XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
stepsVector->addElement(step);
break;
}
aToken = tokens.elementAt(++i);
const XMLCh* localPart = stringPool->getValueForId(aToken);
QName aQName(prefix, localPart, uri, fMemoryManager);
// build step
XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(&aQName);
XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_CHILD, nodeTest);
stepsVector->addElement(step);
firstTokenOfLocationPath = false;
break;
}
case XercesXPath::EXPRTOKEN_PERIOD:
{
// build step
XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
stepsVector->addElement(step);
if (firstTokenOfLocationPath && i+1 < tokenCount) {
aToken = tokens.elementAt(i+1);
if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH){
if (++i == tokenCount - 1) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep2, fMemoryManager);
}
if (i+1 < tokenCount) {
aToken = tokens.elementAt(i+1);
if (aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlash, fMemoryManager);
}
}
// build step
nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
step = new (fMemoryManager) XercesStep(XercesStep::AxisType_DESCENDANT, nodeTest);
stepsVector->addElement(step);
}
}
firstTokenOfLocationPath=false;
break;
}
case XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH:
{
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoDoubleForwardSlash, fMemoryManager);
}
case XercesXPath::EXPRTOKEN_OPERATOR_SLASH:
{
if (i == 0) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoForwardSlashAtStart, fMemoryManager);
}
// keep on truckin'
if (firstTokenOfLocationPath) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoSelectionOfRoot, fMemoryManager);
}
if (i == tokenCount - 1) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager);
}
aToken = tokens.elementAt(i+1);
if(aToken == XercesXPath::EXPRTOKEN_OPERATOR_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_DOUBLE_SLASH || aToken == XercesXPath::EXPRTOKEN_OPERATOR_UNION)
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_ExpectedStep3, fMemoryManager);
firstTokenOfLocationPath=false;
break;
}
default:
firstTokenOfLocationPath=false;
}
}
XMLSize_t stepsSize = stepsVector->size();
if (stepsSize == 0) {
if (!fLocationPaths || fLocationPaths->size() == 0) {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_EmptyExpr, fMemoryManager);
}
else {
ThrowXMLwithMemMgr(XPathException, XMLExcepts::XPath_NoUnionAtEnd, fMemoryManager);
}
}
if(stepsVector->elementAt(0)->getAxisType()!=XercesStep::AxisType_SELF)
{
// prepend ./
XercesNodeTest* nodeTest = new (fMemoryManager) XercesNodeTest(XercesNodeTest::NodeType_NODE, fMemoryManager);
XercesStep* step = new (fMemoryManager) XercesStep(XercesStep::AxisType_SELF, nodeTest);
stepsVector->insertElementAt(step, 0);
}
XercesLocationPath* newPath = new (fMemoryManager) XercesLocationPath(stepsVector);
janSteps.orphan();
bool bFound=false;
for(XMLSize_t j=0;j<fLocationPaths->size();j++)
if((*(fLocationPaths->elementAt(j)))==(*newPath))
{
bFound=true;
break;
}
if(bFound)
delete newPath;
else
fLocationPaths->addElement(newPath);
}