2009-09-15 19 views
12

estoy usando este método para serializar mi objetivo:¿Cómo controlo la parte <?xml ?> de la serialización xml con .NET?

public static string XmlSerialize(object o) 
{ 
    var stringWriter = new StringWriter(); 
    var xmlSerializer = new XmlSerializer(o.GetType()); 
    xmlSerializer.Serialize(stringWriter, o); 
    string xml = stringWriter.ToString(); 
    stringWriter.Close(); 
    return xml; 
} 

Hace XML que comienza así:

<?xml version="1.0" encoding="utf-16"?> 
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 

Pero yo quiero que se vea como esto:

<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?> 
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

Entonces, ¿cómo cambio la codificación a Windows-1252 y establezco standalone = yes? Además, ¿cómo consigo que el objeto excluya el valor xmlns?

He visto un par de preguntas similares, como this one, pero esperaba que pudiera ser más simple para mí, tal vez estableciendo algunos atributos en alguna parte.

Actualización 2: Después de ver las respuestas y los comentarios de John, y pensando en esto más, decidí simplemente hacer un segundo método. No creo que la creación de este extravagante xml personalizado solo para una tercera parte en una ocasión deba llamarse algo tan genérico como "XmlSerialize" en primer lugar.

tanto, he creado un segundo método que toma un documento XML y en primer lugar, elimina el elemento de un espacio de nombres como esto:

xElement.Attributes().Where(a => a.IsNamespaceDeclaration && a.Value == "http://www.w3.org/2001/XMLSchema").Remove(); 

entonces, que lo escribe en XML con código de Juan. Finalmente devuelve ese xml, tras la salida de este:

new XDeclaration("1.0", "Windows-1252", "yes").ToString() 

Y eso es feo, pero me pone exactamente lo que necesito para esta tercera parte para entender mi XML.

+0

Realmente, use 'XmlReader.Create' y' XmlWriter.Create' en lugar de 'XmlTextReader' y' XmlTextWriter'. Además, debe colocar estas cosas en bloques 'using'. –

+0

En última instancia, fui con su código. Pero me pregunto, siempre que cierre todo, ¿no es eso tan bueno como usar bloques? – Chris

+0

No. Los bloques 'using' se aseguran de que los objetos se eliminen, incluso cuando ocurran excepciones. –

Respuesta

25

Prueba esto:

public static string XmlSerialize(object o) 
{ 
    using (var stringWriter = new StringWriter()) 
    { 
     var settings = new XmlWriterSettings 
          { 
           Encoding = Encoding.GetEncoding(1252), 
           OmitXmlDeclaration = true 
          }; 
     using (var writer = XmlWriter.Create(stringWriter, settings)) 
     { 
      var xmlSerializer = new XmlSerializer(o.GetType()); 
      xmlSerializer.Serialize(writer, o); 
     } 
     return stringWriter.ToString(); 
    } 
} 

Esto no va a deshacerse de la xsd: espacio de nombres, pero entonces, ¿por qué quiere?


Actualización: Parece que cada vez que se utiliza un StringWriter, se obtiene UTF-16, incluso si se utiliza un XmlWriter encima de él con el conjunto de codificación. El siguiente paso sería escribir en un MemoryStream. Pero eso plantea la pregunta de por qué quieres devolver una cadena. Por ejemplo, si va a dar la vuelta y enviar la cadena a una transmisión, deberíamos enviarla directamente a esta transmisión. Lo mismo para un TextWriter.

+0

Estoy usando una API y han especificado que la cosa xsd no debería estar ahí. Por qué no lo quieren y por qué no pueden simplemente ignorarlo, no tengo ni idea. – Chris

+0

John, no quiero deshacerme de la declaración xml. Quiero conservarlo y cambiar lo que se genera. – Chris

+2

Deshágase de OmitXmlDeclaration = true, y debería devolver la declaración. Necesitas patear a tu gente API ** realmente duro ** si se atragantan con la declaración xsd. Será necesario si se debe especificar xsi: tipo. Si no todos seguimos los estándares, pronto XML no será estándar en absoluto. –

2

Puede usar un XmlTextWriter en lugar de un StringWriter. Aquí hay un extracto de algunos de mis códigos con su conjunto de codificación.

XmlTextWriter textWriter = new XmlTextWriter(stream, Encoding.GetEncoding(1252)); 
textWriter.Namespaces = false; 
+3

'XmlTextWriter' ya no se debe usar, a partir de .NET 2.0. –

0

FWIW, obtuve la codificación para trabajar usando un XmlWriter con XMLWriterSettings. Este es un ejemplo:

... 
// My object type was from a class generated by xsd. 
XmlSerializer xms = new XmlSerializer(typeof(SomeType)); 
SomeType objSt; 
using(FileStream fs = new FileStream("C:\SomeFile.xml", FileMode.Open, FileAccess.Read)) 
{  
    using(XmlReader xr = XmlReader.Create(fs)) // Supposed to preserve encoding. 
    { 
    objSt = (SomeType)xms.Deserialize(xr); 
    }  
} 

... 
... // Do some stuff, change some attribute values. 
... 

XmlWriterSettings xsw= new XmlWriterSettings(); 
xsw.Indent= true; 
xsw.NewLineOnAttributes= true; 
xsw.Encoding = Encoding.GetEncoding(1252); 
using(XmlWriter xwXsw = XmlWriter.Create("C:\SomeFile_Changed.xml",xsw)) 
{  
    xms.Serialize(xwXsw, objSt); 
} 
... 
... // Finish up and get out. 
... 

Por alguna razón, yo era capaz de conseguir que todo funcione una vez sólo con el objeto XmlSerializer serializar y con un TextWriter, ya que de acuerdo con la EM ayuda para XmlSerializer.Deserialize (XmlReader) " XmlReader detecta y usa automáticamente la codificación especificada por el documento XML ". Luego comencé a jugar con XmlWriterSettings y rompí algo ...

+0

A tardía -1 por no poner FileStream, 'XmlReader' y' XmlWriter' en bloques 'using'. –

+0

Cool - pero el comentario dice explícitamente "sin manejo de excepción o" usando "". No estoy seguro de por qué lo hice de esa manera, hace mucho tiempo. No quise herir tus sentimientos :) – GTAE86

+0

¿A qué comentario te refieres? –

Cuestiones relacionadas