具有多个命名空间的DataContractSerializer

我正在使用DataContractSerializer将对象序列化为XML。 主要对象是带有命名空间“ http://personaltrading.test.com/ ”的SecurityHolding,它包含一个名为Amount的属性,它是一个名为“ http://core.test.com ”的类。 当我将其序列化为XML时,我得到以下内容:

   1.05 USD  0  3681  

无论如何我可以控制d3p1前缀吗? 我做错了什么或者我应该做别的事吗?

首先,命名空间别名的选择对于格式良好的解析器没有任何区别。

但; 它必须是DataContractSerializer吗? 使用XmlSerializer ,您可以使用接受XmlSerializerNamespacesSerialize的重载。 这允许您选择和使用您使用的命名空间和别名。

最终, DataContractSerializer 并非旨在提供完整的xml控件; 这不是它的目标。 如果你想要严格的xml控件, XmlSerializer是一个更好的选择,即使它更老(并且有自己的一些细微差别/弱点)。

完整示例:

 using System; using System.Xml.Serialization; public class Amount { public const string CoreNamespace = "http://core.test.com/"; [XmlElement("Amount", Namespace=CoreNamespace)] public decimal Value { get; set; } [XmlElement("CurrencyCode", Namespace = CoreNamespace)] public string Currency { get; set; } } [XmlType("SecurityHolding", Namespace = SecurityHolding.TradingNamespace)] public class SecurityHolding { public const string TradingNamespace = "http://personaltrading.test.com/"; [XmlElement("Amount", Namespace = Amount.CoreNamespace)] public Amount Amount { get; set; } public int BrokerageId { get; set; } public string BrokerageName { get; set; } public int RecordId { get; set; } } static class Program { static void Main() { var data = new[] { new SecurityHolding { Amount = new Amount { Value = 1.05M, Currency = "USD" }, BrokerageId = 0, BrokerageName = null, RecordId = 3681 } }; var ser = new XmlSerializer(data.GetType(), new XmlRootAttribute("ArrayOfSecurityHolding") { Namespace = SecurityHolding.TradingNamespace}); var ns = new XmlSerializerNamespaces(); ns.Add("foo", Amount.CoreNamespace); ser.Serialize(Console.Out, data, ns); } } 

输出:

    1.05 USD  0 3681   

我已经解决了这个问题与Marc略有不同,可以在基类中实现。

  1. 创建新属性以定义将在数据协定中使用的其他XML命名空间。

     [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)] public sealed class NamespaceAttribute : Attribute { public NamespaceAttribute() { } public NamespaceAttribute(string prefix, string uri) { Prefix = prefix; Uri = uri; } public string Prefix { get; set; } public string Uri { get; set; } } 
  2. 将属性添加到数据协定中。

     [DataContract(Name = "SomeObject", Namespace = "http://schemas.domain.com/namespace/")] [Namespace(Prefix = "a", Uri = "http://schemas.microsoft.com/2003/10/Serialization/Arrays")] [Namespace(Prefix = "wm", Uri = "http://schemas.datacontract.org/2004/07/System.Windows.Media")] public class SomeObject : SerializableObject { private IList colors; [DataMember] [DisplayName("Colors")] public IList Colors { get { return colors; } set { colours = value; } } } 
  3. 然后在Save方法中,使用reflection来获取属性,然后将它们写入文件。

     public static void Save(SerializableObject o, string filename) { using (Stream outputStream = new FileStream(filename, FileMode.Create, FileAccess.Write)) { if (outputStream == null) throw new ArgumentNullException("Must have valid output stream"); if (outputStream.CanWrite == false) throw new ArgumentException("Cannot write to output stream"); object[] attributes; attributes = o.GetType().GetCustomAttributes(typeof(NamespaceAttribute), true); XmlWriterSettings writerSettings = new XmlWriterSettings(); writerSettings.Indent = true; writerSettings.NewLineOnAttributes = true; using (XmlWriter w = XmlWriter.Create(outputStream, writerSettings)) { DataContractSerializer s = new DataContractSerializer(o.GetType()); s.WriteStartObject(w, o); foreach (NamespaceAttribute ns in attributes) w.WriteAttributeString("xmlns", ns.Prefix, null, ns.Uri); // content s.WriteObjectContent(w, o); s.WriteEndObject(w); } } } 

我也在努力解决这个问题。 我在下面提出的解决方案不是最佳的恕我直言,但它的工作。 和上面的Marc Gravell一样,我建议使用XmlSerializer。

诀窍是在类中添加一个返回XmlSerializerNamespaces对象的字段。 必须使用XmlNamespaceDeclarations属性修饰此字段。 在类的构造函数中,添加名称空间,如下例所示。 在下面的xml中注意,根元素以及someString元素都是正确的前缀。

有关XmlSerializerNamespaces的更多信息

架构参考

 [XmlRoot(Namespace="http://STPMonitor.myDomain.com")] public class CFMessage : IQueueMessage { [XmlNamespaceDeclarations] public XmlSerializerNamespaces xmlns; [XmlAttribute("schemaLocation", Namespace=System.Xml.Schema.XmlSchema.InstanceNamespace)] public string schemaLocation = "http://STPMonitor.myDomain.com/schemas/CFMessage.xsd"; [XmlAttribute("type")] public string Type { get; set; } [XmlAttribute("username")] public string UserName { get; set; } [XmlAttribute("somestring", Namespace = "http://someURI.com")] public string SomeString = "Hello World"; public List QueueItems { get; set; } public CFMessage() { xmlns = new XmlSerializerNamespaces(); xmlns.Add("myDomain", "http://STPMonitor.myDomain.com"); xmlns.Add("xyz", "http://someURI.com"); } }   

添加“http://www.w3.org/2001/XMLSchema”命名空间:

  private static string DataContractSerialize(object obj) { StringWriter sw = new StringWriter(); DataContractSerializer serializer = new DataContractSerializer(obj.GetType()); using (XmlTextWriter xw = new XmlTextWriter(sw)) { //serializer.WriteObject(xw, obj); // // Insert namespace for C# types serializer.WriteStartObject(xw, obj); xw.WriteAttributeString("xmlns", "x", null, "http://www.w3.org/2001/XMLSchema"); serializer.WriteObjectContent(xw, obj); serializer.WriteEndObject(xw); } StringBuilder buffer = sw.GetStringBuilder(); return buffer.ToString(); }