【问题标题】:Attribute XmlNamespaceDeclarations is ignored during XML serializationXML 序列化期间忽略属性 XmlNamespaceDeclarations
【发布时间】:2016-05-26 20:21:57
【问题描述】:

我尝试用自定义命名空间序列化一个对象。类是这样的:

[XmlRoot("Root", Namespace = "myNamespace")]
public partial class MyClass
{
    public MyClass()
    {
        this.Xmlns = new XmlSerializerNamespaces();
        this.Xmlns.Add(string.Empty, "myNamespace");
    }

    [XmlNamespaceDeclarations()]
    public XmlSerializerNamespaces Xmlns = null;
}

这是序列化它的代码:

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
serializer.Serialize(xmlWriter, obj);

预期的结果是

<Root xmlns="myNamespace" />

但是它仍然有 xmlns:xsi 和 xmlns:xsd 属性:

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="myNamespace" />

当我使用serializer.Serialize(xmlWriter, obj, obj.Xmlns) 进行序列化时,结果是正确的。

为什么序列化程序会忽略 XmlNamespaceDeclarations 属性?它不应该自动从中获取名称空间声明吗?如何在序列化类中定义命名空间?

提前致谢!

【问题讨论】:

    标签: c# xml serialization xml-namespaces


    【解决方案1】:

    为什么序列化程序会忽略 XmlNamespaceDeclarations 属性? 它不应该自动从中获取名称空间声明吗?

    实际上,Serializer 所做的是不是 忽略您的XmlNamespaceDeclarations,而是添加它们到默认的内部@987654327 @。

    默认情况下,XmlWriter 中已经嵌入了一些 prefixes-namespaces pairs(或者为了简单起见,我会简单地调用 namespaces)。它们就是你所看到的:

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" //note the lovely pairs here
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    

    因此,如果你使用XmlWriter,你必须忍受它的default namespaces,不幸的是它不会暴露给外部用户。而且,为了让事情“更糟”(实际上,并没有那么糟,但我试着把它放在上下文中),它不知何故不允许你用它做任何事情。

    唯一与namespace 相关的XmlWriter 属性是NamespaceHandling,它只能设置为删除重复 namespaces 或保留它们。这意味着,只有当您以某种方式(相当神奇地)为您的 serializable class 声明 duplicate namespaces 时,该属性才有用:

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    

    尽管如此,XmlWriter 仍然有一些“好”的东西,您可以通过设置省略 XmlDeclaration:

    OmitXmlDeclaration = true;
    

    当您创建XmlWriterSettings 并使用设置初始化您的XmlWriter 时

    简而言之,我们不能指望XmlWriter 通过删除它的default namespaces 来为我们做好事——它根本做不到。

    因此,我们必须向Serializer 获取解决方案


    如何在序列化类中定义命名空间?

    信不信由你,它和你已经做过的一模一样!

    overloading 方法 Serialize(XmlWriter, Object, XmlSerializerNamespaces) 就是为此目的而设计的。当你调用它时:

    serializer.Serialize(xmlWriter, obj, obj.Xmlns);
    

    它替换 default namespaces + your namespaces 只有 your namespaces

    如果使用Serialize(XmlWriter, Object) 重载,Serializer 所做的是将XmlWriter 和Object 中的所有namespaces 取出,然后写入XML 文件。这样你就得到了所有的namespaces:默认的和你的。

    这可能是因为XmlWriter 也(在内部)将XmlNamespaceScope 应用为XmlNamespaceScope.All,而您又一次对此无能为力。

    但是当您使用Serialize(XmlWriter, Object, XmlSerializerNamespaces) 时,实际上是告诉Serializer 只使用您指定的XmlSerializerNamespaces。所以,它做了正确的事!

    换句话说,您所做的已经是在Xml 文件中获取所需命名空间的“官方”方式。

    除此之外,您还可以根据需要将多个 namespaces 放入您的 XML 文件,只需使用任意多次 Xmlns.Add(prefix, ns)。

    因此,您已经为您的目的做了正确的事情。我只是想解释为什么会这样。

    【讨论】:

    • 好的,可以替换命名空间。那么如何从输出中删除命名空间呢?我不想要它们或不需要它们。
    【解决方案2】:

    您将无法对您的序列化课程做任何特别的事情 - 这是一个已知问题。此处建议了各种解决方法:

    XmlSerializer: remove unnecessary xsi and xsd namespaces

    How to serialize an object to XML without getting xmlns="..."?

    xml serialization - remove namespace

    【讨论】:

    • 但是我不需要任何特别的东西。我只希望在类中声明的命名空间生效。
    猜你喜欢
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    相关资源
    最近更新 更多