如何为 IXmlSerialized 类型添加命名空间前缀

2023-11-21

我有以下类定义

[XmlRoot(ElementName = "person",Namespace = "MyNamespace")]
public class Person : IXmlSerializable
{
    public string FirstName { get; set; }
    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces Namespaces
    {
        get
        {
            var xmlSerializerNamespaces = new XmlSerializerNamespaces();
            xmlSerializerNamespaces.Add("My", "MyNamespace");
            return xmlSerializerNamespaces;
        }
    }

    public string LastName { get; set; }

    public XmlSchema GetSchema()
    {
        return null;
    }

    /// <exception cref="NotSupportedException"/>
    public void ReadXml(XmlReader reader)
    {
        throw new NotSupportedException();
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteElementString("firstName",FirstName);
        writer.WriteElementString("lastName", LastName);
    }
}

我想将其序列化My:MyNamespace 的前缀,所以当我调用代码时

var xmlSerializer = new XmlSerializer(typeof(Person));
var person = new Person
            { FirstName = "John",LastName = "Doe"};            
xmlSerializer.Serialize(Console.Out, person, person.Namespaces);

我期望以下输出:

<?xml version="1.0" encoding="ibm850"?>
<My:person xmlns:My="MyNamespace">
    <My:firstName>John</My:firstName>
    <My:lastName>Doe</My:lastName>
</My:person>

但我得到以下输出:

<?xml version="1.0" encoding="ibm850"?>
<person xmlns="MyNamespace">
  <firstName>John</firstName>
  <lastName>Doe</lastName>
</person>

我知道当我使用时编写前缀是有效的可序列化属性属性并且不继承自IXml可序列化,但我的项目中的类要复杂得多,我无法使用默认的 XmlSerializer。


The XmlSerializertype 不提供任何现成的东西来处理这个问题。
如果你确实需要使用XmlSerializer,你最终会得到一个定制的XmlSerializer实施,还不太开放扩展。因此,下面的实现更多的是一个概念证明,只是为了给您一个想法或一个起点。
为了简洁起见,我省略了任何错误处理,只关注Person你的问题中的班级。仍然需要做一些工作来处理任何嵌套的复杂属性。

As the Serialize方法不是virtual我们必须跟踪他们。主要思想是将所有重载定向到具有自定义实现的单个重载。

由于定制,我们必须在Person在通过指定要应用的 xml 命名空间为其属性编写 xml 元素时,可以使用 xml 来定义类。

下面的代码

PrefixedXmlSerializer xmlSerializer = new PrefixedXmlSerializer(typeof(Person));
Person person = new Person { 
    FirstName = "John", 
    LastName = "Doe" 
    };
xmlSerializer.Serialize(Console.Out, person, person.Namespaces);

结果是

<My:person xmlns:My="MyNamespace">
    <My:firstName>John</My:firstName>
    <My:lastName>Doe</My:lastName>
</My:person>

由你来考虑这一切是否可以接受。
到底,<My:person xmlns:My="MyNamespace"> equals <person xmlns="MyNamespace">.

Person

[XmlRoot(ElementName = "person", Namespace = NAMESPACE)]
public class Person : IXmlSerializable
{
    private const string NAMESPACE = "MyNamespace";

    public string FirstName { get; set; }

    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces Namespaces
    {
        get
        {
            var xmlSerializerNamespaces = new XmlSerializerNamespaces();
            xmlSerializerNamespaces.Add("My", NAMESPACE);                
            return xmlSerializerNamespaces;
        }
    }

    public string LastName { get; set; }

    public XmlSchema GetSchema()
    {
        return null;
    }

    /// <exception cref="NotSupportedException"/>
    public void ReadXml(XmlReader reader)
    {
        throw new NotSupportedException();
    }   

    public void WriteXml(XmlWriter writer)
    {
        // Specify the xml namespace.
        writer.WriteElementString("firstName", NAMESPACE, FirstName);
        writer.WriteElementString("lastName", NAMESPACE, LastName);
    }
}

带前缀的 XmlSerializer

public class PrefixedXmlSerializer : XmlSerializer
{
    XmlRootAttribute _xmlRootAttribute;


    public PrefixedXmlSerializer(Type type) : base(type)
    {
        this._xmlRootAttribute = type.GetCustomAttribute<XmlRootAttribute>();        
    }


    public new void Serialize(TextWriter textWriter, Object o, XmlSerializerNamespaces namespaces)
    {
        // Out-of-the-box implementation.
        XmlTextWriter xmlTextWriter = new XmlTextWriter(textWriter);
        xmlTextWriter.Formatting = Formatting.Indented;
        xmlTextWriter.Indentation = 2;

        // Call the shadowed version. 
        this.Serialize(xmlTextWriter, o, namespaces, null, null);
    }


    public new void Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
    {
        // Lookup the xml namespace and prefix to apply.
        XmlQualifiedName[] xmlNamespaces = namespaces.ToArray();                                
        XmlQualifiedName xmlRootNamespace =
            xmlNamespaces
                .Where(ns => ns.Namespace == this._xmlRootAttribute.Namespace)
                .FirstOrDefault();

        // Write the prefixed root element with its xml namespace declaration.
        xmlWriter.WriteStartElement(xmlRootNamespace.Name, this._xmlRootAttribute.ElementName, xmlRootNamespace.Namespace);            

        // Write the xml namespaces; duplicates will be taken care of automatically.
        foreach (XmlQualifiedName xmlNamespace in xmlNamespaces)
        {
            xmlWriter.WriteAttributeString("xmlns", xmlNamespace.Name , null, xmlNamespace.Namespace);
        }

        // Write the actual object xml.
        ((IXmlSerializable)o).WriteXml(xmlWriter);

        xmlWriter.WriteEndElement();       
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为 IXmlSerialized 类型添加命名空间前缀 的相关文章

随机推荐

  • 如何将空字符串解析为 None?

    将空字符串解析为空字符串的惯用方法是什么 None而不是一个Some let handle Option
  • Logback - 如何让每个记录器记录到单独的日志文件?

    我的应用程序有很多 EJB 当前的定制 Logger 实现创建一个像这样的记录器 私有静态 Logger logger Logger getInstance SERVICE NAME 并且日志记录将写入文件 路径 SERVICE NAME
  • 如何同步(使原子化)从两个进程写入一个文件?

    我有两个进程 每个进程都写入大量数据缓冲区 并且我想控制同步这些进程对一个文件的写入 进程1写入缓冲区A 包括 A1 A2 A3 进程2写入缓冲区B 包括 B1 B2 B3 当我们使用write 将这些缓冲区写入磁盘到同一文件的系统调用 一
  • 缩放和平移画布后鼠标坐标不匹配

    我对 javascript 和 canvas 非常陌生 我有一个程序应该检测椭圆路径上的动画元素 它后来形成一棵树 但这是我链接到 jsfiddle 的基本结构 它在没有缩放或平移的情况下工作正常 但一旦我尝试缩放或平移 鼠标坐标就会失控
  • 带有复制构造函数的enable_if

    我在尝试std enable if第一次并挣扎 任何指导将不胜感激 作为一个玩具示例 这是一个简单的静态vector类 我想为其定义一个复制构造函数 但行为取决于向量的相对大小 只需将数据复制到更小或相同大小的向量中 将数据复制到更大的向量
  • sigaction 和 signal 有什么区别?

    我正要向我们这里的应用程序添加一个额外的信号处理程序 我注意到作者使用了sigaction 设置其他信号处理程序 我本来打算用signal 为了遵循约定 我应该使用sigaction 但如果我从头开始写作 我应该选择哪个 Use sigac
  • 打印在地图中时不打印,Python

    primes 2 3 5 7 prime numbers map lambda x print x primes 它不打印任何内容 这是为什么 我试过了 sys stdout write x 也是 但也不起作用 Since lambda x
  • 字符串文字的最大长度?

    我正在尝试创建一个长字符串文字 并将其存储在 std string 中 如果我创建一个最多大约 2600 个字符的文字 则所有内容都可以正常打印 如果超过这个符号数量 我只会打印一些随机的垃圾字符 我一直使用 C 标准作为指导 环境限制被指
  • 与平台无关的字体​​目录?

    Windows macOS 和 Linux 上的字体存储在哪里 这是那些 简单 的问题之一 根据需要可以有一个过度的解决方案 Linux 发行版不使用任何特定的字体管理 使得不同 Linux 风格的字体不一致 非常可配置 并且受到许多因素
  • PHP 搜索字符串(带通配符)

    有没有办法在字符串中添加通配符 我之所以问这个问题 是因为目前我有一个函数可以在两个子字符串之间搜索子字符串 即抓取 我的狗有跳蚤 这句话中 我的 和 有跳蚤 之间的内容 从而得到 狗 function get string between
  • 没有周末的日差

    我想计算用户输入的总天数差异 例如当用户输入 start date 2012 09 06 and end date 2012 09 11 现在我正在使用这段代码来找出差异 count abs strtotime start date str
  • 如何在 C# 项目中使用 Windows 命令行安装 Nuget 包?

    我已经下载了 NuGet 版本 5 1 0 并尝试使用 cmd 安装其中一个包 log4net 它失败了 下面是错误 Microsoft Windows 版本 10 0 19042 1348 c Microsoft Corporation
  • Glassfish 中外部库的放置位置

    我使用 Netbeans 7 创建了一个 JSF2 项目 并成功将其部署在 Glassfish 3 1 上 不过 ear 文件已经变得相当大 6 5mb 其中大部分由外部 jar 文件 如 apache commons solrj prim
  • npm install openssl 在 Windows 10 上失败

    我在 Win10 的 Node js 命令窗口中运行以下命令 它失败了 有人知道如何解决它吗 我正在运行 Node js v7 3 0 C Users haozhang gt npm install openssl C Users haoz
  • WordPress,pre_get_posts 中有多个meta_key

    是否可以添加两个meta key s in pre get posts 我当前的查询 query gt set s query gt set meta key cat adresse stadtteil query gt set meta
  • 类别方法可以被重写吗? IOS

    我正在尝试计划如何向某些对象的所有实例添加一些方法 我认为向父对象 UIViewController 添加一个类别可以满足我想要做的事情 但是我可以重写以这种方式添加的方法吗 大多数情况下 子类将使用默认方法 但我确实知道我需要至少重写该方
  • 在 Android 操作系统中使用 SSLSocket 的 TLS 连接速度很慢

    我正在开发一个 Android 应用程序 它使用 SSLSocket 连接到服务器 这是我正在使用的代码 Connect if socket null socket isClosed socket isConnected if socket
  • “var self = this”方法背后的基本原理是什么? [复制]

    这个问题在这里已经有答案了 可能的重复 JS var self this 当查看用 JavaScript 编写的任意代码 例如在 GitHub 上 时 许多开发人员使用var self this然后使用self代替this来引用当前对象 这
  • 为什么 Hash#select 和 Hash#reject 将键传递给一元块?

    我的理解是Hash select and Hash reject每个都传递一个键及其值的数组 key value 作为每次迭代的单个块参数 您可以使用隐式破坏性赋值直接在块内单独选取它们 a 1 b 2 select k v k a gt
  • 如何为 IXmlSerialized 类型添加命名空间前缀

    我有以下类定义 XmlRoot ElementName person Namespace MyNamespace public class Person IXmlSerializable public string FirstName ge