예제 #1
0
    private Patch CreatePatch( XmlNode sourceNode, XmlElement diffgramElement )
	{
        Debug.Assert( sourceNode.NodeType == XmlNodeType.Document ||
                      sourceNode.NodeType == XmlNodeType.DocumentFragment );

        Patch patch = new Patch( sourceNode );

        _sourceRootNode = sourceNode;

        // create patch for <xmldiff> node children
        CreatePatchForChildren( sourceNode, 
                                diffgramElement,
                                patch );
        return patch;
    }
예제 #2
0
        private void Patch(ref XmlNode sourceNode, XmlDocument diffDoc)
        {
            XmlElement diffgramEl = diffDoc.DocumentElement;

            if (diffgramEl.LocalName != "xmldiff" || diffgramEl.NamespaceURI != XmlDiff.NamespaceUri)
            {
                XmlPatchError.Error(XmlPatchError.ExpectingDiffgramElement);
            }

            XmlNamedNodeMap diffgramAttributes = diffgramEl.Attributes;
            XmlAttribute    srcDocAttr         = (XmlAttribute)diffgramAttributes.GetNamedItem("srcDocHash");

            if (srcDocAttr == null)
            {
                XmlPatchError.Error(XmlPatchError.MissingSrcDocAttribute);
            }

            ulong hashValue = 0;

            try
            {
                hashValue = ulong.Parse(srcDocAttr.Value);
            }
            catch
            {
                XmlPatchError.Error(XmlPatchError.InvalidSrcDocAttribute);
            }

            XmlAttribute optionsAttr = (XmlAttribute)diffgramAttributes.GetNamedItem("options");

            if (optionsAttr == null)
            {
                XmlPatchError.Error(XmlPatchError.MissingOptionsAttribute);
            }

            // parse options
            XmlDiffOptions xmlDiffOptions = XmlDiffOptions.None;

            try
            {
                xmlDiffOptions = XmlDiff.ParseOptions(optionsAttr.Value);
            }
            catch
            {
                XmlPatchError.Error(XmlPatchError.InvalidOptionsAttribute);
            }

            _ignoreChildOrder = ((int)xmlDiffOptions & (int)XmlDiffOptions.IgnoreChildOrder) != 0;

            // Calculate the hash value of source document and check if it agrees with
            // of srcDocHash attribute value.
            if (!XmlDiff.VerifySource(sourceNode, hashValue, xmlDiffOptions))
            {
                XmlPatchError.Error(XmlPatchError.SrcDocMismatch);
            }

            // Translate diffgram & Apply patch
            if (sourceNode.NodeType == XmlNodeType.Document)
            {
                Patch patch = CreatePatch(sourceNode, diffgramEl);

                // create temporary root element and move all document children under it
                XmlDocument sourceDoc = (XmlDocument)sourceNode;
                XmlElement  tempRoot  = sourceDoc.CreateElement("tempRoot");
                XmlNode     child     = sourceDoc.FirstChild;
                while (child != null)
                {
                    XmlNode tmpChild = child.NextSibling;

                    if (child.NodeType != XmlNodeType.XmlDeclaration &&
                        child.NodeType != XmlNodeType.DocumentType)
                    {
                        sourceDoc.RemoveChild(child);
                        tempRoot.AppendChild(child);
                    }

                    child = tmpChild;
                }
                sourceDoc.AppendChild(tempRoot);

                // Apply patch
                XmlNode temp = null;
                patch.Apply(tempRoot, ref temp);

                // remove the temporary root element
                if (sourceNode.NodeType == XmlNodeType.Document)
                {
                    sourceDoc.RemoveChild(tempRoot);
                    Debug.Assert(tempRoot.Attributes.Count == 0);
                    while ((child = tempRoot.FirstChild) != null)
                    {
                        tempRoot.RemoveChild(child);
                        sourceDoc.AppendChild(child);
                    }
                }
            }
            else if (sourceNode.NodeType == XmlNodeType.DocumentFragment)
            {
                Patch   patch = CreatePatch(sourceNode, diffgramEl);
                XmlNode temp  = null;
                patch.Apply(sourceNode, ref temp);
            }
            else
            {
                // create fragment with sourceNode as its only child
                XmlDocumentFragment fragment               = sourceNode.OwnerDocument.CreateDocumentFragment();
                XmlNode             previousSourceParent   = sourceNode.ParentNode;
                XmlNode             previousSourceSibbling = sourceNode.PreviousSibling;

                if (previousSourceParent != null)
                {
                    previousSourceParent.RemoveChild(sourceNode);
                }
                if (sourceNode.NodeType != XmlNodeType.XmlDeclaration)
                {
                    fragment.AppendChild(sourceNode);
                }
                else
                {
                    fragment.InnerXml = sourceNode.OuterXml;
                }

                Patch   patch = CreatePatch(fragment, diffgramEl);
                XmlNode temp  = null;
                patch.Apply(fragment, ref temp);

                XmlNodeList childNodes = fragment.ChildNodes;
                if (childNodes.Count != 1)
                {
                    XmlPatchError.Error(XmlPatchError.InternalErrorMoreThanOneNodeLeft, childNodes.Count.ToString());
                }

                sourceNode = childNodes.Item(0);
                fragment.RemoveAll();
                if (previousSourceParent != null)
                {
                    previousSourceParent.InsertAfter(sourceNode, previousSourceSibbling);
                }
            }
        }