序列化为xml和命名空间放置

时间:2015-09-25 15:23:46

标签: c# xml

我有一个带按钮的网页。点击后,我将我的变量传递给一个类来创建一个xml文件。我试图在名为Message的元素下添加我的命名空间。它无法正常工作。

这是我的班级:

caseA caseA = new caseA();



            caseD caseD = new caseD();
            caseD.caseA = caseA;



            addO addO = new addO();
            addO.caseD = caseD;



            Message Message = new Message();
            Message.addO = addO;

            Request  Request = new  Request();
            Request.Message = Message;

            Request.SName = "Hi";


            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add("z", "http://www.z.com");
            ns.Add("pd", "http://pd.com");
            ns.Add("a", "http://www.a.com");

    XmlSerializer serializer = new XmlSerializer(typeof(Request), new Type[] {typeof(Message), typeof(addO), typeof(caseD), typeof(caseA)});
            StreamWriter writer = new StreamWriter(Server.MapPath("~/images/test.xml"));
            serializer.Serialize(writer, Request, ns);

这是我的按钮事件:

<?xml version="1.0" encoding="utf-8"?>
<Request xmlns:a="http://www.a.com">
  <SName>hi</SName>

  <Message>
    <addO xmlns="http://pd.com">
      <a:caseD>
        <caseA xmlns="http://www.z.com">

        </caseA>
      </a:caseD>
    </addO>
  </Message>
</Request>

我用XML得到这个:

  <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Request>

<SName>Hi</SName>

    <Message>
        <pd:addO
xmlns:a="http://www.a.com" 
xmlns:z="http://www.z.com" 
xmlns:pd="http://pd.com">
            <a:caseD>
                <z:caseA>

                </z:caseA>
            </a:caseD>
        </pd:addO>
    </Message>
</Request>

我需要名称空间只在Message元素下:

openrowset

1 个答案:

答案 0 :(得分:0)

根元素或子元素是否具有命名空间定义无关紧要 - 您的两个XML样本在语义上是相同的。

尽管如此,如果您正在处理无法正确处理此问题的接收系统,您可以利用[XmlAnyElementAttribute]属性与XmlSerializer进行嵌套序列化,在AddO的外部序列化中嵌入Request元素的内部序列化结果(包括所需的命名空间)。

首先,您需要一些扩展方法来序列化XElement类以及其他相关实用程序:

public static class XmlExtensions
{
    public static XmlSerializerNamespaces NoStandardXmlNamespaces()
    {
        var ns = new XmlSerializerNamespaces();
        ns.Add("", ""); // Disable the xmlns:xsi and xmlns:xsd lines.
        return ns;
    }

    public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null)
    {
        using (var reader = element.CreateReader())
        {
            object result = (serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader);
            if (result is T)
                return (T)result;
        }
        return default(T);
    }

    public static XElement SerializeToXElement<T>(this T obj)
    {
        return obj.SerializeToXElement(null, NoStandardXmlNamespaces());
    }

    public static XElement SerializeToXElement<T>(this T obj, XmlSerializerNamespaces ns)
    {
        return obj.SerializeToXElement(null, ns);
    }

    public static XElement SerializeToXElement<T>(this T obj, XmlSerializer serializer, XmlSerializerNamespaces ns)
    {
        var doc = new XDocument();
        using (var writer = doc.CreateWriter())
            (serializer ?? new XmlSerializer(obj.GetType())).Serialize(writer, obj, ns);
        var element = doc.Root;
        if (element != null)
            element.Remove();
        return element;
    }

    public static T LoadFromXML<T>(this string xmlString, XmlSerializer serializer = null)
    {
        serializer = serializer ?? new XmlSerializer(typeof(T));

        T returnValue = default(T);
        using (StringReader reader = new StringReader(xmlString))
        {
            object result = serializer.Deserialize(reader);
            if (result is T)
            {
                returnValue = (T)result;
            }
        }
        return returnValue;
    }

    public static string GetXml<T>(this T obj, XmlSerializerNamespaces ns, bool? standalone)
    {
        return GetXml(obj, null, ns, standalone);
    }

    public static string GetXml<T>(T obj, XmlSerializer serializer, XmlSerializerNamespaces ns, bool? standalone)
    {
        serializer = serializer ?? new XmlSerializer(obj.GetType());
        using (var textWriter = new Utf8StringWriter())
        {
            var settings = new XmlWriterSettings() { Indent = true, IndentChars = "    " }; // For cosmetic purposes.
            using (var xmlWriter = XmlWriter.Create(textWriter, settings))
            {
                if (standalone != null)
                    xmlWriter.WriteStartDocument(standalone.Value);
                serializer.Serialize(xmlWriter, obj, ns);
            }
            return textWriter.ToString();
        }
    }

    public static string RootXmlElementName(this Type type)
    {
        var xmlRoot = type.GetCustomAttribute<XmlRootAttribute>();
        if (xmlRoot != null && !string.IsNullOrEmpty(xmlRoot.ElementName))
            return xmlRoot.ElementName;
        return type.Name;
    }
}

public class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding
    {
        get { return Encoding.UTF8; }
    }
}

接下来,按如下方式定义包括Message类的类。请注意,您的问题中的类不会编译(一些缺少类型),所以我简化了它们:

public class Request
{
    public string SName { get; set; }

    public Message Message { get; set; }
}

public static class Namespaces
{
    public const string pd = "http://pd.com";
    public const string a = "http://www.a.com";
    public const string z = "http://www.z.com";

    public static XmlSerializerNamespaces GetNamespaces()
    {
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("pd", pd);
        ns.Add("a", a);
        ns.Add("z", z);
        return ns;
    }
}

public class Message
{
    [XmlIgnore]
    public AddO AddO { get; set; }

    // Do nested serialization here
    [XmlAnyElement]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public XElement[] AddOXml
    {
        get
        {
            if (AddO == null)
                return null;
            var ns = Namespaces.GetNamespaces();
            var element = AddO.SerializeToXElement(ns);
            element.Name = element.Name.Namespace + "addO";
            return new[] { element };
        }
        set
        {
            if (value == null || value.Length == 0)
                AddO = null;
            AddO = value.Select(x => { x.Name = x.Name.Namespace + typeof(AddO).RootXmlElementName(); return x.Deserialize<AddO>(); }).FirstOrDefault();
        }
    }
}

[XmlRoot(Namespace = Namespaces.pd)]
public class AddO
{
    [XmlElement("caseD", Namespace = Namespaces.a )]
    public CaseD CaseD { get; set; }
}

public class CaseD
{
    [XmlElement("caseA", Namespace = Namespaces.z)]
    public CaseA CaseA { get; set; }
}

public class CaseA
{
    public string Value { get; set; }
}

现在,测试一下:

public class TestClass
{
    public static void Test()
    {
        var request = new Request
        {
            SName = "Hi",
            Message = new Message
            {
                AddO = new AddO
                {
                    CaseD = new CaseD { CaseA = new CaseA { Value = "Test Value" } },
                }
            }
        };
        var xml = request.GetXml(XmlExtensions.NoStandardXmlNamespaces(), true);
        Debug.WriteLine(xml);
        var request2 = xml.LoadFromXML<Request>();
        Debug.WriteLine(request2.GetXml(XmlExtensions.NoStandardXmlNamespaces(), true));

        Debug.Assert(request.Message.AddO.CaseD.CaseA.Value == request2.Message.AddO.CaseD.CaseA.Value); // No assert.
    }
}

原型fiddle。 XML输出是:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Request>
    <SName>Hi</SName>
    <Message>
        <pd:addO xmlns:z="http://www.z.com" xmlns:a="http://www.a.com" xmlns:pd="http://pd.com">
            <a:caseD>
                <z:caseA>
                    <z:Value>Test Value</z:Value>
                </z:caseA>
            </a:caseD>
        </pd:addO>
    </Message>
</Request>