C# 将对象序列化为 XmlDocument

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/781442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 00:55:15  来源:igfitidea点击:

Serialize object to XmlDocument

c#xml-serializationxmldocument

提问by Neil Barnwell

In order to return useful information in SoapException.Detailfor an asmx web service, I took an idea from WCF and created a fault class to contain said useful information. That fault object is then serialised to the required XmlNodeof a thrown SoapException.

为了SoapException.Detail为 asmx Web 服务返回有用的信息,我从 WCF 中获取了一个想法,并创建了一个错误类来包含所述有用的信息。然后将该错误对象序列化为所需XmlNode的 throw SoapException

I'm wondering whether I have the best code to create the XmlDocument- here is my take on it:

我想知道我是否有最好的代码来创建XmlDocument- 这是我的看法:

var xmlDocument = new XmlDocument();
var serializer = new XmlSerializer(typeof(T));
using (var stream = new MemoryStream())
{
    serializer.Serialize(stream, theObjectContainingUsefulInformation);
    stream.Flush();
    stream.Seek(0, SeekOrigin.Begin);

    xmlDocument.Load(stream);
}

Is there a better way of doing this?

有没有更好的方法来做到这一点?

UPDATE:I actually ended up doing the following, because unless you wrap the XML in a <detail>xml element, you get a SoapHeaderExceptionat the client end:

更新:我实际上最终做了以下事情,因为除非你将 XML 包装在一个<detail>xml 元素中,否则你会SoapHeaderException在客户端得到一个:

var serialiseToDocument = new XmlDocument();
var serializer = new XmlSerializer(typeof(T));
using (var stream = new MemoryStream())
{
    serializer.Serialize(stream, e.ExceptionContext);
    stream.Flush();
    stream.Seek(0, SeekOrigin.Begin);

    serialiseToDocument.Load(stream);
}

// Remove the xml declaration
serialiseToDocument.RemoveChild(serialiseToDocument.FirstChild);

// Memorise the node we want
var serialisedNode = serialiseToDocument.FirstChild;

// and wrap it in a <detail> element
var rootNode = serialiseToDocument.CreateNode(XmlNodeType.Element, "detail", "");
rootNode.AppendChild(serialisedNode);

UPDATE 2:Given John Saunders excellent answer, I've now started using the following:

更新 2:鉴于 John Saunders 的出色回答,我现在开始使用以下内容:

private static void SerialiseFaultDetail()
{
    var fault = new ServiceFault
                    {
                        Message = "Exception occurred",
                        ErrorCode = 1010
                    };

    // Serialise to the XML document
    var detailDocument = new XmlDocument();
    var nav = detailDocument.CreateNavigator();

    if (nav != null)
    {
        using (XmlWriter writer = nav.AppendChild())
        {
            var ser = new XmlSerializer(fault.GetType());
            ser.Serialize(writer, fault);
        }
    }

    // Memorise and remove the element we want
    XmlNode infoNode = detailDocument.FirstChild;
    detailDocument.RemoveChild(infoNode);

    // Move into a root <detail> element
    var rootNode = detailDocument.AppendChild(detailDocument.CreateNode(XmlNodeType.Element, "detail", ""));
    rootNode.AppendChild(infoNode);

    Console.WriteLine(detailDocument.OuterXml);
    Console.ReadKey();
}

采纳答案by John Saunders

EDIT: Creates output inside of detail element

编辑:在 detail 元素内创建输出

public class MyFault
{
    public int ErrorCode { get; set; }
    public string ErrorMessage { get; set; }
}

public static XmlDocument SerializeFault()
{
    var fault = new MyFault
                    {
                        ErrorCode = 1,
                        ErrorMessage = "This is an error"
                    };

    var faultDocument = new XmlDocument();
    var nav = faultDocument.CreateNavigator();
    using (var writer = nav.AppendChild())
    {
        var ser = new XmlSerializer(fault.GetType());
        ser.Serialize(writer, fault);
    }

    var detailDocument = new XmlDocument();
    var detailElement = detailDocument.CreateElement(
        "exc", 
        SoapException.DetailElementName.Name,
        SoapException.DetailElementName.Namespace);
    detailDocument.AppendChild(detailElement);
    detailElement.AppendChild(
        detailDocument.ImportNode(
            faultDocument.DocumentElement, true));
    return detailDocument;
}