c# - XDocument: guardar XML en un archivo sin BOM
linq-to-xml byte-order-mark (3)
Estoy generando un archivo XML utf-8 usando XDocument
.
XDocument xml_document = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement(ROOT_NAME,
new XAttribute("note", note)
)
);
...
xml_document.Save(@file_path);
El archivo se genera correctamente y se valida con un archivo xsd con éxito.
Cuando intento cargar el archivo XML en un servicio en línea, el servicio dice que mi archivo es wrong at line 1
; Descubrí que el problema se debe a la lista de materiales en los primeros bytes del archivo.
¿Sabe por qué se adjunta la lista de materiales al archivo y cómo puedo guardar el archivo sin él?
Como se indica en el artículo de Wikipedia de la marca de orden de bytes :
Si bien el estándar Unicode permite BOM en UTF-8 , no lo requiere ni lo recomienda . El orden de bytes no tiene significado en UTF-8, por lo que una lista de materiales solo sirve para identificar una secuencia de texto o un archivo como UTF-8 o que se convirtió de otro formato que tiene una lista de materiales
¿Es un problema de XDocument
o debo comunicarme con los proveedores del servicio en línea para solicitar una actualización del analizador?
La forma más conveniente de deshacerse del carácter de la lista de materiales cuando se utiliza XDocument es simplemente guardar el documento, luego hacer una lectura directa del archivo como un archivo y luego volver a escribirlo. Las rutinas de archivo eliminarán el carácter por ti:
XDocument xTasks = new XDocument();
XElement xRoot = new XElement("tasklist",
new XAttribute("timestamp",lastUpdated),
new XElement("lasttask",lastTask)
);
...
xTasks.Add(xRoot);
xTasks.Save("tasks.xml");
// read it straight in, write it straight back out. Done.
string[] lines = File.ReadAllLines("tasks.xml");
File.WriteAllLines("tasks.xml",lines);
(Es un asco, pero funciona por razones de conveniencia, al menos tendrá un archivo bien formado para cargar a su proveedor en línea).
Primero que todo: el proveedor de servicios DEBE manejarlo, de acuerdo con la especificación XML, que establece que la lista de materiales puede estar presente en caso de representación UTF-8.
Puede obligar a guardar su XML sin BOM de esta manera:
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = new UTF8Encoding(false); // The false means, do not emit the BOM.
using (XmlWriter w = XmlWriter.Create("my.xml", settings))
{
doc.Save(w);
}
(Googled desde aquí: http://social.msdn.microsoft.com/Forums/en/xmlandnetfx/thread/ccc08c65-01d7-43c6-adf3-1fc70fdb026a )
Use un XmlTextWriter
y páselo al método Save () de XDocument, de esa manera puede tener más control sobre el tipo de codificación utilizada:
var doc = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement("root", new XAttribute("note", "boogers"))
);
using (var writer = new XmlTextWriter(".//boogers.xml", new UTF8Encoding(false)))
{
doc.Save(writer);
}
El constructor de la clase UTF8Encoding
tiene una sobrecarga que especifica si se usa o no la BOM (marca de orden de bytes) con un valor booleano, en su caso false
.
El resultado de este código se verificó utilizando Notepad ++ para inspeccionar la codificación del archivo.