2009-06-01 56 views
20

我試圖生成這樣的XML:.NET XML序列化

<?xml version="1.0"?> 
<!DOCTYPE APIRequest SYSTEM 
"https://url"> 
<APIRequest> 
    <Head> 
     <Key>123</Key> 
    </Head> 
    <ObjectClass> 
    <Field>Value</Field 
    </ObjectClass> 
</APIRequest> 

我有一個類(對象類)的屬性這樣飾XMLSerialization:

[XmlRoot("ObjectClass")] 
public class ObjectClass 
{ 
    [XmlElement("Field")] 
    public string Field { get; set; } 
} 

而且我真正的哈克直覺的想法,只是得到這個工作是當我序列化時做到這一點:

ObjectClass inst = new ObjectClass(); 
XmlSerializer serializer = new XmlSerializer(inst.GetType(), ""); 

StringWriter w = new StringWriter(); 
w.WriteLine(@"<?xml version=""1.0""?>"); 
w.WriteLine("<!DOCTYPE APIRequest SYSTEM"); 
w.WriteLine(@"""https://url"">"); 
w.WriteLine("<APIRequest>"); 
w.WriteLine("<Head>"); 
w.WriteLine(@"<Field>Value</Field>"); 
w.WriteLine(@"</Head>"); 

XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); 
ns.Add("", ""); 
serializer.Serialize(w, inst, ns); 

w.WriteLine("</APIRequest>"); 

然而,這會產生這樣的XML:

<?xml version="1.0"?> 
<!DOCTYPE APIRequest SYSTEM 
"https://url"> 
<APIRequest> 
    <Head> 
     <Key>123</Key> 
    </Head> 
    <?xml version="1.0" encoding="utf-16"?> 
    <ObjectClass> 
    <Field>Value</Field> 
    </ObjectClass> 
</APIRequest> 

即連載語句自動添加一個< XML文本聲明?

我知道我在攻擊這個錯誤,所以有人能指出我正確的方向嗎?作爲一個說明,我認爲只用一個ObjectClass創建一個APIRequest類是不現實的(因爲有20種不同類型的ObjectClass,每個都需要這個樣板),但是糾正我如果我錯了。

+0

自動?你似乎是手動添加聲明:w.WriteLine(@「<?xml version =」「1.0」「?>」);. – Cerebrus 2009-06-01 05:47:54

+1

@Cerebrus,他不希望標籤內部的。 – sisve 2009-06-01 05:55:16

+0

是的,這是它感謝清除:-) – 2009-06-01 06:05:55

回答

24

永遠不要使用字符串連接來構建xml。這是邪惡的。

輸出:

<?xml version="1.0" encoding="utf-16"?> 
<!DOCTYPE APIRequest SYSTEM "https://url"> 
<APIRequest> 
    <Head> 
    <Key>123</Key> 
    </Head> 
    <ObjectClass> 
    <Field>Value</Field> 
    </ObjectClass> 
</APIRequest> 

代碼:

using System; 
using System.Diagnostics; 
using System.Text; 
using System.Xml; 
using System.Xml.Serialization; 

public static class Program { 
    public static void Main() { 
     var obj = new ObjectClass { Field = "Value" }; 

     var settings = new XmlWriterSettings { 
      Indent = true 
     }; 

     var xml = new StringBuilder(); 
     using (var writer = XmlWriter.Create(xml, settings)) { 
      Debug.Assert(writer != null); 

      writer.WriteDocType("APIRequest", null, "https://url", null); 
      writer.WriteStartElement("APIRequest"); 
      writer.WriteStartElement("Head"); 
      writer.WriteElementString("Key", "123"); 
      writer.WriteEndElement(); // </Head> 

      var nsSerializer = new XmlSerializerNamespaces(); 
      nsSerializer.Add("", ""); 

      var xmlSerializer = new XmlSerializer(obj.GetType(), ""); 
      xmlSerializer.Serialize(writer, obj, nsSerializer); 

      writer.WriteEndElement(); // </APIRequest> 
     } 

     Console.WriteLine(xml.ToString()); 
     Console.ReadLine(); 
    } 
} 

[XmlRoot("ObjectClass")] 
public class ObjectClass { 
    [XmlElement("Field")] 
    public string Field { get; set; } 
} 
1

派生自己的XmlTextWriter省略XML聲明。

Private Class MyXmlTextWriter 
Inherits XmlTextWriter 
Sub New(ByVal sb As StringBuilder) 
    MyBase.New(New StringWriter(sb)) 
End Sub 
Sub New(ByVal w As TextWriter) 
    MyBase.New(w) 
End Sub 

Public Overrides Sub WriteStartDocument() 
    ' Don't emit XML declaration 
End Sub 
Public Overrides Sub WriteStartDocument(ByVal standalone As Boolean) 
    ' Don't emit XML declaration 
End Sub 
End Class 

使用派生的MyXmlTextWriter實例調用Serialize。

Dim tw As New MyXmlTextWriter(sb) 
Dim objXmlSerializer As New XmlSerializer(type) 
objXmlSerializer.Serialize(tw, obj) 
1

Scott Hanselman's在這方面得到了很好的發表。我使用了Kzu的例子(斯科特的博客指出),而且它的效果很好。

-2

一個襯墊,從字符串中刪除第一行:

String.Join("\n", strXML.Split('\n').Skip(1).ToArray()) 

不優雅,但簡潔。

30

試試這個:

internal static string ToXml(object obj) 
{ 
    string retval = null; 
    if (obj != null) 
    { 
    StringBuilder sb = new StringBuilder(); 
    using(XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { OmitXmlDeclaration = true })) 
    { 
     new XmlSerializer(obj.GetType()).Serialize(writer, obj); 
    } 
    retval = sb.ToString(); 
    } 
    return retval; 
} 
2

如果你不想依賴於XML作家性能方面的原因等等,你可以這樣做:

// Read into memory stream and set namespaces to empty strings 
XmlSerializerNamespaces nsSerializer = new XmlSerializerNamespaces(); 
nsSerializer.Add(string.Empty, string.Empty); 
XmlSerializer xs = new XmlSerializer(typeof(Model.AudioItem)); 
xs.Serialize(ms, item, nsSerializer); 

// Read into UTF-8 stream and read off first line (i.e "<?xml version="1.0"?>") 
StreamReader sr = new StreamReader(ms); 
ms.Position = 0; 
sr.ReadLine(); 

sr.ReadToEnd()的ToString( )現在包含裸序列號

-1
if (!string.IsNullOrEmpty(strXML) && strXML.Contains(@"<?xml")) 
strXML = strXML.Remove(0, strXML.IndexOf(@"?>", 0) + 2);