XML序列化命名空间

我的代码产生的命名空间有问题。 我想要的是下面的XML:

  
Addr1 Addr2

我得到的是这个XML:

   
Addr1 Addr2

主要区别是:

 1. xmlns:schemaLocation= needs to be xsi:schemaLocation= 2. xmlns:xmlns= needs to be xmlns= 3. Attributes Order, I would prefer the Attributes to be presented before the namespace attributes (This is not a big Issue, just nice to have) 

目前我正在做的是用上面的1和2中的序列化字符串中的值替换我想要的值,一个有效的hack但我怀疑有一种方法可以修改命名空间代码来执行此操作吗?

这是我正在使用的代码,如何更改GetNameSpace()以在第1点和第2点执行我需要的操作,也可以重新排序属性?:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { ClassToSerialize myInstance = new ClassToSerialize(); myInstance.Type = "Customer"; myInstance.Name = "Some Name"; myInstance.AddressField = new Address("Addr1", "Addr2"); String sString = SerializeObject(myInstance, GetNameSpace()); //Hack to achieve what I want from namespaces sString = sString.Replace("xmlns:schemaLocation=", "xsi:schemaLocation="); sString = sString.Replace("xmlns:xmlns=", "xmlns="); } private XmlSerializerNamespaces GetNameSpace() { XmlSerializerNamespaces xsNS = new XmlSerializerNamespaces(); xsNS.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance"); xsNS.Add("xmlns", "http://www.nrf-arts.org/namespace"); xsNS.Add("schemaLocation", "http://www.123.org/namespace C:\\Schema\\ClassToSerialize.xsd"); xsNS.Add("Test", "http://www.Test.org/"); return xsNS; } public static string SerializeObject(X toSerialize, XmlSerializerNamespaces xmlNameSpace) { string strRetVal = ""; try { XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType()); StringWriter textWriter = new StringWriter(); using (StringWriter writer = new Utf8StringWriter()) { xmlSerializer.Serialize(writer, toSerialize, xmlNameSpace); strRetVal = writer.ToString(); } } catch (Exception ex) { string strError = ex.ToString(); } return strRetVal; } } public class Utf8StringWriter : StringWriter { public override Encoding Encoding { get { return Encoding.UTF8; } } } public class ClassToSerialize { [XmlAttribute()] public string Type { get; set; } [XmlAttribute()] public string Name { get; set; } [XmlElement("Address")] public Address AddressField { get; set; } } public class Address { [XmlElement, DefaultValue("")] public string Line1 { get; set; } [XmlElement, DefaultValue("")] public string Line2 { get; set; } public Address() { } public Address(string L1, string L2) { Line1 = L1; Line2 = L2; } } 

  1. 您可以通过在如何将xsi schemalocation添加到root c#object XmlSerializer中的答案行添加合成属性来添加xsi:schemaLocation – 但是使用属性而不是字段。 如果你使用一个字段,你实际上会在内存中添加你的类的足迹。

  2. 要定义默认命名空间xmlns="http://www.nrf-arts.org/namespace" ,可以应用[XmlRoot("ClassToSerialize", Namespace="http://www.nrf-arts.org/namespace")]ClassToSerialize或分配XmlRootAttribute覆盖并将其传递给XmlSerializer构造函数 。 如果您执行后者,请务必缓存序列化程序。

  3. 除了实现IXmlSerializable ,这有点麻烦,我不知道是否可以使用XmlSerializer控制属性顺序。 但是,XML规范声明“开始标记或空元素标记中的属性规范的顺序并不重要” ,因此我建议不要担心它。

因此,以下应该做的伎俩。 注意我在GetNameSpace()移动了GetNameSpace()并将其重命名为GetAdditionalNamespaces()

 [XmlRoot("ClassToSerialize", Namespace="http://www.nrf-arts.org/namespace")] public class ClassToSerialize { public static XmlSerializerNamespaces GetAdditionalNamespaces() { XmlSerializerNamespaces xsNS = new XmlSerializerNamespaces(); xsNS.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance"); xsNS.Add("Test", "http://www.Test.org/"); return xsNS; } [XmlAttribute("schemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")] public string XSDSchemaLocation { get { return "http://www.123.org/namespace C:\\Schema\\ClassToSerialize.xsd"; } set { // Do nothing - fake property. } } [XmlAttribute()] public string Type { get; set; } [XmlAttribute()] public string Name { get; set; } [XmlElement("Address")] public Address AddressField { get; set; } }