我尝试使用自定义 namespace 序列化对象。这是该类的样子:

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

提前致谢!

最佳答案



实际上,Serializer的作用是而不是而不是忽略您的XmlNamespaceDeclarations,而是将它们添加到默认的内部XmlWriter namespaces中。

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

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,但不幸的是,该XmlWriter不会暴露给外部用户。而且,为了使事情变得“更糟”(实际上,还没有那么糟,但是我尝试将其放在上下文中),它以某种方式不允许您对此做任何事情。

namespace有关的唯一namespaces属性是NamespaceHandling,只能将其设置为删除重复的duplicate namespaces或保留它们。这意味着,只有当您以某种方式(相当神奇地)为serializable class声明了XmlWriter时,该属性才有任何用处:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"

但是,XmlDeclaration仍然具有一些“好”的东西,您可以通过设置以下内容来忽略XmlWriterSettings:
OmitXmlDeclaration = true;

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

简而言之,我们不能希望default namespaces通过删除其Serializer对我们有所作为-简直是做不到。

因此,我们必须对default namespaces + your namespaces进行求解



信不信由你,这就像你已经做过的一样!

overloading方法Serialize(XmlWriter, Object, XmlSerializerNamespaces)就是为此目的而设计的。调用时:
serializer.Serialize(xmlWriter, obj, obj.Xmlns);

它将your namespaces替换为Serialize(XmlWriter, Object)
如果使用Serializer重载,那么namespaces要做的是将XmlWriterObject中的所有namespaces都接受,然后编写XML文件。因此,您在那里获得了所有的XmlWriter:默认的和您的

这可能是因为XmlNamespaceScope.All也(内部)将XmlNamespaceScope用作Serialize(XmlWriter, Object, XmlSerializerNamespaces),您-再次-对此无能为力。

但是,当您使用Serializer时,实际上是告诉XmlSerializerNamespaces仅使用您指定的Xml。因此,它做对了!

换句话说,您所做的已经是一种在namespaces文件中获取所需 namespace 的“官方”方法。

除了该注释之外,您还可以根据需要将多个Xmlns.Add(prefix, ns)放入您的XML文件中,只需简单地使用所需的ojit_code次数即可。

因此,您已经针对自己的目的做了正确的事情。我只是试图解释为什么会这样。

关于c# - XML序列化期间将忽略属性XmlNamespaceDeclarations,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35417590/

10-11 00:48