从C#类序列化XML,需要设置名称空间

时间:2015-07-13 23:19:51

标签: c# xml serialization

我无法使用XmlSerializer(和C#属性)让我的顶级元素看起来完全像这样:

<rootObject xmlns="http://www.example.com/xmlschemas/nonStandardSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.example.com/xmlschemas/nonStandardSchema1.xsd">
    <otherSerializedObjects />
</rootObject>

目前,我最接近的是:

<rootObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    d1p1:schemaLocation="http://www.example.com/xmlschemas/nonStandardSchema1.xsd" 
    xmlns:d1p1="xsi" 
    xmlns="http://www.example.com/xmlschemas/nonStandardSchema">
    <otherSerializedObjects />
</rootObject>

C#

[XmlRoot("rootObject", Namespace = "http://www.example.com/xmlschemas/nonStandardSchema")]
public class RootObject
{
    [XmlAttribute("schemaLocation", Namespace = "xsi")]
    public string SchemaLocation { get; set; }

    [XmlElement("Image")]
    public Object[] OtherSerializedObjects { get; set; }

    public RootObject()
    {
        OtherSerializedObjects = new Object[]{};
    }
}   

public class Program
{
    static void Main(string[] args)
    {
        var rootObject = new RootObject
        {
            SchemaLocation = "http://www.example.com/xmlschemas/nonStandardSchema1.xsd",
            OtherSerializedObjects = new object[]{}
        };

        var serializer = new XmlSerializer(typeof(RootObject));
        var stringWriter = new StringWriter();
        serializer.Serialize(stringWriter, rootObject);
        Console.WriteLine(stringWriter.ToString()); 
    }
}

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

首先,schemaLocation字段/属性的[XmlAttribute(Namespace=X)]属性需要 X 完整命名空间>,而不是本地命名空间快捷方式。顺便说一下,这可以是属性而不是字段。为此目的使用字段会浪费内存。

其次,要消除标准xmlns:xsd="http://www.w3.org/2001/XMLSchema",请使用XmlSerializer.Serialize重载,只需传入XmlSerializerNamespaces所需的命名空间。

因此:

[XmlRoot("rootObject", Namespace = "http://www.example.com/xmlschemas/nonStandardSchema")]
public class RootObject
{
    public static XmlSerializerNamespaces GetAdditionalNamespaces()
    {
        XmlSerializerNamespaces xsNS = new XmlSerializerNamespaces();


        xsNS.Add("", "http://www.example.com/xmlschemas/nonStandardSchema");
        xsNS.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");

        return xsNS;
    }

    [XmlAttribute("schemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
    public string XSDSchemaLocation
    {
        get
        {
            return "http://www.example.com/xmlschemas/nonStandardSchema1.xsd";
        }
        set
        {
            // Do nothing - fake property.
        }
    }

    [XmlElement("Image")]
    public Object[] OtherSerializedObjects { get; set; }

    public RootObject()
    {
        OtherSerializedObjects = new Object[]{};
    }
}   

然后使用它:

        var rootObject = new RootObject
        {
            OtherSerializedObjects = new object[]{}
        };

        var serializer = new XmlSerializer(typeof(RootObject));
        var stringWriter = new StringWriter();
        var ns = RootObject.GetAdditionalNamespaces();

        var settings = new XmlWriterSettings() { Indent = true, IndentChars = "    " }; // For cosmetic purposes.
        using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
        {
            serializer.Serialize(xmlWriter, rootObject, ns);
        }

        Console.WriteLine(stringWriter.ToString()); 

示例fiddle

答案 1 :(得分:0)

命名空间需要是整个命名空间,而不是缩短版本。

[XmlAttribute("schemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]

在我的测试中,它会自动使用xsi