XML 序列化和命名空间前缀
Posted
技术标签:
【中文标题】XML 序列化和命名空间前缀【英文标题】:XML Serialization and namespace prefixes 【发布时间】:2011-01-21 08:08:16 【问题描述】:我正在寻找一种使用 C# 的方法,我可以将一个类序列化为 XML 并添加一个命名空间,但定义该命名空间将使用的前缀。
最终我正在尝试生成以下 XML:
<myNamespace:Node xmlns:myNamespace="...">
<childNode>something in here</childNode>
</myNamespace:Node>
我知道DataContractSerializer
和XmlSerializer
都可以添加命名空间,但它们似乎会在内部生成前缀,而我无法控制。我可以使用这些序列化程序中的任何一个来控制它吗(我可以使用它们中的任何一个)?
如果我无法控制命名空间的生成,我是否需要编写自己的 XML 序列化程序,如果是这样,最好的方法是什么?
【问题讨论】:
【参考方案1】:要控制命名空间别名,请使用XmlSerializerNamespaces
。
[XmlRoot("Node", Namespace="http://flibble")]
public class MyType
[XmlElement("childNode")]
public string Value get; set;
static class Program
static void Main()
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("myNamespace", "http://flibble");
XmlSerializer xser = new XmlSerializer(typeof(MyType));
xser.Serialize(Console.Out, new MyType(), ns);
如果您需要在运行时更改命名空间,您可以另外使用XmlAttributeOverrides
。
【讨论】:
+1 但我可以建议进行编辑以明确 .Add 方法中的第一个参数是设置前缀的神奇之处。在我查看 MSDN 文档之前,我并不清楚答案。 公平地假设 DataContractSerializer 没有等效项吗? (只是想保持我的选择开放) @Slace - 是的,我相信可以安全地假设没有 DCS 的等价物。归根结底,DCS 并不打算让您对输出有太多控制(如果您想控制 xml,请使用XmlSerializer
- 这是它的工作)。
有什么办法可以用这样的类属性来做到这一点:[XmlRoot("Node", Namespace="http://flibble", NamespacePrefix="myNamespace")]
?
@uzay95 是的,MSDN 上有一个例子:msdn.microsoft.com/en-us/library/dzxwk3ez(v=vs.110).aspx【参考方案2】:
当使用从类型具有命名空间的模式中生成的代码时,此命名空间覆盖适用于根级别,但不同类型中的标签将具有与类关联的命名空间。
我有一个场合需要使用两个不同的生成类,但根据我正在与之交谈的服务器有不同的名称空间(不要问不在我的控制之下)。
我尝试了这里提供的所有覆盖,最后放弃并使用了一种实际上效果很好的蛮力方法。我所做的是序列化为字符串。然后使用 string.replace 更改命名空间,然后使用 stringwriter 从字符串发布流。响应相同 - 捕获到字符串 - 操作命名空间,然后从字符串编写器反序列化字符串。
它可能并不优雅或使用所有花哨的覆盖,但它完成了工作。
【讨论】:
我遇到了类似的问题,我的解决方案是将""
命名空间显式分配给XmlElementAttribute
值中的类中的所有属性,然后仅为父类添加覆盖需要的时候。我正在使用我无法控制的第 3 方解决方案,并且拒绝更改他们的流程,因为“我们的其他客户都没有这个问题”【参考方案3】:
我从another thread 来到这里,看起来“重复”,但在我看来不是。
我在那里回答,但不是很清楚,所以让我在这里再回答一次。
如果你的目标是这样做:
<sample xmlns:sample="urn:sample:ns">
<something>value<something>
<sample:somethingelse>value2</sample:somethingelse>
<new_root xmlns:newns="url:new:ns">
<newns:item1>sample1</newns:item1>
</new_root>
</sample>
我确实为你找到了解决方案:)。
您需要做的是在“new_root”类中添加这样的命名空间声明。
[XmlNamespaceDeclarations]
public XmlSerializerNamespaces newns;
并在您的 item1 类中添加以下装饰以使用您的命名空间
[XmlElement("item1", Namespace = "url:new:ns")]
【讨论】:
这些都不适用于 ROOT 节点;巧合的是,这正是 OP 所要求的。 嗨,Christian,是的,正如我在帖子中所写,我将答案放在这里是因为其他线程(面临不同的问题,我同意)被标记为重复,抱歉,如果我不是对此还不够清楚,但我的目的是帮助从另一个线程到达的人,此外,当 OP 已经得到回答时。希望这能澄清一点以上是关于XML 序列化和命名空间前缀的主要内容,如果未能解决你的问题,请参考以下文章
在不修改 C# XSD 类的情况下向 XML 序列化添加前缀和命名空间
如何在 .NET 中的反序列化期间指定 XML 序列化属性以支持命名空间前缀?
简单的 XML 框架:元素列表中的字符串在序列化时没有命名空间前缀