XML序列化命名空间 [英] XML Serialization Namespaces
问题描述
我有我的代码是生产的命名空间的问题。我想是下面的XML:
< XML版本=1.0编码=UTF-8 ?>
< ClassToSerialize类型=客户NAME =有些名称的xmlns:XSI =http://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 =http://www.w3.org/2001/XMLSchema-instance的xmlns:的schemaLocation =http://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;
}
}
-
您可以添加
XSI:的schemaLocation
通过沿的如何XSI的schemaLocation添加到根C#对象的XmlSerializer - 但使用一个属性,而不是一个场。如果你使用一个字段,你实际上将添加到您的内存类的足迹 -
要定义一个默认的命名空间
的xmlns =。 http://www.nrf-arts.org/namespace
,您可以应用的[XmlRoot(ClassToSerialize,命名空间=http://www.nrf-arts.org/namespace )]
您的ClassToSerialize
或分配一个XmlRootAttribute
重写,并将它传递给的XmlSerializer
构造。一定要缓存,如果你选择后者串行。 -
除了实施的
的IXmlSerializable
,这是有点累赘,我不知道它可以控制与的XmlSerializer
属性顺序。然而,XML规范声明属性规范的起始标签的顺序或空元素标签不显著,所以我建议不要担心。
因此,下面应该做的伎俩。请注意我搬到你的 GetNameSpace()
在 ClassToSerialize
并更名为 GetAdditionalNamespaces()
:
[XmlRoot(ClassToSerialize,命名空间=http://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,命名空间=http://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;
}
}
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.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 yourClassToSerialize
or allocate anXmlRootAttribute
override and pass it to theXmlSerializer
constructor. Be sure to cache the serializer if you do the latter.Other than implementing
IXmlSerializable
, which is somewhat burdensome, I don't know if it's possible to control the attribute order withXmlSerializer
. 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屋!