XML 序列化期间忽略属性 XmlNamespaceDeclarations

Attribute XmlNamespaceDeclarations is ignored during XML serialization

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

[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 属性?它不应该自动从中获取名称空间声明吗?如何在序列化 class 中定义命名空间?

提前致谢!

您将无法对您的序列化 class 执行任何特殊操作 - 这是一个已知问题。这里提出了各种解决方法:

XmlSerializer: remove unnecessary xsi and xsd namespaces

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

xml serialization - remove namespace

Why does serializer ignore that XmlNamespaceDeclarations attribute? Shouldn't it automatically take the namespace declarations from it?

实际上,Serializer 所做的是 而不是 忽略 你的 XmlNamespaceDeclarations 它们添加到默认的内部 XmlWriter namespaces 中。

默认情况下,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,不幸的是,它不会暴露给外部用户。而且,为了让事情变得 "worse"(实际上,并没有那么糟糕,但我试着把它放在上下文中),它以某种方式不允许你用它做任何事情。

唯一与 namespace 有关的 XmlWriter 属性 是 NamespaceHandling,它只能设置为删除 duplicate namespaces 或保留它们。这意味着,属性 只有在您以某种方式 - 相当神奇地 - 为您的 serializable class:

声明 duplicate namespaces 时才有用
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 

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

OmitXmlDeclaration = true;

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

简而言之,我们不能希望 XmlWriter 通过删除它 default namespaces 来为我们做好事 - 它根本不可能。

因此,我们必须Serializer得到解决方案


How can I define namespaces inside serialized class?

信不信由你,这和您已经做过的完全一样

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

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

仅用替换default namespaces + your namespacesyour namespaces

如果您使用 Serialize(XmlWriter, Object) 重载,Serializer 所做的是获取 XmlWriterObject 中的所有 namespaces然后写入 XML 文件。因此,您在那里获得了所有 namespaces 默认值和您的

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

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

换句话说,您所做的已经是在 Xml 文件中获取所需名称空间的 "official" 方法。

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

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