c# – 带有IXmlSerializable的命名空间前缀

对使用的适当装饰器或可能需要的任何设计感到困惑.序列化实现IXmlSerializable的类是否有办法在XmlRoot元素中包含命名空间及其前缀?

例如,类定义.

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",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>

第二个是XmlSerializer的输出,如果删除了类的IXmlSerializable实现并取消注释XmlElement装饰器.我知道返回的两个Xml文档都是有效的,但尝试删除冗余的命名空间声明会很好.我认为这样的事情是可能的,因为IXmlSerializable旨在更好地控制类的序列化/反序列化方式.

更新:一个非常有趣的答案建议修改XmlWriterSettings!看起来这会通过修改NamespaceHandling属性来清除所有内容.但是,这仍然会导致为每个成员重写名称空间.完整的序列化代码如下:

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添加一个String属性.有效!
void IXmlSerializable.WriteXml(XmlWriter writer) {
        writer.WriteAttributeString("xmlns:me","member.com");
        writer.WriteAttributeString("xmlns","www.123.com");
        writer.WriteElementString(XML_MEMBER_PREFIX,Member3);
    }

并从类中删除[XmlRoot(“Classy”,Namespace = XML_NS)]和xmlsn属性.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...