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>

我知道DataContractSerializerXmlSerializer 都可以添加命名空间,但它们似乎会在内部生成前缀,而我无法控制。我可以使用这些序列化程序中的任何一个来控制它吗(我可以使用它们中的任何一个)?

如果我无法控制命名空间的生成,我是否需要编写自己的 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 序列化添加前缀和命名空间

XML 属性未获取命名空间前缀

如何在 .NET 中的反序列化期间指定 XML 序列化属性以支持命名空间前缀?

简单的 XML 框架:元素列表中的字符串在序列化时没有命名空间前缀

XML 和 XSL 中的前缀命名空间处理由 XML 解析器返回错误

接收解析 XML:未绑定前缀错误和属性缺少 Android 命名空间前缀