// don't return true or false, if it's invalid path, just throw exception during the process
// for whitespace thing, i will directly trim the tree built here...
public void CompileXPath(string xPath, bool isField, XmlNamespaceManager nsmgr)
{
if ((xPath == null) || (xPath.Length == 0))
{
throw new XmlSchemaException(SR.Sch_EmptyXPath, string.Empty);
}
// firstly i still need to have an ArrayList to store tree only...
// can't new ForwardAxis right away
string[] xpath = xPath.Split('|');
ArrayList AstArray = new ArrayList(xpath.Length);
_fAxisArray = new ArrayList(xpath.Length);
// throw compile exceptions
// can i only new one builder here then run compile several times??
try
{
for (int i = 0; i < xpath.Length; ++i)
{
// default ! isdesorself (no .//)
Axis ast = (Axis)(XPathParser.ParseXPathExpression(xpath[i]));
AstArray.Add(ast);
}
}
catch
{
throw new XmlSchemaException(SR.Sch_ICXpathError, xPath);
}
Axis?stepAst;
for (int i = 0; i < AstArray.Count; ++i)
{
Axis ast = (Axis)AstArray[i] !;
// Restricted form
// field can have an attribute:
// throw exceptions during casting
if ((stepAst = ast) == null)
{
throw new XmlSchemaException(SR.Sch_ICXpathError, xPath);
}
Axis top = stepAst;
// attribute will have namespace too
// field can have top attribute
if (IsAttribute(stepAst))
{
if (!isField)
{
throw new XmlSchemaException(SR.Sch_SelectorAttr, xPath);
}
else
{
SetURN(stepAst, nsmgr);
try
{
stepAst = (Axis?)(stepAst.Input);
}
catch
{
throw new XmlSchemaException(SR.Sch_ICXpathError, xPath);
}
}
}
// field or selector
while ((stepAst != null) && (IsNameTest(stepAst) || IsSelf(stepAst)))
{
// trim tree "." node, if it's not the top one
if (IsSelf(stepAst) && (ast != stepAst))
{
top.Input = stepAst.Input;
}
else
{
top = stepAst;
// set the URN
if (IsNameTest(stepAst))
{
SetURN(stepAst, nsmgr);
}
}
try
{
stepAst = (Axis?)(stepAst.Input);
}
catch
{
throw new XmlSchemaException(SR.Sch_ICXpathError, xPath);
}
}
// the rest part can only be .// or null
// trim the rest part, but need compile the rest part first
top.Input = null;
if (stepAst == null)
{ // top "." and has other element beneath, trim this "." node too
if (IsSelf(ast) && (ast.Input != null))
{
_fAxisArray.Add(new ForwardAxis(DoubleLinkAxis.ConvertTree((Axis)(ast.Input)), false));
}
else
{
_fAxisArray.Add(new ForwardAxis(DoubleLinkAxis.ConvertTree(ast), false));
}
continue;
}
if (!IsDescendantOrSelf(stepAst))
{
throw new XmlSchemaException(SR.Sch_ICXpathError, xPath);
}
try
{
stepAst = (Axis?)(stepAst.Input);
}
catch
{
throw new XmlSchemaException(SR.Sch_ICXpathError, xPath);
}
if ((stepAst == null) || (!IsSelf(stepAst)) || (stepAst.Input != null))
{
throw new XmlSchemaException(SR.Sch_ICXpathError, xPath);
}
// trim top "." if it's not the only node
if (IsSelf(ast) && (ast.Input != null))
{
_fAxisArray.Add(new ForwardAxis(DoubleLinkAxis.ConvertTree((Axis)(ast.Input)), true));
}
else
{
_fAxisArray.Add(new ForwardAxis(DoubleLinkAxis.ConvertTree(ast), true));
}
}
}