XmlSerializer:删除不必要的xsi和xsd名称空间

时间:2022-11-20 15:26:13

Is there a way to configure the XmlSerializer so that it doesn't write default namespaces in the root element?

是否有一种方法可以配置XmlSerializer,使其不会在根元素中写入默认名称空间?

What I get is this:

我得到的是:

<?xml ...>
<rootelement xmlns:xsi="..." xmlns:xsd="...">
</rootelement>

and I want to remove both xmlns declarations.

我想删除这两个xmlns声明。

Duplicate of: How to serialize an object to XML without getting xmlns=”…”?

副本:如何将对象序列化为XML而不获取xmlns= "…" ?

3 个解决方案

#1


52  

Since Dave asked for me to repeat my answer to Omitting all xsi and xsd namespaces when serializing an object in .NET, I have updated this post and repeated my answer here from the afore-mentioned link. The example used in this answer is the same example used for the other question. What follows is copied, verbatim.

由于Dave要求我重复我的答案,在. net中序列化一个对象时省略了所有xsi和xsd名称空间,所以我更新了这篇文章,并从上述链接重复了我的答案。这个答案中使用的示例与另一个问题中使用的示例相同。以下内容逐字复制。


After reading Microsoft's documentation and several solutions online, I have discovered the solution to this problem. It works with both the built-in XmlSerializer and custom XML serialization via IXmlSerialiazble.

在在线阅读了Microsoft的文档和几个解决方案之后,我发现了这个问题的解决方案。它通过IXmlSerialiazble与内置的XmlSerializer和自定义XML序列化一起工作。

To whit, I'll use the same MyTypeWithNamespaces XML sample that's been used in the answers to this question so far.

对于whit,我将使用相同的MyTypeWithNamespaces XML示例,到目前为止已经在这个问题的答案中使用过。

[XmlRoot("MyTypeWithNamespaces", Namespace="urn:Abracadabra", IsNullable=false)]
public class MyTypeWithNamespaces
{
    // As noted below, per Microsoft's documentation, if the class exposes a public
    // member of type XmlSerializerNamespaces decorated with the 
    // XmlNamespacesDeclarationAttribute, then the XmlSerializer will utilize those
    // namespaces during serialization.
    public MyTypeWithNamespaces( )
    {
        this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
            // Don't do this!! Microsoft's documentation explicitly says it's not supported.
            // It doesn't throw any exceptions, but in my testing, it didn't always work.

            // new XmlQualifiedName(string.Empty, string.Empty),  // And don't do this:
            // new XmlQualifiedName("", "")

            // DO THIS:
            new XmlQualifiedName(string.Empty, "urn:Abracadabra") // Default Namespace
            // Add any other namespaces, with prefixes, here.
        });
    }

    // If you have other constructors, make sure to call the default constructor.
    public MyTypeWithNamespaces(string label, int epoch) : this( )
    {
        this._label = label;
        this._epoch = epoch;
    }

    // An element with a declared namespace different than the namespace
    // of the enclosing type.
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        get { return this._label; }
        set { this._label = value; }
    }
    private string _label;

    // An element whose tag will be the same name as the property name.
    // Also, this element will inherit the namespace of the enclosing type.
    public int Epoch
    {
        get { return this._epoch; }
        set { this._epoch = value; }
    }
    private int _epoch;

    // Per Microsoft's documentation, you can add some public member that
    // returns a XmlSerializerNamespaces object. They use a public field,
    // but that's sloppy. So I'll use a private backed-field with a public
    // getter property. Also, per the documentation, for this to work with
    // the XmlSerializer, decorate it with the XmlNamespaceDeclarations
    // attribute.
    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces Namespaces
    {
        get { return this._namespaces; }
    }
    private XmlSerializerNamespaces _namespaces;
}

That's all to this class. Now, some objected to having an XmlSerializerNamespaces object somewhere within their classes; but as you can see, I neatly tucked it away in the default constructor and exposed a public property to return the namespaces.

这就是这门课的全部内容。现在,有些人反对在类的某个地方放置XmlSerializerNamespaces对象;但是正如您所看到的,我将它巧妙地隐藏在默认构造函数中,并公开了一个公共属性来返回名称空间。

Now, when it comes time to serialize the class, you would use the following code:

现在,当需要序列化类时,您将使用以下代码:

MyTypeWithNamespaces myType = new MyTypeWithNamespaces("myLabel", 42);

/******
   OK, I just figured I could do this to make the code shorter, so I commented out the
   below and replaced it with what follows:

// You have to use this constructor in order for the root element to have the right namespaces.
// If you need to do custom serialization of inner objects, you can use a shortened constructor.
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces), new XmlAttributeOverrides(),
    new Type[]{}, new XmlRootAttribute("MyTypeWithNamespaces"), "urn:Abracadabra");

******/
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),
    new XmlRootAttribute("MyTypeWithNamespaces") { Namespace="urn:Abracadabra" });

// I'll use a MemoryStream as my backing store.
MemoryStream ms = new MemoryStream();

// This is extra! If you want to change the settings for the XmlSerializer, you have to create
// a separate XmlWriterSettings object and use the XmlTextWriter.Create(...) factory method.
// So, in this case, I want to omit the XML declaration.
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Encoding = Encoding.UTF8; // This is probably the default
// You could use the XmlWriterSetting to set indenting and new line options, but the
// XmlTextWriter class has a much easier method to accomplish that.

// The factory method returns a XmlWriter, not a XmlTextWriter, so cast it.
XmlTextWriter xtw = (XmlTextWriter)XmlTextWriter.Create(ms, xws);
// Then we can set our indenting options (this is, of course, optional).
xtw.Formatting = Formatting.Indented;

// Now serialize our object.
xs.Serialize(xtw, myType, myType.Namespaces);

Once you have done this, you should get the following output:

完成此操作后,您应该得到以下输出:

<MyTypeWithNamespaces>
    <Label xmlns="urn:Whoohoo">myLabel</Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

I have successfully used this method in a recent project with a deep hierachy of classes that are serialized to XML for web service calls. Microsoft's documentation is not very clear about what to do with the publicly accesible XmlSerializerNamespaces member once you've created it, and so many think it's useless. But by following their documentation and using it in the manner shown above, you can customize how the XmlSerializer generates XML for your classes without resorting to unsupported behavior or "rolling your own" serialization by implementing IXmlSerializable.

在最近的一个项目中,我成功地使用了这个方法,其中包含了大量的类,这些类被序列化为用于web服务调用的XML。微软的文档并不清楚一旦创建了公开可接受的XmlSerializerNamespaces成员,该如何处理,因此很多人认为它毫无用处。但是,通过遵循它们的文档并按照上面所示的方式使用它们,您可以定制XmlSerializer如何为您的类生成XML,而无需求助于不受支持的行为或通过实现IXmlSerializable来“滚动您自己的”序列化。

It is my hope that this answer will put to rest, once and for all, how to get rid of the standard xsi and xsd namespaces generated by the XmlSerializer.

我希望这个答案将彻底解决如何摆脱XmlSerializer生成的标准xsi和xsd名称空间的问题。

UPDATE: I just want to make sure I answered the OP's question about removing all namespaces. My code above will work for this; let me show you how. Now, in the example above, you really can't get rid of all namespaces (because there are two namespaces in use). Somewhere in your XML document, you're going to need to have something like xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. If the class in the example is part of a larger document, then somewhere above a namespace must be declared for either one of (or both) Abracadbra and Whoohoo. If not, then the element in one or both of the namespaces must be decorated with a prefix of some sort (you can't have two default namespaces, right?). So, for this example, Abracadabra is the default namespace. I could inside my MyTypeWithNamespaces class add a namespace prefix for the Whoohoo namespace like so:

更新:我只是想确保我回答了OP关于删除所有名称空间的问题。以上代码将适用于此;我来告诉你怎么做。现在,在上面的示例中,您确实不能删除所有名称空间(因为使用了两个名称空间)。在XML文档的某个地方,需要使用xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. "如果示例中的类是较大文档的一部分,那么必须声明在名称空间的某个位置上(或两者)Abracadbra和Whoohoo。如果不是,那么其中一个或两个名称空间中的元素必须用某种前缀来修饰(您不能有两个默认的名称空间,对吧?)因此,在本例中,Abracadabra是默认的命名空间。我可以在MyTypeWithNamespaces类中为Whoohoo名称空间添加一个名称空间前缀,如下所示:

public MyTypeWithNamespaces
{
    this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
        new XmlQualifiedName(string.Empty, "urn:Abracadabra"), // Default Namespace
        new XmlQualifiedName("w", "urn:Whoohoo")
    });
}

Now, in my class definition, I indicated that the <Label/> element is in the namespace "urn:Whoohoo", so I don't need to do anything further. When I now serialize the class using my above serialization code unchanged, this is the output:

现在,在我的类定义中,我指出元素位于名称空间“urn:Whoohoo”中,因此我不需要做任何进一步的工作。当我现在使用上面的序列化代码对类进行序列化时,这是输出:

<MyTypeWithNamespaces xmlns:w="urn:Whoohoo">
    <w:Label>myLabel</w:Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

Because <Label> is in a different namespace from the rest of the document, it must, in someway, be "decorated" with a namespace. Notice that there are still no xsi and xsd namespaces.

因为


This ends my answer to the other question. But I wanted to make sure I answered the OP's question about using no namespaces, as I feel I didn't really address it yet. Assume that <Label> is part of the same namespace as the rest of the document, in this case urn:Abracadabra:

这就结束了我对另一个问题的回答。但我想确保我已经回答了OP关于不使用名称空间的问题,因为我觉得我还没有真正解决它。假设

<MyTypeWithNamespaces>
    <Label>myLabel<Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

Your constructor would look as it would in my very first code example, along with the public property to retrieve the default namespace:

在我的第一个代码示例中,您的构造函数将与公共属性一起检索默认名称空间:

// As noted below, per Microsoft's documentation, if the class exposes a public
// member of type XmlSerializerNamespaces decorated with the 
// XmlNamespacesDeclarationAttribute, then the XmlSerializer will utilize those
// namespaces during serialization.
public MyTypeWithNamespaces( )
{
    this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
        new XmlQualifiedName(string.Empty, "urn:Abracadabra") // Default Namespace
    });
}

[XmlNamespaceDeclarations]
public XmlSerializerNamespaces Namespaces
{
    get { return this._namespaces; }
}
private XmlSerializerNamespaces _namespaces;

Then, later, in your code that uses the MyTypeWithNamespaces object to serialize it, you would call it as I did above:

然后,在使用typemywithnamespaces对象对其进行序列化的代码中,您将像我上面所做的那样调用它:

MyTypeWithNamespaces myType = new MyTypeWithNamespaces("myLabel", 42);

XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),
    new XmlRootAttribute("MyTypeWithNamespaces") { Namespace="urn:Abracadabra" });

...

// Above, you'd setup your XmlTextWriter.

// Now serialize our object.
xs.Serialize(xtw, myType, myType.Namespaces);

And the XmlSerializer would spit back out the same XML as shown immediately above with no additional namespaces in the output:

XmlSerializer将返回与上面所示相同的XML,输出中没有附加名称空间:

<MyTypeWithNamespaces>
    <Label>myLabel<Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

#2


233  

//Create our own namespaces for the output
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

//Add an empty namespace and empty value
ns.Add("", "");

//Create the serializer
XmlSerializer slz = new XmlSerializer(someType);

//Serialize the object with our own namespaces (notice the overload)
slz.Serialize(myXmlTextWriter, someObject, ns)

#3


6  

There is an alternative - you can provide a member of type XmlSerializerNamespaces in the type to be serialized. Decorate it with the XmlNamespaceDeclarations attribute. Add the namespace prefixes and URIs to that member. Then, any serialization that does not explicitly provide an XmlSerializerNamespaces will use the namespace prefix+URI pairs you have put into your type.

还有一种替代方法——您可以在要序列化的类型中提供XmlSerializerNamespaces类型的成员。使用xmlnamespacedeclaration属性对其进行修饰。向该成员添加名称空间前缀和uri。然后,任何没有显式提供xmlserizeralinamespaces的序列化都将使用您放入类型中的名称空间前缀+URI对。

Example code, suppose this is your type:

示例代码,假设这是您的类型:

[XmlRoot(Namespace = "urn:mycompany.2009")]
public class Person {
  [XmlAttribute] 
  public bool Known;
  [XmlElement]
  public string Name;
  [XmlNamespaceDeclarations]
  public XmlSerializerNamespaces xmlns;
}

You can do this:

你可以这样做:

var p = new Person
  { 
      Name = "Charley",
      Known = false, 
      xmlns = new XmlSerializerNamespaces()
  }
p.xmlns.Add("",""); // default namespace is emoty
p.xmlns.Add("c", "urn:mycompany.2009");

And that will mean that any serialization of that instance that does not specify its own set of prefix+URI pairs will use the "p" prefix for the "urn:mycompany.2009" namespace. It will also omit the xsi and xsd namespaces.

这意味着,该实例的任何序列化,如果没有指定自己的前缀+URI对集,都将使用“p”前缀表示“urn:mycompany”。2009”名称空间。它还将省略xsi和xsd名称空间。

The difference here is that you are adding the XmlSerializerNamespaces to the type itself, rather than employing it explicitly on a call to XmlSerializer.Serialize(). This means that if an instance of your type is serialized by code you do not own (for example in a webservices stack), and that code does not explicitly provide a XmlSerializerNamespaces, that serializer will use the namespaces provided in the instance.

这里的不同之处在于,您将XmlSerializerNamespaces添加到类型本身,而不是在调用xmlseriali泽. serialize()时显式地使用它。这意味着,如果您的类型的实例被您不拥有的代码序列化(例如在webservices堆栈中),并且该代码没有显式地提供XmlSerializerNamespaces,那么序列化器将使用实例中提供的名称空间。

#1


52  

Since Dave asked for me to repeat my answer to Omitting all xsi and xsd namespaces when serializing an object in .NET, I have updated this post and repeated my answer here from the afore-mentioned link. The example used in this answer is the same example used for the other question. What follows is copied, verbatim.

由于Dave要求我重复我的答案,在. net中序列化一个对象时省略了所有xsi和xsd名称空间,所以我更新了这篇文章,并从上述链接重复了我的答案。这个答案中使用的示例与另一个问题中使用的示例相同。以下内容逐字复制。


After reading Microsoft's documentation and several solutions online, I have discovered the solution to this problem. It works with both the built-in XmlSerializer and custom XML serialization via IXmlSerialiazble.

在在线阅读了Microsoft的文档和几个解决方案之后,我发现了这个问题的解决方案。它通过IXmlSerialiazble与内置的XmlSerializer和自定义XML序列化一起工作。

To whit, I'll use the same MyTypeWithNamespaces XML sample that's been used in the answers to this question so far.

对于whit,我将使用相同的MyTypeWithNamespaces XML示例,到目前为止已经在这个问题的答案中使用过。

[XmlRoot("MyTypeWithNamespaces", Namespace="urn:Abracadabra", IsNullable=false)]
public class MyTypeWithNamespaces
{
    // As noted below, per Microsoft's documentation, if the class exposes a public
    // member of type XmlSerializerNamespaces decorated with the 
    // XmlNamespacesDeclarationAttribute, then the XmlSerializer will utilize those
    // namespaces during serialization.
    public MyTypeWithNamespaces( )
    {
        this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
            // Don't do this!! Microsoft's documentation explicitly says it's not supported.
            // It doesn't throw any exceptions, but in my testing, it didn't always work.

            // new XmlQualifiedName(string.Empty, string.Empty),  // And don't do this:
            // new XmlQualifiedName("", "")

            // DO THIS:
            new XmlQualifiedName(string.Empty, "urn:Abracadabra") // Default Namespace
            // Add any other namespaces, with prefixes, here.
        });
    }

    // If you have other constructors, make sure to call the default constructor.
    public MyTypeWithNamespaces(string label, int epoch) : this( )
    {
        this._label = label;
        this._epoch = epoch;
    }

    // An element with a declared namespace different than the namespace
    // of the enclosing type.
    [XmlElement(Namespace="urn:Whoohoo")]
    public string Label
    {
        get { return this._label; }
        set { this._label = value; }
    }
    private string _label;

    // An element whose tag will be the same name as the property name.
    // Also, this element will inherit the namespace of the enclosing type.
    public int Epoch
    {
        get { return this._epoch; }
        set { this._epoch = value; }
    }
    private int _epoch;

    // Per Microsoft's documentation, you can add some public member that
    // returns a XmlSerializerNamespaces object. They use a public field,
    // but that's sloppy. So I'll use a private backed-field with a public
    // getter property. Also, per the documentation, for this to work with
    // the XmlSerializer, decorate it with the XmlNamespaceDeclarations
    // attribute.
    [XmlNamespaceDeclarations]
    public XmlSerializerNamespaces Namespaces
    {
        get { return this._namespaces; }
    }
    private XmlSerializerNamespaces _namespaces;
}

That's all to this class. Now, some objected to having an XmlSerializerNamespaces object somewhere within their classes; but as you can see, I neatly tucked it away in the default constructor and exposed a public property to return the namespaces.

这就是这门课的全部内容。现在,有些人反对在类的某个地方放置XmlSerializerNamespaces对象;但是正如您所看到的,我将它巧妙地隐藏在默认构造函数中,并公开了一个公共属性来返回名称空间。

Now, when it comes time to serialize the class, you would use the following code:

现在,当需要序列化类时,您将使用以下代码:

MyTypeWithNamespaces myType = new MyTypeWithNamespaces("myLabel", 42);

/******
   OK, I just figured I could do this to make the code shorter, so I commented out the
   below and replaced it with what follows:

// You have to use this constructor in order for the root element to have the right namespaces.
// If you need to do custom serialization of inner objects, you can use a shortened constructor.
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces), new XmlAttributeOverrides(),
    new Type[]{}, new XmlRootAttribute("MyTypeWithNamespaces"), "urn:Abracadabra");

******/
XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),
    new XmlRootAttribute("MyTypeWithNamespaces") { Namespace="urn:Abracadabra" });

// I'll use a MemoryStream as my backing store.
MemoryStream ms = new MemoryStream();

// This is extra! If you want to change the settings for the XmlSerializer, you have to create
// a separate XmlWriterSettings object and use the XmlTextWriter.Create(...) factory method.
// So, in this case, I want to omit the XML declaration.
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
xws.Encoding = Encoding.UTF8; // This is probably the default
// You could use the XmlWriterSetting to set indenting and new line options, but the
// XmlTextWriter class has a much easier method to accomplish that.

// The factory method returns a XmlWriter, not a XmlTextWriter, so cast it.
XmlTextWriter xtw = (XmlTextWriter)XmlTextWriter.Create(ms, xws);
// Then we can set our indenting options (this is, of course, optional).
xtw.Formatting = Formatting.Indented;

// Now serialize our object.
xs.Serialize(xtw, myType, myType.Namespaces);

Once you have done this, you should get the following output:

完成此操作后,您应该得到以下输出:

<MyTypeWithNamespaces>
    <Label xmlns="urn:Whoohoo">myLabel</Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

I have successfully used this method in a recent project with a deep hierachy of classes that are serialized to XML for web service calls. Microsoft's documentation is not very clear about what to do with the publicly accesible XmlSerializerNamespaces member once you've created it, and so many think it's useless. But by following their documentation and using it in the manner shown above, you can customize how the XmlSerializer generates XML for your classes without resorting to unsupported behavior or "rolling your own" serialization by implementing IXmlSerializable.

在最近的一个项目中,我成功地使用了这个方法,其中包含了大量的类,这些类被序列化为用于web服务调用的XML。微软的文档并不清楚一旦创建了公开可接受的XmlSerializerNamespaces成员,该如何处理,因此很多人认为它毫无用处。但是,通过遵循它们的文档并按照上面所示的方式使用它们,您可以定制XmlSerializer如何为您的类生成XML,而无需求助于不受支持的行为或通过实现IXmlSerializable来“滚动您自己的”序列化。

It is my hope that this answer will put to rest, once and for all, how to get rid of the standard xsi and xsd namespaces generated by the XmlSerializer.

我希望这个答案将彻底解决如何摆脱XmlSerializer生成的标准xsi和xsd名称空间的问题。

UPDATE: I just want to make sure I answered the OP's question about removing all namespaces. My code above will work for this; let me show you how. Now, in the example above, you really can't get rid of all namespaces (because there are two namespaces in use). Somewhere in your XML document, you're going to need to have something like xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. If the class in the example is part of a larger document, then somewhere above a namespace must be declared for either one of (or both) Abracadbra and Whoohoo. If not, then the element in one or both of the namespaces must be decorated with a prefix of some sort (you can't have two default namespaces, right?). So, for this example, Abracadabra is the default namespace. I could inside my MyTypeWithNamespaces class add a namespace prefix for the Whoohoo namespace like so:

更新:我只是想确保我回答了OP关于删除所有名称空间的问题。以上代码将适用于此;我来告诉你怎么做。现在,在上面的示例中,您确实不能删除所有名称空间(因为使用了两个名称空间)。在XML文档的某个地方,需要使用xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo. "如果示例中的类是较大文档的一部分,那么必须声明在名称空间的某个位置上(或两者)Abracadbra和Whoohoo。如果不是,那么其中一个或两个名称空间中的元素必须用某种前缀来修饰(您不能有两个默认的名称空间,对吧?)因此,在本例中,Abracadabra是默认的命名空间。我可以在MyTypeWithNamespaces类中为Whoohoo名称空间添加一个名称空间前缀,如下所示:

public MyTypeWithNamespaces
{
    this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
        new XmlQualifiedName(string.Empty, "urn:Abracadabra"), // Default Namespace
        new XmlQualifiedName("w", "urn:Whoohoo")
    });
}

Now, in my class definition, I indicated that the <Label/> element is in the namespace "urn:Whoohoo", so I don't need to do anything further. When I now serialize the class using my above serialization code unchanged, this is the output:

现在,在我的类定义中,我指出元素位于名称空间“urn:Whoohoo”中,因此我不需要做任何进一步的工作。当我现在使用上面的序列化代码对类进行序列化时,这是输出:

<MyTypeWithNamespaces xmlns:w="urn:Whoohoo">
    <w:Label>myLabel</w:Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

Because <Label> is in a different namespace from the rest of the document, it must, in someway, be "decorated" with a namespace. Notice that there are still no xsi and xsd namespaces.

因为


This ends my answer to the other question. But I wanted to make sure I answered the OP's question about using no namespaces, as I feel I didn't really address it yet. Assume that <Label> is part of the same namespace as the rest of the document, in this case urn:Abracadabra:

这就结束了我对另一个问题的回答。但我想确保我已经回答了OP关于不使用名称空间的问题,因为我觉得我还没有真正解决它。假设

<MyTypeWithNamespaces>
    <Label>myLabel<Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

Your constructor would look as it would in my very first code example, along with the public property to retrieve the default namespace:

在我的第一个代码示例中,您的构造函数将与公共属性一起检索默认名称空间:

// As noted below, per Microsoft's documentation, if the class exposes a public
// member of type XmlSerializerNamespaces decorated with the 
// XmlNamespacesDeclarationAttribute, then the XmlSerializer will utilize those
// namespaces during serialization.
public MyTypeWithNamespaces( )
{
    this._namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
        new XmlQualifiedName(string.Empty, "urn:Abracadabra") // Default Namespace
    });
}

[XmlNamespaceDeclarations]
public XmlSerializerNamespaces Namespaces
{
    get { return this._namespaces; }
}
private XmlSerializerNamespaces _namespaces;

Then, later, in your code that uses the MyTypeWithNamespaces object to serialize it, you would call it as I did above:

然后,在使用typemywithnamespaces对象对其进行序列化的代码中,您将像我上面所做的那样调用它:

MyTypeWithNamespaces myType = new MyTypeWithNamespaces("myLabel", 42);

XmlSerializer xs = new XmlSerializer(typeof(MyTypeWithNamespaces),
    new XmlRootAttribute("MyTypeWithNamespaces") { Namespace="urn:Abracadabra" });

...

// Above, you'd setup your XmlTextWriter.

// Now serialize our object.
xs.Serialize(xtw, myType, myType.Namespaces);

And the XmlSerializer would spit back out the same XML as shown immediately above with no additional namespaces in the output:

XmlSerializer将返回与上面所示相同的XML,输出中没有附加名称空间:

<MyTypeWithNamespaces>
    <Label>myLabel<Label>
    <Epoch>42</Epoch>
</MyTypeWithNamespaces>

#2


233  

//Create our own namespaces for the output
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

//Add an empty namespace and empty value
ns.Add("", "");

//Create the serializer
XmlSerializer slz = new XmlSerializer(someType);

//Serialize the object with our own namespaces (notice the overload)
slz.Serialize(myXmlTextWriter, someObject, ns)

#3


6  

There is an alternative - you can provide a member of type XmlSerializerNamespaces in the type to be serialized. Decorate it with the XmlNamespaceDeclarations attribute. Add the namespace prefixes and URIs to that member. Then, any serialization that does not explicitly provide an XmlSerializerNamespaces will use the namespace prefix+URI pairs you have put into your type.

还有一种替代方法——您可以在要序列化的类型中提供XmlSerializerNamespaces类型的成员。使用xmlnamespacedeclaration属性对其进行修饰。向该成员添加名称空间前缀和uri。然后,任何没有显式提供xmlserizeralinamespaces的序列化都将使用您放入类型中的名称空间前缀+URI对。

Example code, suppose this is your type:

示例代码,假设这是您的类型:

[XmlRoot(Namespace = "urn:mycompany.2009")]
public class Person {
  [XmlAttribute] 
  public bool Known;
  [XmlElement]
  public string Name;
  [XmlNamespaceDeclarations]
  public XmlSerializerNamespaces xmlns;
}

You can do this:

你可以这样做:

var p = new Person
  { 
      Name = "Charley",
      Known = false, 
      xmlns = new XmlSerializerNamespaces()
  }
p.xmlns.Add("",""); // default namespace is emoty
p.xmlns.Add("c", "urn:mycompany.2009");

And that will mean that any serialization of that instance that does not specify its own set of prefix+URI pairs will use the "p" prefix for the "urn:mycompany.2009" namespace. It will also omit the xsi and xsd namespaces.

这意味着,该实例的任何序列化,如果没有指定自己的前缀+URI对集,都将使用“p”前缀表示“urn:mycompany”。2009”名称空间。它还将省略xsi和xsd名称空间。

The difference here is that you are adding the XmlSerializerNamespaces to the type itself, rather than employing it explicitly on a call to XmlSerializer.Serialize(). This means that if an instance of your type is serialized by code you do not own (for example in a webservices stack), and that code does not explicitly provide a XmlSerializerNamespaces, that serializer will use the namespaces provided in the instance.

这里的不同之处在于,您将XmlSerializerNamespaces添加到类型本身,而不是在调用xmlseriali泽. serialize()时显式地使用它。这意味着,如果您的类型的实例被您不拥有的代码序列化(例如在webservices堆栈中),并且该代码没有显式地提供XmlSerializerNamespaces,那么序列化器将使用实例中提供的名称空间。