gpt4 book ai didi

xml-serialization - 如何为 IXmlSerializable 类型添加命名空间前缀

转载 作者:行者123 更新时间:2023-12-03 23:58:19 25 4
gpt4 key购买 nike

我有以下类定义

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

我想用 序列化它我的: 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>

我知道当我使用 时,写前缀是有效的SerializableAttribute 属性而不是继承自 IXmlSerializable ,但我在项目中的类要复杂得多,我不能使用默认的 XmlSerializer。

最佳答案

XmlSerializer type 不提供任何开箱即用的东西来处理这个问题。
如果你真的需要使用XmlSerializer ,你最终会得到一个自定义 XmlSerializer实现,它不是很开放扩展。出于这个原因,下面的实现更像是一个概念证明,只是为了给你一个想法或一个起点。
为简洁起见,我省略了任何错误处理,仅关注 Person在你的问题中上课。还有一些工作要做来处理任何嵌套的复杂属性。

Serialize方法不是 virtual我们将不得不给他们留下阴影。主要思想是将所有重载定向到具有自定义实现的单个重载。

由于自定义,我们必须在 Person 中更加明确通过指定要应用的 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">等于 <person xmlns="MyNamespace"> .



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

PrefixedXmlSerializer

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

关于xml-serialization - 如何为 IXmlSerializable 类型添加命名空间前缀,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51590112/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com