XML序列化命名空间 [英] XML Serialization Namespaces

查看:126
本文介绍了XML序列化命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 < XML版本=1.0编码=UTF-8 ?> 
< ClassToSerialize类型=客户NAME =有些名称的xmlns:XSI =htt​​p://www.w3.org/2001/XMLSchema-instanceXSI:=的schemaLocationHTTP:// WWW。 123.org/namespace C:\Schema\ClassToSerialize.xsd
的xmlns:测试=http://www.Test.org/的xmlns =http://www.nrf-arts.org /命名空间>
<地址>
< 1号线>地址1< /线路1>
< 2号线>地址2< /线路2>
< /地址>
< / ClassToSerialize>



什么我得到是这样的XML:

 <?XML版本=1.0编码=UTF-8>?; 
< ClassToSerialize的xmlns:XSI =htt​​p://www.w3.org/2001/XMLSchema-instance的xmlns:的schemaLocation =htt​​p://www.123.org/namespace C:\Schema\\ \\ClassToSerialize.xsd
的xmlns:测试=http://www.Test.org/的xmlns:的xmlns =http://www.nrf-arts.org/namespaceTYPE =客户名称=有些名称>
<地址>
< 1号线>地址1< /线路1>
< 2号线>地址2< /线路2>
< /地址>
< / ClassToSerialize>



主要区别是:



  1。的xmlns:=的schemaLocation必须XSI:=的schemaLocation 
2的xmlns:的xmlns =必须的xmlns =
3.属性命令,我宁愿属性被提出的命名空间属性之前(这是不是一个大问题,只是很高兴有)

目前我在做什么是替代值序列化的字符串在1安培; 2上面我想要的值,即工作的技巧,但我怀疑有修改的空间代码,在这一点上做到这一点的方法吗?



下面是代码我使用,我怎样才能改变GetNameSpace()做什么,我需要点1安培; 2,也可以我重新排序的属性:

 公共部分Form1类:表格
{
酒店的公共Form1中()
{
的InitializeComponent();
}

私人无效的button1_Click(对象发件人,EventArgs五)
{
ClassToSerialize将myInstance =新ClassToSerialize();
myInstance.Type =客户;
myInstance.Name =有些名称;
myInstance.AddressField =新的地址(地址1,地址2);

字符串sString = SerializeObject&所述; ClassToSerialize>(将myInstance,GetNameSpace());

//哈克达到什么样的,我从命名空间$ B $希望B sString = sString.Replace(的xmlns:=的schemaLocation,XSI:=的schemaLocation);
sString = sString.Replace(的xmlns:的xmlns =,的xmlns =);
}

私人XmlSerializerNamespaces GetNameSpace()
{
XmlSerializerNamespaces xsNS =新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(测试,http://www.Test.org/);

返回xsNS;
}

公共静态字符串SerializeObject< X>(X toSerialize,XmlSerializerNamespaces XML命名空间)
{
串strRetVal =;

{
的XmlSerializer XmlSerializer的=新的XmlSerializer(toSerialize.GetType());
的StringWriter的TextWriter =新的StringWriter();使用

(StringWriter的作家=新Utf8StringWriter())
{
xmlSerializer.Serialize(作家,toSerialize,XML命名空间);
strRetVal = writer.ToString();
}
}
赶上(异常前)
{
串STRERROR = ex.ToString();
}

返回strRetVal;
}
}

公共类Utf8StringWriter:StringWriter的
{
公众覆盖编码编码
{
{返回编码。 UTF8; }
}
}

公共类ClassToSerialize
{
[XmlAttribute()]
公共字符串类型{搞定;组; }

[XmlAttribute()]
公共字符串名称{;组; }

[的XmlElement(地址)]
公共广播AddressField {搞定;组; }
}

公共类地址
{
[XmlElement的,默认值()]
公共字符串一号线{搞定;组; }

[XmlElement的,默认值()]
公共字符串2号线{搞定;组; }

公共广播()
{

}

公共广播(串L1,串L2)
{
线路1 = L1;
= 2号线L2;
}
}


解决方案

  1. 您可以添加 XSI:的schemaLocation 通过沿的如何XSI的schemaLocation添加到根C#对象的XmlSerializer - 但使用一个属性,而不是一个场。如果你使用一个字段,你实际上将添加到您的内存类的足迹


  2. 要定义一个默认的命名空间的xmlns =。 http://www.nrf-arts.org/namespace,您可以应用的 [XmlRoot(ClassToSerialize,命名空间=http://www.nrf-arts.org/namespace )] 您的 ClassToSerialize 分配一个 XmlRootAttribute 重写,并将它传递给的XmlSerializer 构造。一定要缓存,如果你选择后者串行。


  3. 除了实施的 的IXmlSerializable ,这是有点累赘,我不知道它可以控制与的XmlSerializer 属性顺序。然而,XML规范声明属性规范的起始标签的顺序或空元素标签不显著,所以我建议不要担心。




因此,下面应该做的伎俩。请注意我搬到你的 GetNameSpace() ClassToSerialize 并更名为 GetAdditionalNamespaces()

  [XmlRoot(ClassToSerialize,命名空间=htt​​p://www.nrf-arts.org /命名空间)] 
公共类ClassToSerialize
{
公共静态XmlSerializerNamespaces GetAdditionalNamespaces()
{
XmlSerializerNamespaces xsNS =新XmlSerializerNamespaces();

xsNS.Add(XSI,http://www.w3.org/2001/XMLSchema-instance);
xsNS.Add(测试,http://www.Test.org/);

返回xsNS;
}

[XmlAttribute(的schemaLocation,命名空间=htt​​p://www.w3.org/2001/XMLSchema-instance)]
公共字符串XSDSchemaLocation
{
得到
{
返回http://www.123.org/namespace C:\\Schema\\ClassToSerialize.xsd
}

{
//什么都不做 - 假的财产。
}
}

[XmlAttribute()]
公共字符串类型{搞定;组; }

[XmlAttribute()]
公共字符串名称{;组; }

[的XmlElement(地址)]
公共广播AddressField {搞定;组; }
}


I have an issue with the Namespaces that my code is producing. What I'd Like is the XML below:

<?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>

What I'm getting is this 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>

Main differences are:

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)

Currently what I am doing is to replace the values in the serialized string in 1 & 2 above with the values I want, a hack that works but i suspect there is a way to modify the namespace code to do this at that point?

Here is the code I am using, how can i change GetNameSpace() to do what I need in points 1 & 2, also can i re-order the attributes?:

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. You can add xsi:schemaLocation by adding a synthetic property along the lines of the answer in How to add xsi schemalocation to root c # object XmlSerializer -- but use a property instead of a field. If you use a field you will actually add to the footprint of your class in memory.

  2. To define a default namespace xmlns="http://www.nrf-arts.org/namespace", you can apply [XmlRoot("ClassToSerialize", Namespace="http://www.nrf-arts.org/namespace")] to your ClassToSerialize or allocate an XmlRootAttribute override and pass it to the XmlSerializer constructor. Be sure to cache the serializer if you do the latter.

  3. Other than implementing IXmlSerializable, which is somewhat burdensome, I don't know if it's possible to control the attribute order with XmlSerializer. However, the XML specification states "the order of attribute specifications in a start-tag or empty-element tag is not significant", so I recommend not worrying about it.

Thus the following should do the trick. Note I moved your GetNameSpace() inside ClassToSerialize and renamed it 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; }
}

这篇关于XML序列化命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆