El código se ve así:
StringBuilder builder = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
using (XmlWriter xmlWriter = XmlWriter.Create(builder, settings))
{
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
s.Serialize(xmlWriter, objectToSerialize);
}
El documento serializado resultante incluye espacios de nombres, así:
<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns="urn:something">
...
</message>
Para eliminar los espacios de nombres xsi y xsd, puedo seguir la respuesta de ¿Cómo serializar un objeto a XML sin obtener xmlns = "..."? .
Quiero mi etiqueta de mensaje como <message>
(sin ningún atributo de espacio de nombres). ¿Cómo puedo hacer esto?
c#
.net
xml-serialization
NetSide
fuente
fuente
Respuestas:
fuente
s.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Esta es la segunda de dos respuestas.
Si desea eliminar todos los espacios de nombres de forma arbitraria de un documento durante la serialización, puede hacerlo implementando su propio XmlWriter.
La forma más fácil es derivar de XmlTextWriter y anular el método StartElement que emite espacios de nombres. XmlSerializer invoca el método StartElement al emitir cualquier elemento, incluida la raíz. Al anular el espacio de nombres para cada elemento y reemplazarlo con la cadena vacía, ha eliminado los espacios de nombres de la salida.
Supongamos que este es el tipo:
Así es como usaría tal cosa durante la serialización:
Sin embargo, XmlTextWriter está roto. Según el documento de referencia , cuando escribe no verifica lo siguiente:
Estos problemas con XmlTextWriter han existido desde la v1.1 de .NET Framework, y seguirán siendo compatibles con versiones anteriores. Si no le preocupan esos problemas, entonces utilice XmlTextWriter. Pero a la mayoría de la gente le gustaría un poco más de fiabilidad.
Para obtener eso, mientras suprime los espacios de nombres durante la serialización, en lugar de derivar de XmlTextWriter, defina una implementación concreta del resumen XmlWriter y sus 24 métodos.
Un ejemplo está aquí:
Luego, proporcione una clase derivada que anule el método StartElement, como antes:
Y luego usa este escritor así:
Gracias por esto a Oleg Tkachenko .
fuente
LookupPrefix(string ns)
para devolver siempre una cadena vacía para eliminar todas las declaraciones de esquema.XmlWriter
yXmlWriterSettings
.Después de leer la documentación de Microsoft y varias soluciones en línea, descubrí la solución a este problema. Funciona con la
XmlSerializer
serialización XML incorporada y personalizada a través deIXmlSerialiazble
.A saber, utilizaré la misma
MyTypeWithNamespaces
muestra XML que se ha utilizado en las respuestas a esta pregunta hasta ahora.Eso es todo para esta clase. Ahora, algunos se opusieron a tener un
XmlSerializerNamespaces
objeto en algún lugar dentro de sus clases; pero como puede ver, lo guardé cuidadosamente en el constructor predeterminado y expuse una propiedad pública para devolver los espacios de nombres.Ahora, cuando llegue el momento de serializar la clase, usaría el siguiente código:
Una vez que haya hecho esto, debería obtener el siguiente resultado:
He utilizado con éxito este método en un proyecto reciente con una gran jerarquía de clases que se serializan en XML para llamadas de servicio web. La documentación de Microsoft no es muy clara sobre qué hacer con el
XmlSerializerNamespaces
miembro de acceso público una vez que lo ha creado, y muchos piensan que es inútil. Pero siguiendo su documentación y usándola de la manera que se muestra arriba, puede personalizar cómo XmlSerializer genera XML para sus clases sin recurrir a comportamientos no admitidos o "rodar su propia" serialización mediante la implementaciónIXmlSerializable
.Espero que esta respuesta deje de lado, de una vez por todas, cómo deshacerse del estándar
xsi
y losxsd
espacios de nombres generados porXmlSerializer
.ACTUALIZACIÓN: Solo quiero asegurarme de haber respondido la pregunta del OP sobre la eliminación de todos los espacios de nombres. Mi código anterior funcionará para esto; Déjame enseñarte como. Ahora, en el ejemplo anterior, realmente no puede deshacerse de todos los espacios de nombres (porque hay dos espacios de nombres en uso). En algún lugar de su documento XML, necesitará tener algo como esto
xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo
. Si la clase en el ejemplo es parte de un documento más grande, entonces se debe declarar en algún lugar sobre un espacio de nombres para uno de (o ambos)Abracadbra
yWhoohoo
. De lo contrario, el elemento en uno o en ambos espacios de nombres debe estar decorado con un prefijo de algún tipo (no puede tener dos espacios de nombres predeterminados, ¿verdad?). Entonces, para este ejemplo,Abracadabra
es el espacio de nombres defalt. Podría dentro de miMyTypeWithNamespaces
clase agregar un prefijo de espacio de nombres para elWhoohoo
espacio de nombres de esta manera:Ahora, en mi definición de clase, indiqué que el
<Label/>
elemento está en el espacio de nombres"urn:Whoohoo"
, por lo que no necesito hacer nada más. Cuando ahora serializo la clase usando mi código de serialización anterior sin cambios, esta es la salida:Debido a que
<Label>
está en un espacio de nombres diferente del resto del documento, debe, de alguna manera, estar "decorado" con un espacio de nombres. Tenga en cuenta que todavía no hay espacios de nombresxsi
yxsd
.fuente
XmlWriter
es lo que está contenido en loXmlMediaTypeFormatter
que fuerza los espacios de nombres xsi y xsd en mi salida independientemente. Esto solo afecta a quienes usan el valor predeterminado de WebApiXmlMediaTypeFormatter
. Copié el código fuente y lo modifiqué para pasar mi propiedad de espacios de nombres al método Serialize, ya que era necesario para evitar queXmlWriter
agregaran automáticamente los dos valores predeterminados. Ver esta respuestaXmlSerializerNamespaces
decorado con elXmlNamespacesDeclarationAttribute
. Esto fue tomado directamente de MSDN y esencialmente usa esos espacios de nombres declarados en lugar de los predeterminados proporcionados porXmlSerializer
.Esta es la primera de mis dos respuestas a la pregunta.
Si desea un control preciso sobre los espacios de nombres, por ejemplo, si desea omitir algunos de ellos pero no otros, o si desea reemplazar un espacio de nombres con otro, puede hacerlo utilizando XmlAttributeOverrides .
Supongamos que tiene esta definición de tipo:
Y este pseudocódigo de serialización:
Obtendría algo como este XML:
Observe que hay un espacio de nombres predeterminado en el elemento raíz, y también hay un espacio de nombres distinto en el elemento "Etiqueta". Estos espacios de nombres fueron dictados por los atributos que decoran el tipo, en el código anterior.
El marco de serialización Xml en .NET incluye la posibilidad de anular explícitamente los atributos que decoran el código real. Lo haces con la clase XmlAttributesOverrides y amigos. Supongamos que tengo el mismo tipo y lo serializo de esta manera:
El resultado se ve así;
Has eliminado los espacios de nombres.
Una pregunta lógica es, ¿ puede eliminar todos los espacios de nombres de tipos arbitrarios durante la serialización, sin pasar por las anulaciones explícitas? La respuesta es SÍ, y cómo hacerlo está en mi próxima respuesta.
fuente
fuente