Сериализация XML XML без текстового объявления <? Xml>
Я пытаюсь создать XML следующим образом:
<?xml version="1.0"?>
<!DOCTYPE APIRequest SYSTEM
"https://url">
<APIRequest>
<Head>
<Key>123</Key>
</Head>
<ObjectClass>
<Field>Value</Field
</ObjectClass>
</APIRequest>
У меня есть класс (ObjectClass), украшенный атрибутами 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>
то есть. оператор serialize автоматически добавляет текстовое объявление <? XML.
Я знаю, что нападаю на это неправильно, может ли кто-то указать мне в правильном направлении?
В качестве примечания я не думаю, что практический смысл состоит в том, чтобы просто сделать класс APIRequest с ObjectClass в нем (потому что, как говорят 20 различных типов ObjectClass, каждый из них нуждается в этом шаблоне вокруг них), но исправьте меня, если Я ошибаюсь.
Ответы
Ответ 1
Никогда не создавайте 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; }
}
Ответ 2
попробуйте следующее:
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;
}
Ответ 3
Если вы не хотите полагаться на создателя 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() теперь содержит голую сериализацию
Ответ 4
Выведите собственный 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
Вызовите Serialize с экземпляром полученного MyXmlTextWriter.
Dim tw As New MyXmlTextWriter(sb)
Dim objXmlSerializer As New XmlSerializer(type)
objXmlSerializer.Serialize(tw, obj)
Ответ 5
Скотт Гензельман получил хороший пост на этом. Я использовал пример Kzu (на что указывает блог Скотта) некоторое время назад для одного и того же, и он отлично работал.
Ответ 6
if (!string.IsNullOrEmpty(strXML) && strXML.Contains(@"<?xml"))
strXML = strXML.Remove(0, strXML.IndexOf(@"?>", 0) + 2);
Ответ 7
Один вкладыш, чтобы удалить первую строку из строки:
String.Join("\n", strXML.Split('\n').Skip(1).ToArray())
Не элегантный, но лаконичный.