2011-06-07 16 views
14

Por alguna razón el siguiente código produce XML que no contenga una declaración:¿Dónde está mi XDeclaration?

 XDocument xDocument = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), 
      new XElement("project", 
       new XAttribute("number", project.ProjectNumber), 
       new XElement("store", 
        new XAttribute("number", project.StoreNumber) 
       ), 

       // User Element 
       new XElement("user", 
        new XAttribute("owner-id", project.OwnerID ?? 0), 
        new XElement("email", new XCData(project.OwnerEmail ?? "")), 
        new XElement("project-name", new XCData(project.ProjectName ?? "")) 
       ), 

       // Nested Project Element 
       new XElement("nested-project", 
        new XAttribute("version", new Version(1, 0)), 
        new XElement("project", 
         new XAttribute("version", new Version(1, 0)), 
         xProjectItems = new XElement("project-items") 
        ), 
        new XElement("price-per-part", project.PricePerPart), 
        new XElement("sheet-quantity", project.SheetQuantity), 
        new XElement("edge-length", project.EdgeLength), 
        new XElement("price", project.Price), 
        new XElement("status", project.Status), 
        xMaterialItems = new XElement("alternative-material-items"), 
        xProductItems = new XElement("project-product-items") 
       ) 
      ) 
     ); 

     String strXML = xDocument.ToString(); 

Se ha producido una declaración antes. ¿Me estoy perdiendo algo obvio?

Gracias.

Respuesta

23

La XDeclaration estará disponible cuando utilice uno de los XDocument.Save methods. Por ejemplo:

var doc = new XDocument (
      new XDeclaration ("1.0", "utf-8", "yes"), 
      new XElement ("test", "data") 
     ); 

string path = Path.Combine(Path.GetTempPath(), "temp.xml"); 
doc.Save(path); 
Console.WriteLine(File.ReadAllText(path)); 

Alternativamente, usted podría utilizar este enfoque:

var sw = new StringWriter(); 
doc.Save(sw); 
string result = sw.GetStringBuilder().ToString(); 
Console.WriteLine(result); 

EDIT: nota que algunos enfoques convertir la designación UTF-8 a UTF-16. Si desea forzar que sea UTF-8 que tendría que utilizar este enfoque diferente:

using (var mem = new MemoryStream()) 
using (var writer = new XmlTextWriter(mem, System.Text.Encoding.UTF8)) 
{ 
    writer.Formatting = Formatting.Indented; 
    doc.WriteTo(writer); 
    writer.Flush(); 
    mem.Flush(); 
    mem.Seek(0, SeekOrigin.Begin); 
    using (var reader = new StreamReader(mem)) 
    { 
     var xml = reader.ReadToEnd(); 
     Console.WriteLine(xml); 
    } 
} 
+0

+1 Debería haber usado un StringWriter en mi respuesta. Doh! =] – rsbarro

+1

Eso es cojo. No es tu solución (lo cual es genial, no me di cuenta de que podrías hacer eso con un 'StringWriter'). Es cojo que Microsoft hiciera eso. No guardo este XML en un archivo, lo paso a una transmisión. ¿Cuál es la diferencia entre un 'XDocument' y un 'XElement'? Quiero decir que es bueno que sean iguales, pero debería haber alguna distinción. Y si alguien no quiere la declaración en la cadena, simplemente podría hacer: 'xMyDocument.Root.ToString();' – Jordan

+0

@Jordan Supongo que el razonamiento es que un XDocument representa un documento completo, y un XElement es un fragmento de XML. A pesar de eso, son muy similares. –

3

El documentation no establece explícitamente que xDocument.ToString() dará salida a la declaración XML, sólo dice: "Devuelve el código XML con sangría para este nodo ".

En mis pruebas, he encontrado que los métodos siguientes tendrán salida de la declaración:

Uso ToString en la propiedad Declaration:

string strXML = string.Concat(xDocument.Declaration.ToString(), "\r\n", 
           xDocument.ToString()); 

o utilizar el Save método:

string strXml; 
using(var ms = new MemoryStream()) 
{ 
    xDocument.Save(ms); 
    ms.Position = 0; 
    using(var sr = new StreamReader(ms)) 
    { 
     strXml = sr.ReadToEnd(); 
    } 
} 
+0

Nota: Creo que el enfoque de @Ahmad Mageed con 'StringWriter' es el camino a seguir. La misma idea pero más corta que mi método 'Guardar'. – rsbarro

+0

+1 por el esfuerzo. Supongo que hay un caso para el enfoque más largo, como se muestra en mi edición, cuando se necesita forzar la codificación. –

Cuestiones relacionadas