.net - reglas - xml distingue entre mayusculas y minusculas
.NET SerializaciĆ³n XML sin<? Xml> declaraciĆ³n de texto (7)
Derive su propio XmlTextWriter para omitir la declaración 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
Llame a Serialize con una instancia del MyXmlTextWriter derivado.
Dim tw As New MyXmlTextWriter(sb)
Dim objXmlSerializer As New XmlSerializer(type)
objXmlSerializer.Serialize(tw, obj)
Estoy tratando de generar XML de esta manera:
<?xml version="1.0"?>
<!DOCTYPE APIRequest SYSTEM
"https://url">
<APIRequest>
<Head>
<Key>123</Key>
</Head>
<ObjectClass>
<Field>Value</Field
</ObjectClass>
</APIRequest>
Tengo una clase (ObjectClass) decorada con atributos de serialización XML como este:
[XmlRoot("ObjectClass")]
public class ObjectClass
{
[XmlElement("Field")]
public string Field { get; set; }
}
Y mi pensamiento intuitivo realmente intrincado para hacer que esto funcione es hacer esto cuando serialice:
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>");
Sin embargo, esto genera XML de esta manera:
<?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>
es decir, la declaración de serialización agrega automáticamente una declaración de texto <? xml.
Sé que estoy atacando esto mal, ¿puede alguien dirigirme en la dirección correcta?
Como nota, no creo que tenga sentido práctico simplemente hacer una clase APIRequest con un ObjectClass (porque hay 20 tipos diferentes de ObjectClass que necesitan esta repetición), pero corríjame si estoy incorrecto.
Nunca compile xml usando la concatenación de cadenas. Es malvado
Salida:
<?xml version="1.0" encoding="utf-16"?>
<!DOCTYPE APIRequest SYSTEM "https://url">
<APIRequest>
<Head>
<Key>123</Key>
</Head>
<ObjectClass>
<Field>Value</Field>
</ObjectClass>
</APIRequest>
Código:
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; }
}
Si no desea confiar en un escritor xml por razones de rendimiento, etc., puede hacer esto:
// 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 () ahora contiene la serialización simple
Un trazador de líneas, para eliminar la primera línea de una cadena:
String.Join("/n", strXML.Split(''/n'').Skip(1).ToArray())
No elegante, pero conciso.
prueba esto:
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;
}
Scott Hanselman tiene un buen post en esto. Utilicé el ejemplo de Kzu (que señala el blog de Scott) hace un tiempo para la misma cosa y funcionó muy bien.
if (!string.IsNullOrEmpty(strXML) && strXML.Contains(@"<?xml"))
strXML = strXML.Remove(0, strXML.IndexOf(@"?>", 0) + 2);