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; } }
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 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; } }