internal static XmlNodeList SelectNodes( XmlNode rootNode, XmlNode currentParentNode, string pathDescriptor) { switch (pathDescriptor[0]) { case '*': if (pathDescriptor.Length == 1) { return(PathDescriptorParser.SelectAllChildren(currentParentNode)); } PathDescriptorParser.OnInvalidExpression(pathDescriptor); return((XmlNodeList)null); case '/': return(PathDescriptorParser.SelectAbsoluteNodes(rootNode, pathDescriptor)); case '@': if (pathDescriptor.Length < 2) { PathDescriptorParser.OnInvalidExpression(pathDescriptor); } return(pathDescriptor[1] == '*' ? PathDescriptorParser.SelectAllAttributes(currentParentNode) : PathDescriptorParser.SelectAttributes(currentParentNode, pathDescriptor)); default: return(PathDescriptorParser.SelectChildNodes(currentParentNode, pathDescriptor, 0)); } }
private static XmlNodeList SelectAbsoluteNodes(XmlNode rootNode, string path) { var pos = 1; var xmlNode = rootNode; int startPos; while (true) { startPos = pos; var childNodes = xmlNode.ChildNodes; var num = PathDescriptorParser.ReadPosition(path, ref pos); if (pos == path.Length || path[pos] == '/') { if (childNodes.Count == 0 || num < 0 || num > childNodes.Count) { PathDescriptorParser.OnNoMatchingNode(path); } xmlNode = childNodes.Item(num - 1); if (pos != path.Length) { ++pos; } else { break; } } else if (path[pos] != '-' && path[pos] != '|') { PathDescriptorParser.OnInvalidExpression(path); } else { goto label_8; } } var xmlPatchNodeList = (XmlPatchNodeList) new SingleNodeList(); xmlPatchNodeList.AddNode(xmlNode); return((XmlNodeList)xmlPatchNodeList); label_8: return(PathDescriptorParser.SelectChildNodes(xmlNode, path, startPos)); }
private static XmlNodeList SelectAttributes(XmlNode parentNode, string path) { var pos = 1; var attributes = parentNode.Attributes; var xmlPatchNodeList = (XmlPatchNodeList)null; while (true) { var name = PathDescriptorParser.ReadAttrName(path, ref pos); if (xmlPatchNodeList == null) { xmlPatchNodeList = pos != path.Length ? (XmlPatchNodeList) new MultiNodeList() : (XmlPatchNodeList) new SingleNodeList(); } var namedItem = attributes.GetNamedItem(name); if (namedItem == null) { PathDescriptorParser.OnNoMatchingNode(path); } xmlPatchNodeList.AddNode(namedItem); if (pos != path.Length) { if (path[pos] == '|') { ++pos; if (path[pos] != '@') { PathDescriptorParser.OnInvalidExpression(path); } ++pos; } else { PathDescriptorParser.OnInvalidExpression(path); } } else { break; } } return((XmlNodeList)xmlPatchNodeList); }
private static XmlNodeList SelectAllChildren(XmlNode parentNode) { var childNodes = parentNode.ChildNodes; if (childNodes.Count == 0) { PathDescriptorParser.OnNoMatchingNode("*"); return((XmlNodeList)null); } if (childNodes.Count == 1) { var xmlPatchNodeList = (XmlPatchNodeList) new SingleNodeList(); xmlPatchNodeList.AddNode(childNodes.Item(0)); return((XmlNodeList)xmlPatchNodeList); } var enumerator = childNodes.GetEnumerator(); var xmlPatchNodeList1 = (XmlPatchNodeList) new MultiNodeList(); while (enumerator.MoveNext()) { xmlPatchNodeList1.AddNode((XmlNode)enumerator.Current); } return((XmlNodeList)xmlPatchNodeList1); }
private void CreatePatchForChildren( XmlNode sourceParent, XmlElement diffgramParent, XmlPatchParentOperation patchParent) { XmlPatchOperation child = null; var xmlNode1 = diffgramParent.FirstChild; while (xmlNode1 != null) { if (xmlNode1.NodeType != XmlNodeType.Element) { xmlNode1 = xmlNode1.NextSibling; } else { var diffgramParent1 = (XmlElement)xmlNode1; XmlNodeList xmlNodeList = null; var attribute1 = diffgramParent1.GetAttribute("match"); if (attribute1 != string.Empty) { xmlNodeList = PathDescriptorParser.SelectNodes(this._sourceRootNode, sourceParent, attribute1); if (xmlNodeList.Count == 0) { XmlPatchError.Error("Invalid XDL diffgram. No node matches the path descriptor '{0}'.", attribute1); } } XmlPatchOperation newChild = null; switch (diffgramParent1.LocalName) { case "node": if (xmlNodeList.Count != 1) { XmlPatchError.Error("Invalid XDL diffgram; more than one node matches the '{0}' path descriptor on the xd:node or xd:change element.", attribute1); } var xmlNode2 = xmlNodeList.Item(0); if (this._sourceRootNode.NodeType != XmlNodeType.Document || xmlNode2.NodeType != XmlNodeType.XmlDeclaration && xmlNode2.NodeType != XmlNodeType.DocumentType) { newChild = new PatchSetPosition(xmlNode2); this.CreatePatchForChildren(xmlNode2, diffgramParent1, (XmlPatchParentOperation)newChild); break; } break; case "add": if (attribute1 != string.Empty) { var bSubtree = diffgramParent1.GetAttribute("subtree") != "no"; newChild = new PatchCopy(xmlNodeList, bSubtree); if (!bSubtree) { this.CreatePatchForChildren(sourceParent, diffgramParent1, (XmlPatchParentOperation)newChild); break; } break; } var attribute2 = diffgramParent1.GetAttribute("type"); if (attribute2 != string.Empty) { var nodeType = (XmlNodeType)int.Parse(attribute2); var flag = nodeType == XmlNodeType.Element; if (nodeType != XmlNodeType.DocumentType) { newChild = new PatchAddNode(nodeType, diffgramParent1.GetAttribute("name"), diffgramParent1.GetAttribute("ns"), diffgramParent1.GetAttribute("prefix"), flag ? string.Empty : diffgramParent1.InnerText, this._ignoreChildOrder); if (flag) { this.CreatePatchForChildren(sourceParent, diffgramParent1, (XmlPatchParentOperation)newChild); break; } break; } newChild = new PatchAddNode(nodeType, diffgramParent1.GetAttribute("name"), diffgramParent1.GetAttribute("systemId"), diffgramParent1.GetAttribute("publicId"), diffgramParent1.InnerText, this._ignoreChildOrder); break; } newChild = new PatchAddXmlFragment(diffgramParent1.ChildNodes); break; case "remove": var bSubtree1 = diffgramParent1.GetAttribute("subtree") != "no"; newChild = new PatchRemove(xmlNodeList, bSubtree1); if (!bSubtree1) { this.CreatePatchForChildren(xmlNodeList.Item(0), diffgramParent1, (XmlPatchParentOperation)newChild); break; } break; case "change": if (xmlNodeList.Count != 1) { XmlPatchError.Error("Invalid XDL diffgram; more than one node matches the '{0}' path descriptor on the xd:node or xd:change element.", attribute1); } var xmlNode3 = xmlNodeList.Item(0); newChild = xmlNode3.NodeType == XmlNodeType.DocumentType ? new PatchChange(xmlNode3, diffgramParent1.HasAttribute("name") ? diffgramParent1.GetAttribute("name") : null, diffgramParent1.HasAttribute("systemId") ? diffgramParent1.GetAttribute("systemId") : null, diffgramParent1.HasAttribute("publicId") ? diffgramParent1.GetAttribute("publicId") : null, diffgramParent1.IsEmpty ? null : diffgramParent1) : new PatchChange(xmlNode3, diffgramParent1.HasAttribute("name") ? diffgramParent1.GetAttribute("name") : null, diffgramParent1.HasAttribute("ns") ? diffgramParent1.GetAttribute("ns") : null, diffgramParent1.HasAttribute("prefix") ? diffgramParent1.GetAttribute("prefix") : null, xmlNode3.NodeType == XmlNodeType.Element ? null : diffgramParent1); if (xmlNode3.NodeType == XmlNodeType.Element) { this.CreatePatchForChildren(xmlNode3, diffgramParent1, (XmlPatchParentOperation)newChild); break; } break; case "descriptor": return; } if (newChild != null) { patchParent.InsertChildAfter(child, newChild); child = newChild; } xmlNode1 = xmlNode1.NextSibling; } } }
private static XmlNodeList SelectChildNodes( XmlNode parentNode, string path, int startPos) { var pos = startPos; var childNodes = parentNode.ChildNodes; var num1 = PathDescriptorParser.ReadPosition(path, ref pos); var xmlPatchNodeList = pos != path.Length ? (XmlPatchNodeList) new MultiNodeList() : (XmlPatchNodeList) new SingleNodeList(); while (true) { if (num1 <= 0 || num1 > childNodes.Count) { PathDescriptorParser.OnNoMatchingNode(path); } var node = childNodes.Item(num1 - 1); xmlPatchNodeList.AddNode(node); if (pos != path.Length) { if (path[pos] == '|') { ++pos; } else if (path[pos] == '-') { ++pos; var num2 = PathDescriptorParser.ReadPosition(path, ref pos); if (num2 <= 0 || num2 > childNodes.Count) { PathDescriptorParser.OnNoMatchingNode(path); } while (num1 < num2) { ++num1; node = node.NextSibling; xmlPatchNodeList.AddNode(node); } if (pos != path.Length) { if (path[pos] == '|') { ++pos; } else { PathDescriptorParser.OnInvalidExpression(path); } } else { break; } } num1 = PathDescriptorParser.ReadPosition(path, ref pos); } else { break; } } return((XmlNodeList)xmlPatchNodeList); }
private void CreatePatchForChildren(XmlNode sourceParent, XmlElement diffgramParent, XmlPatchParentOperation patchParent) { Debug.Assert(sourceParent != null); Debug.Assert(diffgramParent != null); Debug.Assert(patchParent != null); XmlPatchOperation lastPatchOp = null; XmlNode node = diffgramParent.FirstChild; while (node != null) { if (node.NodeType != XmlNodeType.Element) { node = node.NextSibling; continue; } XmlElement diffOp = (XmlElement)node; XmlNodeList matchNodes = null; string matchAttr = diffOp.GetAttribute("match"); if (matchAttr != string.Empty) { matchNodes = PathDescriptorParser.SelectNodes(_sourceRootNode, sourceParent, matchAttr); if (matchNodes.Count == 0) { XmlPatchError.Error(XmlPatchError.NoMatchingNode, matchAttr); } } XmlPatchOperation patchOp = null; switch (diffOp.LocalName) { case "node": { Debug.Assert(matchAttr != string.Empty); if (matchNodes.Count != 1) { XmlPatchError.Error(XmlPatchError.MoreThanOneNodeMatched, matchAttr); } XmlNode matchNode = matchNodes.Item(0); if (_sourceRootNode.NodeType != XmlNodeType.Document || (matchNode.NodeType != XmlNodeType.XmlDeclaration && matchNode.NodeType != XmlNodeType.DocumentType)) { patchOp = new PatchSetPosition(matchNode); CreatePatchForChildren(matchNode, diffOp, (XmlPatchParentOperation)patchOp); } break; } case "add": { // copy node/subtree if (matchAttr != string.Empty) { bool bSubtree = diffOp.GetAttribute("subtree") != "no"; patchOp = new PatchCopy(matchNodes, bSubtree); if (!bSubtree) { CreatePatchForChildren(sourceParent, diffOp, (XmlPatchParentOperation)patchOp); } } else { string type = diffOp.GetAttribute("type"); // add single node if (type != string.Empty) { XmlNodeType nodeType = (XmlNodeType)int.Parse(type); bool bElement = (nodeType == XmlNodeType.Element); if (nodeType != XmlNodeType.DocumentType) { patchOp = new PatchAddNode(nodeType, diffOp.GetAttribute("name"), diffOp.GetAttribute("ns"), diffOp.GetAttribute("prefix"), bElement ? string.Empty : diffOp.InnerText, _ignoreChildOrder); if (bElement) { CreatePatchForChildren(sourceParent, diffOp, (XmlPatchParentOperation)patchOp); } } else { patchOp = new PatchAddNode(nodeType, diffOp.GetAttribute("name"), diffOp.GetAttribute("systemId"), diffOp.GetAttribute("publicId"), diffOp.InnerText, _ignoreChildOrder); } } // add blob else { Debug.Assert(diffOp.ChildNodes.Count > 0); patchOp = new PatchAddXmlFragment(diffOp.ChildNodes); } } break; } case "remove": { Debug.Assert(matchAttr != string.Empty); bool bSubtree = diffOp.GetAttribute("subtree") != "no"; patchOp = new PatchRemove(matchNodes, bSubtree); if (!bSubtree) { Debug.Assert(matchNodes.Count == 1); CreatePatchForChildren(matchNodes.Item(0), diffOp, (XmlPatchParentOperation)patchOp); } break; } case "change": { Debug.Assert(matchAttr != string.Empty); if (matchNodes.Count != 1) { XmlPatchError.Error(XmlPatchError.MoreThanOneNodeMatched, matchAttr); } XmlNode matchNode = matchNodes.Item(0); if (matchNode.NodeType != XmlNodeType.DocumentType) { patchOp = new PatchChange(matchNode, diffOp.HasAttribute("name") ? diffOp.GetAttribute("name") : null, diffOp.HasAttribute("ns") ? diffOp.GetAttribute("ns") : null, diffOp.HasAttribute("prefix") ? diffOp.GetAttribute("prefix") : null, (matchNode.NodeType == XmlNodeType.Element) ? null : diffOp); } else { patchOp = new PatchChange(matchNode, diffOp.HasAttribute("name") ? diffOp.GetAttribute("name") : null, diffOp.HasAttribute("systemId") ? diffOp.GetAttribute("systemId") : null, diffOp.HasAttribute("publicId") ? diffOp.GetAttribute("publicId") : null, diffOp.IsEmpty ? null : diffOp); } if (matchNode.NodeType == XmlNodeType.Element) { CreatePatchForChildren(matchNode, diffOp, (XmlPatchParentOperation)patchOp); } break; } case "descriptor": return; default: Debug.Assert(false, "Invalid element in the XDL diffgram ."); break; } if (patchOp != null) { patchParent.InsertChildAfter(lastPatchOp, patchOp); lastPatchOp = patchOp; } node = node.NextSibling; } }