2009-06-05 16 views
98

Tengo un servicio WCF que necesita devolver una cadena de XML. Pero parece que el escritor solo quiere construir un archivo, no una cadena. Intenté:XmlWriter para escribir en una cadena en lugar de en un archivo

string nextXMLstring = ""; 
using (XmlWriter writer = XmlWriter.Create(nextXMLstring)) 

Esto genera un error diciendo que nextXMLstring no tiene una ruta de archivo. Quiere algo como:

using (XmlWriter writer = XmlWriter.Create("nextXMLstring.xml")) 

¿Cómo puedo construir mi XML y luego devolverlo como una cadena?

Gracias!

Respuesta

178

Necesita crear un StringWriter y pasarlo al XmlWriter.

La sobrecarga de cadena de XmlWriter.Create es para un nombre de archivo.

E.g.

using (var sw = new StringWriter()) { 
    using (var xw = XmlWriter.Create(sw)) { 
    // Build Xml with xw. 


    } 
    return sw.ToString(); 
} 
+2

@Will: redujo el cambio. XmlTextWriter.Close() se va a enjuagar a la secuencia, por lo que quiere que suceda antes de extraer la cadena. (Poca diferencia en este caso, pero prefiere hacerlo de forma consistente porque la semántica de enjuague de las clases * Writer y Stream no siempre está claramente documentada). – Richard

+1

Solo un comentario para las personas que usan esto. Si omite el uso de() y en su lugar declara su XmlWriter normalmente, asegúrese de llamar a xw.Flush antes de llamar a sw.ToString() o de lo contrario, puede que no obtenga todo el contenido. (Obviamente, es mejor utilizar los corchetes de uso ...) – Ravendarksky

+0

Tenga en cuenta que el siguiente código da CA2202 advertencia durante el análisis del código, porque el método Dispose() se llamará dos veces en el objeto StringWriter –

100

Como dijo Richard, StringWriter es el camino a seguir. Sin embargo, hay una pega: de forma predeterminada, StringWriter se anunciará como UTF-16. Generalmente XML está en UTF-8. Puede solucionar esto creando una subclase de StringWriter;

public class Utf8StringWriter : StringWriter 
{ 
    public override Encoding Encoding 
    { 
     get { return Encoding.UTF8; } 
    } 
} 

Esto afectará a la declaración escrita por XmlWriter. Por supuesto, si luego escribes la cadena en otro lugar en forma binaria, asegúrate de usar una codificación que coincida con la codificación que arregles para el StringWriter. (El código anterior supone siempre UTF-8, es trivial para hacer una versión más general que acepta una codificación en el constructor.)

Se podría entonces utilizar:

using (TextWriter writer = new Utf8StringWriter()) 
{ 
    using (XmlWriter xmlWriter = XmlWriter.Create(writer)) 
    { 
     ... 
    } 
    return writer.ToString(); 
} 
+5

+1 Esto a menudo se pasa por alto y es importante saber . –

+0

Eso sería 'sobrescritura pública Codificación de codificación'. – Einar

+0

@Einar: Gracias, corregido. –

23

Sé que esto es viejo y respondió, pero aquí hay otra manera de hacerlo. En particular, si usted no quiere que la lista de materiales UTF8 en el inicio de la cadena y desea que el texto sangrado:

using (var ms = new MemoryStream()) 
{ 
    using (var x = new XmlTextWriter(ms, new UTF8Encoding(false)) 
           { Formatting = Formatting.Indented }) 
    { 
       // ... 
       return Encoding.UTF8.GetString(ms.ToArray()); 
    } 
} 
+3

'Encoding.UTF8.GetString (ms.ToArray())' es una simplificación a su regreso. – SliverNinja

+0

@SliverNinja ¡Agradable! Adicional. – brianary

+1

'ms.ToArray()' no devuelve ningún elemento cuando intenté esto. Tuve que agregar 'x.Close()' o mover la declaración return fuera de la instrucción using interna. –

8

Uso StringBuilder:

var sb = new StringBuilder(); 
    using (XmlWriter xmlWriter = XmlWriter.Create(sb)) 
    { 
     ... 
    } 
return sb.ToString(); 
0

chicos no se olvide de llamar xmlWriter.Close() y xmlWriter.Dispose() o de lo contrario su cadena no terminará de crearse. Solo será una cadena vacía

+0

No se preocupe, using statement se encargará de la eliminación del objeto. –

+0

Esta es una pregunta de 2009. Por lo tanto, el valor de brindar una respuesta ahora sería para futuros usuarios que puedan tener problemas similares. En consecuencia, las respuestas a preguntas antiguas como esta solo deberían proporcionarse si pueden identificar claramente el problema y explicar/proporcionar una solución. Por lo general, es inútil tratar de involucrar al OP en una conversación, ya que es probable que hayan avanzado. – MikeC

Cuestiones relacionadas