带有IXmlSerializable的命名空间前缀 [英] Namespace Prefixes with IXmlSerializable

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

问题描述

在正确使用的装饰器上混淆了位,或者可能需要任何设计.序列化正在实现IXmlSerializable的类时,是否可以在XmlRoot元素中包含名称空间及其前缀?

Bit confused on the proper decorators to use, or whatever design might be necessary. When serializing a class which is implementing IXmlSerializable is there a way to include the namespace and its prefix in the XmlRoot element?

例如类定义.

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; }
}

通过以下方式序列化时:

When serialized via:

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文档都是有效的,但是最好尝试删除冗余的名称空间声明.我认为这是可能的,因为IXmlSerializable可以更好地控制如何对您的类进行序列化/反序列化.

The second is the output of XmlSerializer if the class's implementation of IXmlSerializable is removed and you uncomment the XmlElement decorators. I know both of the Xml documents returned are valid, but it would be nice to try and remove the redundant namespace declarations. I would assume such a thing is possible, since IXmlSerializable is meant to give greater control over how your class is serialized/deserialized.

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

Update: A very interesting answer suggested modifying the XmlWriterSettings! It looked like this would clear everything up by modifying the NamespaceHandling property. However this still results in the namespaces being rewritten for each member. Full serialization code below:

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添加了一个字符串属性.奏效了!

I simply added an String Attribute to WriteXml. It worked!

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 属性.

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

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