【问题标题】:XML Serialization and namespace prefixesXML 序列化和命名空间前缀
【发布时间】:2011-01-21 08:08:16
【问题描述】:

我正在寻找一种使用 C# 的方法,我可以将一个类序列化为 XML 并添加一个命名空间,但定义该命名空间将使用的前缀。

最终我正在尝试生成以下 XML:

<myNamespace:Node xmlns:myNamespace="...">
  <childNode>something in here</childNode>
</myNamespace:Node>

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

如果我无法控制命名空间的生成,我是否需要编写自己的 XML 序列化程序,如果是这样,最好的方法是什么?

【问题讨论】:

    标签: c# xml-serialization datacontractserializer xmlserializer


    【解决方案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 已经得到回答时。希望这能澄清一点
    猜你喜欢
    • 2013-05-02
    • 1970-01-01
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    相关资源
    最近更新 更多