XmlSerializer生成没有命名空间前缀的XML

时间:2010-05-14 19:30:48

标签: c# xml-serialization

我必须创建一个前缀为所有元素的XML文件,如下所示:

<ps:Request num="123" xmlns:ps="www.ladieda.com">
   <ps:ClientId>5566</ps:ClientId>
<ps:Request>

当我序列化我的对象时,c#是聪明的并且这样做:

<Request num="123" xmlns="www.ladieda.com">
   <ClientId>5566</ClientId>
<Request>

这很好,因为ps:不是必需的。

但有没有办法强制C#序列化所有前缀?

我的序列化代码是这样的(对于传入的对象pObject):

String XmlizedString = null;
MemoryStream memoryStream = new MemoryStream();
XmlSerializer xs = new XmlSerializer(pObject.GetType());
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);

xs.Serialize(xmlTextWriter, pObject);
memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
return XmlizedString;


private String UTF8ByteArrayToString(Byte[] characters)
{
    UTF8Encoding encoding = new UTF8Encoding();
    String constructedString = encoding.GetString(characters);
    return (constructedString);
}

2 个答案:

答案 0 :(得分:15)

首先,如果您的字符串的使用者正在处理XML,那么他们就不会关心前缀,因为它与XML无关。也许他们不理解XML,并认为他们正在处理一个字符串(可能需要在每个元素上都有字符串“ps:”)。

其次,您应该稍微更改一下代码:

XmlSerializer xs = new XmlSerializer(pObject.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
    XmlWriterSettings settings = new XmlWriterSettings()
    {
        Encoding = Encoding.UTF8
    };
    using (XmlWriter writer = XmlWriter.Create(memoryStream, settings))
    {
        xs.Serialize(writer, pObject);
    }
    return Encoding.UTF8.GetString(memoryStream.ToArray());
}

如果抛出异常,这将正确处理流和XmlWriter,停止使用已弃用的XmlTextWriter类,但仍然返回包含为UTF-8编写的XML的字符串。

最后,要控制前缀,请参阅"How to: Qualify XML Element and XML Attribute Names"

XmlSerializerNamespaces myNamespaces = new XmlSerializerNamespaces();
myNamespaces.Add("ps", "www.ladieda.com");

XmlSerializer xs = new XmlSerializer(pObject.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
    XmlWriterSettings settings = new XmlWriterSettings()
    {
        Encoding = Encoding.UTF8
    };
    using (XmlWriter writer = XmlWriter.Create(memoryStream, settings))
    {
        xs.Serialize(writer, pObject, myNamespaces);
    }
    return Encoding.UTF8.GetString(memoryStream.ToArray());
}

答案 1 :(得分:0)

另请查看XmlNamespaceDeclarationsAttribute。警告:反序列化时只会为您提供由该元素定义的名称空间,它不会在父元素中定义名称空间。如果你没有一致的根类型,那么使用@John Saunders的XmlSerializer.Serialize()重载。

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlnamespacedeclarationsattribute.aspx

在另一个问题中,@ John Saunders建议在WSDL中控制xmlns时使用此属性:Namespace Prefixes in Wsdl (.net)

来自MSDN示例:

// C#
using System;
using System.IO;
using System.Xml.Serialization;
[XmlRoot("select")]
public class Select {
    [XmlAttribute] public string xpath;
    [XmlNamespaceDeclarations] public XmlSerializerNamespaces xmlns;
}
public class Test {
    public static void Main(string[] args) {
       Select mySelect = new Select();
       mySelect.xpath = "myNS:ref/@common:y";
       mySelect.xmlns = new XmlSerializerNamespaces();
       mySelect.xmlns.Add("MyNS", "myNS.tempuri.org");
       mySelect.xmlns.Add("common", "common.tempuri.org");
       XmlSerializer ser = new XmlSerializer(typeof(Select));
       ser.Serialize(Console.Out, mySelect);
    }
}
// Output:
// <?xml version="1.0" encoding="IBM437"?>
// <select xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmln:xsi="http://www.w3.org/2001/XMLSchema-instance" 
// xmlns:common="common.tempuri.org" xmlns:MyNS="myNS.tempuri.org" xpath="myNS:ref/@common:y" />