public ForwardAxis(DoubleLinkAxis axis, bool isdesorself) { this.isDss = isdesorself; this.isAttribute = Asttree.IsAttribute(axis); this.topNode = axis; this.rootNode = axis; while (this.rootNode.Input != null) { this.rootNode = (DoubleLinkAxis)(this.rootNode.Input); } // better to calculate it out, since it's used so often, and if the top is self then the whole tree is self this.isSelfAxis = Asttree.IsSelf(this.topNode); }
//constructor internal DoubleLinkAxis(Axis axis, DoubleLinkAxis inputaxis) { this.next = null; this._input = inputaxis; this._urn = axis.URN; this._prefix = axis.Prefix; this._name = axis.Name; this._nodetype = axis.Type; this._axistype = axis.TypeOfAxis; this.abbrAxis = axis.abbrAxis; if (inputaxis != null) { inputaxis.Next = this; } }
// equal & ! attribute then move // "a/b/c" pointer from a move to b // return true if reach c and c is an element and c is the axis internal bool MoveToChild(string name, string URN, int depth, ForwardAxis parent) { // an attribute can never be the same as an element if (Asttree.IsAttribute(this.curNode)) { return(false); } // either moveToParent or moveToChild status will have to be changed into unmatch... if (this.isMatch) { this.isMatch = false; } if (!AxisStack.Equal(this.curNode.Name, this.curNode.URN, name, URN)) { return(false); } if (this.curDepth == -1) { SetDepth(depth); } else if (depth > this.curDepth) { return(false); } // matched ... if (this.curNode == parent.TopNode) { this.isMatch = true; return(true); } // move down this.curNode DoubleLinkAxis nowNode = (DoubleLinkAxis)(this.curNode.Next); if (Asttree.IsAttribute(nowNode)) { this.isMatch = true; // for attribute return(false); } this.curNode = nowNode; this.curDepth++; return(false); }
// only for debug #if DEBUG public void PrintTree(StreamWriter msw) { foreach (ForwardAxis axis in fAxisArray) { msw.WriteLine("<Tree IsDss=\"{0}\" IsAttribute=\"{1}\">", axis.IsDss, axis.IsAttribute); DoubleLinkAxis printaxis = axis.TopNode; while (printaxis != null) { msw.WriteLine(" <node>"); msw.WriteLine(" <URN> {0} </URN>", printaxis.URN); msw.WriteLine(" <Prefix> {0} </Prefix>", printaxis.Prefix); msw.WriteLine(" <Name> {0} </Name>", printaxis.Name); msw.WriteLine(" <NodeType> {0} </NodeType>", printaxis.Type); msw.WriteLine(" <AxisType> {0} </AxisType>", printaxis.TypeOfAxis); msw.WriteLine(" </node>"); printaxis = (DoubleLinkAxis)(printaxis.Input); } msw.WriteLine("</Tree>"); } }
// "a/b/c" pointer from b move to a // needn't change even tree structure changes internal void MoveToParent(int depth, ForwardAxis parent) { // "a/b/c", trying to match b (current node), but meet the end of a, so move pointer to a if (depth == this.curDepth - 1) { // really need to move the current node pointer to parent // what i did here is for seperating the case of IsDss or only IsChild // bcoz in the first case i need to expect "a" from random depth // -1 means it doesn't expect some specific depth (referecing the dealing to -1 in movetochild method // while in the second case i can't change the root depth which is 1. if ((this.curNode.Input == parent.RootNode) && (parent.IsDss)) { this.curNode = parent.RootNode; this.rootDepth = this.curDepth = -1; return; } else if (this.curNode.Input != null) // else cur-depth --, cur-node change { this.curNode = (DoubleLinkAxis)(this.curNode.Input); this.curDepth--; return; } else { return; } } // "a/b/c", trying to match b (current node), but meet the end of x (another child of a) // or maybe i matched, now move out the current node // or move out after failing to match attribute // the node i m next expecting is still the current node else if (depth == this.curDepth) // after matched or [2] failed in matching attribute { if (this.isMatch) { this.isMatch = false; } } return; // this node is still what i am expecting // ignore }
// 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 == string.Empty)) { throw new XmlSchemaException(Res.Sch_EmptyXPath); } // 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); this.fAxisArray = new ArrayList(xpath.Length); // throw compile exceptions // can i only new one builder here then run compile several times?? try { foreach (string value in xpath) { // default ! isdesorself (no .//) Axis ast = (Axis)(XPathParser.ParseXPathExpresion(value)); AstArray.Add(ast); } } catch { throw new XmlSchemaException(Res.Sch_ICXpathError, xPath); } Axis stepAst; foreach (Axis ast in AstArray) { // Restricted form // field can have an attribute: // throw exceptions during casting if ((stepAst = ast) == null) { throw new XmlSchemaException(Res.Sch_ICXpathError, xPath); } Axis top = stepAst; // attribute will have namespace too // field can have top attribute if (IsAttribute(stepAst)) { if (!isField) { throw new XmlSchemaException(Res.Sch_SelectorAttr, xPath); } else { SetURN(stepAst, nsmgr); try { stepAst = (Axis)(stepAst.Input); } catch { throw new XmlSchemaException(Res.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(Res.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)) { this.fAxisArray.Add(new ForwardAxis(DoubleLinkAxis.ConvertTree((Axis)(ast.Input)), false)); } else { this.fAxisArray.Add(new ForwardAxis(DoubleLinkAxis.ConvertTree(ast), false)); } continue; } if (!IsDescendantOrSelf(stepAst)) { throw new XmlSchemaException(Res.Sch_ICXpathError, xPath); } try { stepAst = (Axis)(stepAst.Input); } catch { throw new XmlSchemaException(Res.Sch_ICXpathError, xPath); } if ((stepAst == null) || (!IsSelf(stepAst)) || (stepAst.Input != null)) { throw new XmlSchemaException(Res.Sch_ICXpathError, xPath); } // trim top "." if it's not the only node if (IsSelf(ast) && (ast.Input != null)) { this.fAxisArray.Add(new ForwardAxis(DoubleLinkAxis.ConvertTree((Axis)(ast.Input)), true)); } else { this.fAxisArray.Add(new ForwardAxis(DoubleLinkAxis.ConvertTree(ast), true)); } } }
// constructor internal AxisElement(DoubleLinkAxis node, int depth) { this.curNode = node; this.rootDepth = this.curDepth = depth; this.isMatch = false; }