public List <XPathNode> Parse(string xPath) { List <XPathNode> ret = new List <XPathNode> (); //adding // if the path doesn't if (xPath.StartsWith("/") == false && xPath.StartsWith("//") == false) { xPath = "//" + xPath; } List <Token> tokens = _lexer.Tokenize(xPath); int currentIndex = 0; while (currentIndex < tokens.Count) { //searching for ancestry XPathNode newNode = new XPathNode(); newNode.IsChild = true; if (tokens [currentIndex].Desc == "ANCESTOR") { newNode.IsChild = false; } currentIndex++; while (tokens [currentIndex].Desc == "WHITE_SPACE") { currentIndex++; } newNode.TagName = tokens [currentIndex].Content; currentIndex++; while (currentIndex < tokens.Count && tokens [currentIndex].Desc == "WHITE_SPACE") { currentIndex++; } //check for attributes if (currentIndex < tokens.Count && tokens [currentIndex].Desc == "OPEN_PREDICATE") { //maybe the input is broken and we don't have //a closing bracket while (currentIndex < tokens.Count && tokens [currentIndex].Desc != "END_PREDICATE") { currentIndex++; while (currentIndex < tokens.Count && tokens [currentIndex].Desc == "WHITE_SPACE") { currentIndex++; } //number if (tokens [currentIndex].Desc == "NUMBER") { var numberPredicate = new XPathNumberPredicate(); numberPredicate.Number = int.Parse(tokens[currentIndex].Content); newNode.predicates.Add(numberPredicate); currentIndex++; while (currentIndex < tokens.Count && tokens [currentIndex].Desc == "WHITE_SPACE") { currentIndex++; } //we have some junk in here //we gonna parse until here and bail if (tokens [currentIndex].Desc != "END_PREDICATE") { ret.Add(newNode); break; } } //attribute if (tokens [currentIndex].Desc == "ATTRIBUTE") { XPathAttribute attribute = new XPathAttribute(); attribute.Name = tokens [currentIndex].Content; newNode.predicates.Add(attribute); currentIndex++; while (currentIndex < tokens.Count && tokens [currentIndex].Desc == "WHITE_SPACE") { currentIndex++; } //maybe we have a test for existence of attribute if (tokens [currentIndex].Desc != "END_PREDICATE") { //how to compare if (tokens [currentIndex].Desc == "EQUAL") { } currentIndex++; while (currentIndex < tokens.Count && tokens [currentIndex].Desc == "WHITE_SPACE") { currentIndex++; } attribute.ValueToMatch = tokens [currentIndex].Content; currentIndex++; while (currentIndex < tokens.Count && tokens [currentIndex].Desc == "WHITE_SPACE") { currentIndex++; } if (currentIndex < tokens.Count && tokens [currentIndex].Desc == "AND") { currentIndex++; } } } } currentIndex++; } ret.Add(newNode); } return(ret); }
private List <Component> EvaluateStep(XPathNode step, List <GameObject> nodeSet, bool treatChildAsSelf = false) { List <Component> ret = new List <Component> (); HashSet <Component> added = new HashSet <Component> (); foreach (var node in nodeSet) { //get the type for the current tag Type nodeType = FindType(step.TagName); lastTypeUsed = nodeType; //couldn't find the type for this node //return null if (nodeType == null) { return(new List <Component> ()); } List <Component> results = new List <Component>(); if (step.IsChild) { if (treatChildAsSelf) { var component = node.gameObject.GetComponent(nodeType); if (component != null) { results.Add(component); } } else { //look for tag name in children for (int i = 0; i < node.transform.childCount; i++) { var child = node.transform.GetChild(i).gameObject; var component = child.GetComponent(nodeType); if (component != null) { results.Add(component); } } } } else { //look for tag name in all descendents var res = node.GetComponentsInChildren(nodeType); if (res != null) { results = res.ToList(); //remove self from the list if (!treatChildAsSelf && node.GetComponent(nodeType)) { results.Remove(node.GetComponent(nodeType)); } } } foreach (var comp in results) { //this may happen because Unity //doesn't have a root object(s) //so we need to rely on GetObjectsOfType //which return not only the root, but all objects //in a random order if (added.Contains(comp)) { continue; } ret.Add(comp); added.Add(comp); } //need to use the predicates foreach (var predicate in step.predicates) { var retGo = ret.Select(comp => comp.gameObject).ToList(); ret = predicate.Evaluate(retGo, nodeType).Select(go => go.GetComponent(nodeType)).ToList(); } } return(ret); }