对于使用的适当装饰器或可能需要的任何设计,有些困惑。序列化正在实现IXmlSerializable的类时,是否可以在XmlRoot元素中包含 namespace 及其前缀?
例如类定义。
using System;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
[XmlRoot("Classy", Namespace = XML_NS)]
public class TestClass : IXmlSerializable
{
private const string XML_PREFIX = ""; // default namespace
private const string XML_NS = "www.123.com";
private const string XML_MEMBER_PREFIX = "me";
private const string XML_MEMBER_NS = "member.com";
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces xmlsn {
get {
XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
xsn.Add(XML_PREFIX, XML_NS);
xsn.Add(XML_MEMBER_PREFIX, XML_MEMBER_NS);
return xsn;
}
}
void IXmlSerializable.WriteXml(XmlWriter writer) {
writer.WriteElementString(XML_MEMBER_PREFIX, "Member1.5",
XML_MEMBER_NS, Member1);
writer.WriteElementString(XML_MEMBER_PREFIX, "Member2.5",
XML_MEMBER_NS, Member2.ToString());
writer.WriteElementString(XML_PREFIX, "Member3.5", XML_NS, Member3);
}
//[XmlElement(ElementName = "Member1.5", Namespace = XML_MEMBER_NS)]
public string Member1 {
get { return "init"; }
set { ; }
}
//[XmlElement(ElementName = "Member2.5", Namespace = XML_MEMBER_NS)]
public int Member2 {
get { return 3; }
set { ; }
}
//[XmlElement(ElementName = "Member3.5", Namespace = XML_NS)]
public string Member3 {
get { return "default namespace"; }
set { ; }
}
// ignore ReadXml/GetSchema
XmlSchema IXmlSerializable.GetSchema() { return null; }
void IXmlSerializable.ReadXml(XmlReader reader) { return; }
}
通过以下方式序列化时:
TestClass tc = new TestClass();
XmlSerializer ser = new XmlSerializer(typeof(TestClass));
ser(writer, tc, tc.xmlsn); // just a plain XmlWriter to Console.Out
输出是
<?xml version="1.0" encoding="utf-8"?>
<Classy xmlns="www.123.com">
<me:Member1.5 xmlns:me="member.com">init</me:Member1.5>
<me:Member2.5 xmlns:me="member.com">3</me:Member2.5>
<Member3.5>default namespace</Member3.5>
</Classy>
我期望的输出是:
<?xml version="1.0" encoding="utf-8"?>
<Classy xmlns:me="member.com" xmlns="www.123.com">
<me:Member1.5>init</me:Member1.5>
<me:Member2.5>3</me:Member2.5>
<Member3.5>default namespace</Member3.5>
</Classy>
如果删除了该类的IXmlSerializable实现,并且取消了XmlElement装饰器的注释,则第二个是XmlSerializer的输出。我知道返回的两个Xml文档都是有效的,但是最好尝试删除冗余的 namespace 声明。我认为这是可能的,因为IXmlSerializable是为了更好地控制类的序列化/反序列化。
更新:一个非常有趣的答案建议修改XmlWriterSettings!看起来这将通过修改NamespaceHandling属性清除所有内容。但是,这仍然会导致为每个成员重写 namespace 。完整的序列化代码如下:
XmlSerializer ser = new XmlSerializer(typeof(TestClass));
TestClass tc = new TestClass();
XmlWriterSettings xmlSet = new XmlWriterSettings();
xmlSet.Encoding = System.Text.Encoding.UTF8;
xmlSet.Indent = true;
xmlSet.NamespaceHandling = NamespaceHandling.OmitDuplicates;
XmlWriter writer = XmlWriter.Create(Console.Out, xmlSet);
ser.Serialize(writer, tc); // with/without tc.xmlsn same result
writer.Flush();
writer.Close();
最佳答案
我只是向WriteXml添加了一个字符串属性。有效!
void IXmlSerializable.WriteXml(XmlWriter writer) {
writer.WriteAttributeString("xmlns:me", "member.com");
writer.WriteAttributeString("xmlns", "www.123.com");
writer.WriteElementString(XML_MEMBER_PREFIX, "Member1.5",
XML_MEMBER_NS, Member1);
writer.WriteElementString(XML_MEMBER_PREFIX, "Member2.5",
XML_MEMBER_NS, Member2.ToString());
writer.WriteElementString(XML_PREFIX, "Member3.5", XML_NS, Member3);
}
并从该类中删除
[XmlRoot("Classy", Namespace = XML_NS)]
和xmlsn
属性。