Example #1
0
        private void PreprocessDiffgram(XmlDocument diffgramDoc)
        {
            // read xmldiff options
            XmlAttribute attr = (XmlAttribute)diffgramDoc.DocumentElement.Attributes.GetNamedItem("options");

            if (attr == null)
            {
                throw new Exception("Missing 'options' attribute in the diffgram.");
            }
            string         optionsAttr = attr.Value;
            XmlDiffOptions options     = XmlDiff.ParseOptions(optionsAttr);

            _bIgnoreChildOrder = (((int)options & (int)(XmlDiffOptions.IgnoreChildOrder)) > 0);
            _bIgnoreComments   = (((int)options & (int)(XmlDiffOptions.IgnoreComments)) > 0);
            _bIgnorePI         = (((int)options & (int)(XmlDiffOptions.IgnorePI)) > 0);
            _bIgnoreWhitespace = (((int)options & (int)(XmlDiffOptions.IgnoreWhitespace)) > 0);
            _bIgnoreNamespaces = (((int)options & (int)(XmlDiffOptions.IgnoreNamespaces)) > 0);
            _bIgnorePrefixes   = (((int)options & (int)(XmlDiffOptions.IgnorePrefixes)) > 0);
            _bIgnoreDtd        = (((int)options & (int)(XmlDiffOptions.IgnoreDtd)) > 0);

            if (_bIgnoreNamespaces)
            {
                _bIgnorePrefixes = true;
            }

            // read descriptors
            XmlNodeList children = diffgramDoc.DocumentElement.ChildNodes;
            IEnumerator e        = children.GetEnumerator();

            while (e.MoveNext())
            {
                XmlElement desc = e.Current as XmlElement;
                if (desc != null && desc.LocalName == "descriptor")
                {
                    int opid = int.Parse(desc.GetAttribute("opid"));
                    OperationDescriptor.Type type;
                    switch (desc.GetAttribute("type"))
                    {
                    case "move":             type = OperationDescriptor.Type.Move; break;

                    case "prefix change":    type = OperationDescriptor.Type.PrefixChange; break;

                    case "namespace change": type = OperationDescriptor.Type.NamespaceChange; break;

                    default:
                        throw new Exception("Invalid descriptor type.");
                    }
                    OperationDescriptor od = new OperationDescriptor(opid, type);
                    _descriptors[opid] = od;
                }
            }
        }
Example #2
0
        private void PreprocessDiffgram(XmlDocument diffgramDoc)
        {
            var namedItem = (XmlAttribute)diffgramDoc.DocumentElement.Attributes.GetNamedItem("options");

            if (namedItem == null)
            {
                throw new Exception("Missing 'options' attribute in the diffgram.");
            }
            var options = XmlDiff.ParseOptions(namedItem.Value);

            this._bIgnoreChildOrder = (options & XmlDiffOptions.IgnoreChildOrder) > XmlDiffOptions.None;
            this._bIgnoreComments   = (options & XmlDiffOptions.IgnoreComments) > XmlDiffOptions.None;
            this._bIgnorePI         = (options & XmlDiffOptions.IgnorePI) > XmlDiffOptions.None;
            this._bIgnoreWhitespace = (options & XmlDiffOptions.IgnoreWhitespace) > XmlDiffOptions.None;
            this._bIgnoreNamespaces = (options & XmlDiffOptions.IgnoreNamespaces) > XmlDiffOptions.None;
            this._bIgnorePrefixes   = (options & XmlDiffOptions.IgnorePrefixes) > XmlDiffOptions.None;
            this._bIgnoreDtd        = (options & XmlDiffOptions.IgnoreDtd) > XmlDiffOptions.None;
            if (this._bIgnoreNamespaces)
            {
                this._bIgnorePrefixes = true;
            }
            foreach (var childNode in diffgramDoc.DocumentElement.ChildNodes)
            {
                var xmlElement = childNode as XmlElement;
                if (xmlElement is XmlElement && xmlElement.LocalName == "descriptor")
                {
                    var opid = int.Parse(xmlElement.GetAttribute("opid"));
                    OperationDescriptor.Type type;
                    switch (xmlElement.GetAttribute("type"))
                    {
                    case "move":
                        type = OperationDescriptor.Type.Move;
                        break;

                    case "prefix change":
                        type = OperationDescriptor.Type.PrefixChange;
                        break;

                    case "namespace change":
                        type = OperationDescriptor.Type.NamespaceChange;
                        break;

                    default:
                        throw new Exception("Invalid descriptor type.");
                    }
                    var operationDescriptor = new OperationDescriptor(opid, type);
                    this._descriptors[opid] = operationDescriptor;
                }
            }
        }
Example #3
0
        private void Patch(ref XmlNode sourceNode, XmlDocument diffDoc)
        {
            var documentElement = diffDoc.DocumentElement;

            if (documentElement.LocalName != "xmldiff" || documentElement.NamespaceURI != "http://schemas.microsoft.com/xmltools/2002/xmldiff")
            {
                XmlPatchError.Error("Invalid XDL diffgram. Expecting xd:xmldiff as a root element with namespace URI 'http://schemas.microsoft.com/xmltools/2002/xmldiff'.");
            }
            XmlNamedNodeMap attributes = documentElement.Attributes;
            var             namedItem1 = (XmlAttribute)attributes.GetNamedItem("srcDocHash");

            if (namedItem1 == null)
            {
                XmlPatchError.Error("Invalid XDL diffgram. Missing srcDocHash attribute on the xd:xmldiff element.");
            }
            ulong hashValue = 0;

            try
            {
                hashValue = ulong.Parse(namedItem1.Value);
            }
            catch
            {
                XmlPatchError.Error("Invalid XDL diffgram. The srcDocHash attribute has an invalid value.");
            }
            var namedItem2 = (XmlAttribute)attributes.GetNamedItem("options");

            if (namedItem2 == null)
            {
                XmlPatchError.Error("Invalid XDL diffgram. Missing options attribute on the xd:xmldiff element.");
            }
            var options = XmlDiffOptions.None;

            try
            {
                options = XmlDiff.ParseOptions(namedItem2.Value);
            }
            catch
            {
                XmlPatchError.Error("Invalid XDL diffgram. The options attribute has an invalid value.");
            }
            this._ignoreChildOrder = (options & XmlDiffOptions.IgnoreChildOrder) != XmlDiffOptions.None;
            if (!XmlDiff.VerifySource(sourceNode, hashValue, options))
            {
                XmlPatchError.Error("The XDL diffgram is not applicable to this XML document; the srcDocHash value does not match.");
            }
            if (sourceNode.NodeType == XmlNodeType.Document)
            {
                var     patch       = this.CreatePatch(sourceNode, documentElement);
                var     xmlDocument = (XmlDocument)sourceNode;
                var     element     = xmlDocument.CreateElement("tempRoot");
                XmlNode nextSibling;
                for (var xmlNode = xmlDocument.FirstChild; xmlNode != null; xmlNode = nextSibling)
                {
                    nextSibling = xmlNode.NextSibling;
                    if (xmlNode.NodeType != XmlNodeType.XmlDeclaration && xmlNode.NodeType != XmlNodeType.DocumentType)
                    {
                        xmlDocument.RemoveChild(xmlNode);
                        element.AppendChild(xmlNode);
                    }
                }
                xmlDocument.AppendChild(element);
                XmlNode currentPosition = null;
                patch.Apply(element, ref currentPosition);
                if (sourceNode.NodeType != XmlNodeType.Document)
                {
                    return;
                }
                xmlDocument.RemoveChild(element);
                XmlNode firstChild;
                while ((firstChild = element.FirstChild) != null)
                {
                    element.RemoveChild(firstChild);
                    xmlDocument.AppendChild(firstChild);
                }
            }
            else if (sourceNode.NodeType == XmlNodeType.DocumentFragment)
            {
                var     patch           = this.CreatePatch(sourceNode, documentElement);
                XmlNode currentPosition = null;
                patch.Apply(sourceNode, ref currentPosition);
            }
            else
            {
                var documentFragment = sourceNode.OwnerDocument.CreateDocumentFragment();
                var parentNode       = sourceNode.ParentNode;
                var previousSibling  = sourceNode.PreviousSibling;
                parentNode?.RemoveChild(sourceNode);
                if (sourceNode.NodeType != XmlNodeType.XmlDeclaration)
                {
                    documentFragment.AppendChild(sourceNode);
                }
                else
                {
                    documentFragment.InnerXml = sourceNode.OuterXml;
                }
                var     patch           = this.CreatePatch(documentFragment, documentElement);
                XmlNode currentPosition = null;
                patch.Apply(documentFragment, ref currentPosition);
                var childNodes = documentFragment.ChildNodes;
                if (childNodes.Count != 1)
                {
                    XmlPatchError.Error("Internal Error. {0} nodes left after patch, expecting 1.", childNodes.Count.ToString());
                }
                sourceNode = childNodes.Item(0);
                documentFragment.RemoveAll();
                parentNode?.InsertAfter(sourceNode, previousSibling);
            }
        }
Example #4
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);
                }
            }
        }