c# - XML 序列化命名空间

标签 c# xml xml-namespaces

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

<?xml version="1.0" encoding="utf-8"?>
<ClassToSerialize Type="Customer" Name="Some Name" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.123.org/namespace C:\Schema\ClassToSerialize.xsd" 
xmlns:Test="http://www.Test.org/" xmlns="http://www.nrf-arts.org/namespace">
  <Address>
    <Line1>Addr1</Line1>
    <Line2>Addr2</Line2>
  </Address>
</ClassToSerialize>

我得到的是这个 XML:

<?xml version="1.0" encoding="utf-8"?>
<ClassToSerialize xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:schemaLocation="http://www.123.org/namespace C:\Schema\ClassToSerialize.xsd"
 xmlns:Test="http://www.Test.org/" xmlns:xmlns="http://www.nrf-arts.org/namespace" Type="Customer" Name="Some Name">
  <Address>
    <Line1>Addr1</Line1>
    <Line2>Addr2</Line2>
  </Address>
</ClassToSerialize>

主要区别是:

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,但我怀疑有一种方法可以修改 namespace 代码来在此时执行此操作?

这是我正在使用的代码,我如何更改 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<ClassToSerialize>(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>(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. 您可以按照 How to add xsi schemalocation to root c # object XmlSerializer 中的答案添加合成属性来添加 xsi:schemaLocation -- 但使用属性而不是字段。如果您使用一个字段,您实际上会增加您的类在内存中的占用空间。

  2. 要定义默认命名空间 xmlns="http://www.nrf-arts.org/namespace",您可以申请 [XmlRoot("ClassToSerialize", Namespace="http://www.nrf-arts.org/namespace")]到您的 ClassToSerializeallocate an XmlRootAttribute override and pass it to the XmlSerializer constructor .如果您执行后者,请务必缓存序列化程序。

  3. 除了实现 IXmlSerializable ,有点繁琐,不知道能不能用XmlSerializer来控制属性顺序。但是,XML 规范指出 "the order of attribute specifications in a start-tag or empty-element tag is not significant" ,所以我建议不要担心。

因此下面应该可以解决问题。请注意,我将您的 GetNameSpace() 移到了 ClassToSerialize 中并将其重命名为 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; }
}

关于c# - XML 序列化命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27530334/

相关文章:

c# - 如何简单的访问网盘,读写文件?

java - 使用 jsoup 解析具有任何 namespace 的文本的 xml 节点

r - 在rentrez中使用entrez_fetch解析PubMed XML

Xml 命名空间破坏了我的 xpath!

xml - 如何使用 XMLNS 属性转换元素

c# - Linq:在进行投影时设置属性

c# - 如何在子项上添加 where 子句并正确映射它

c# - Html helper 'available' 如何用于 MVC 中的所有 View ?

java - 基于xpath值创建动态xml树

.net - 如何使用 XDocument.XPathEvaluate 处理空命名空间?