XmlSerializer的:删除不必要的XSI和XSD的命名空间 [英] XmlSerializer: remove unnecessary xsi and xsd namespaces

查看:226
本文介绍了XmlSerializer的:删除不必要的XSI和XSD的命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法来配置XmlSerializer的,这样它不会写默认命名空间中的根元素?

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

我得到的是这样的:

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

和我想删除这两个xmlns声明。

and I want to remove both xmlns declarations.

复制的如何没有得到的xmlns =序列化对象到XML...

推荐答案

由于戴夫问我重复我的回答省略所有XSI和序列化在.NET 对象时,XSD命名空间,我已经更新了这篇文章,重复我的答案在这里从上述链接。在该答案中使用的例子是用于其它问题相同的例子。以下是复制,一字不差。

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.

在阅读微软的文档和一些网上的解决方案,我发现了解决这个问题。它的工作原理与两个内置的的XmlSerializer 键,自定义XML序列化,通过 IXmlSerialiazble

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.

要白衣,我会用一个已经用在回答这个问题至今相同 MyTypeWithNamespaces XML示例。

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

[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;
}

这是所有此类。现在,一些反对自己的班级内的某处有一个 XmlSerializerNamespaces 对象;但正如你所看到的,我巧妙地塞到了默认的构造函数和暴露的公共属性返回的命名空间。

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.

现在,当谈到时间的类序列化,你可以使用下面的code:

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>

我已经成功地使用这种方法,在最近的一个项目与类的序列化到XML的Web服务调用了深刻的层次结构。微软的文档不是很清楚如何处理公开入店 XmlSerializerNamespaces 成员一旦你创造了它,所以很多人认为它是无用的。但是按照他们的文档,并在上面显示的方式使用它,你可以自定义XmlSerializer的是如何生成的XML为你的类,而不诉诸不支持的行为,或通过实施的IXmlSerializable

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.

这是我的希望,这个答案将入土为安,一劳永逸,如何摆脱标准的 XSI XSD 所产生的命名空间的的XmlSerializer

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.

更新:我只是想确保我回答的任择议定书的问题,要消除所有的命名空间。我的code以上将适用于这一点;让我来告诉你如何。现在,在上面的例子中,你真的无法摆脱所有命名空间(因为在使用两个命名空间)。放在你的XML文档,你将需要有像的xmlns =金塔:天灵灵地灵灵的xmlns:W =金塔:Whoohoo 如果类的。例子是一个更大的文档的一部分,然后在某处以上命名空间必须为任一个(或两个) Abracadbra Whoohoo ,如果不是,则在一个或两个命名空间的元素必须以某种形式的preFIX装饰(你不能有两个默认的命名空间,对吧?)。所以,在这个例子中,胡言乱语是默认的命名空间,我可以在我的 MyTypeWithNamespaces 类中添加一个命名空间preFIX为 Whoohoo 像这样的命名空间:

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:

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

现在,在我的类定义,我指出了&LT;标签/&GT; 元素的命名空间中的金塔:Whoohoo,所以我不需要做其他事情。当我现在用我上面的序列化code不变序列化类,这是输出:

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:

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

由于&LT;标签&gt; 是从文档的其余部分不同的命名空间,它必须以某种方式,来装饰与命名空间。请注意,仍然没有 XSI XSD 命名空间。

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.

这结束我的回答其他问题。但我想确保我回答的任择议定书的问题,如何使用没有命名空间,因为我觉得我并没有真正解决这个问题呢。假设&LT;标签&gt; 是相同的命名空间文档的其余部分的一部分,在这种情况下金塔:天灵灵地灵灵

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:

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

您的构造看上去就像它会在我的第一个code为例,伴随着公共属性检索默认命名空间:

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;

然后,后来,在code,它使用了 MyTypeWithNamespaces 对象序列化,只需要调用它,因为我做了上面的:

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

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);

的XmlSerializer 将吐回了相同的XML如上面刚与输出无需额外的命名空间:

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

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

这篇关于XmlSerializer的:删除不必要的XSI和XSD的命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆