// This method replaces an EncryptedData element with the decrypted sequence of bytes public void ReplaceData(XmlElement inputElement, byte[] decryptedData) { if (inputElement == null) { throw new ArgumentNullException("inputElement"); } if (decryptedData == null) { throw new ArgumentNullException("decryptedData"); } XmlNode parent = inputElement.ParentNode; if (parent.NodeType == XmlNodeType.Document) { // We're replacing the root element, but we can't just wholesale replace the owner // document's InnerXml, since we need to preserve any other top-level XML elements (such as // comments or the XML entity declaration. Instead, create a new document with the // decrypted XML, import it into the existing document, and replace just the root element. XmlDocument importDocument = new XmlDocument(); importDocument.PreserveWhitespace = true; string decryptedString = m_encoding.GetString(decryptedData); using (StringReader sr = new StringReader(decryptedString)) { using (XmlReader xr = XmlReader.Create(sr, Utils.GetSecureXmlReaderSettings(m_xmlResolver))) { importDocument.Load(xr); } } XmlNode importedNode = inputElement.OwnerDocument.ImportNode(importDocument.DocumentElement, true); parent.RemoveChild(inputElement); parent.AppendChild(importedNode); } else { XmlNode dummy = parent.OwnerDocument.CreateElement(parent.Prefix, parent.LocalName, parent.NamespaceURI); try { parent.AppendChild(dummy); // Replace the children of the dummy node with the sequence of bytes passed in. // The string will be parsed into DOM objects in the context of the parent of the EncryptedData element. dummy.InnerXml = m_encoding.GetString(decryptedData); // Move the children of the dummy node up to the parent. XmlNode child = dummy.FirstChild; XmlNode sibling = inputElement.NextSibling; XmlNode nextChild = null; while (child != null) { nextChild = child.NextSibling; parent.InsertBefore(child, sibling); child = nextChild; } } finally { // Remove the dummy element. parent.RemoveChild(dummy); } // Remove the EncryptedData element parent.RemoveChild(inputElement); } }