O código fica assim:
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);
}
O documento serializado resultante inclui espaços para nome, assim:
<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns="urn:something">
...
</message>
Para remover os namespaces xsi e xsd, posso seguir a resposta em Como serializar um objeto para XML sem obter xmlns = ”…”? .
Quero minha tag de mensagem como <message>
(sem nenhum atributo de espaço para nome). Como posso fazer isso?
c#
.net
xml-serialization
NetSide
fonte
fonte
Respostas:
fonte
s.Serialize(writer, objectToSerialize, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty }));
Esta é a segunda de duas respostas.
Se você deseja remover todos os namespaces arbitrariamente de um documento durante a serialização, pode fazer isso implementando seu próprio XmlWriter.
A maneira mais fácil é derivar do XmlTextWriter e substituir o método StartElement que emite espaços para nome. O método StartElement é chamado pelo XmlSerializer ao emitir qualquer elemento, incluindo a raiz. Substituindo o espaço para nome de cada elemento e substituindo-o pela string vazia, você removeu os espaços para nome da saída.
Suponha que este seja o tipo:
Aqui está como você usaria isso durante a serialização:
O XmlTextWriter está meio que quebrado, no entanto. De acordo com o documento de referência , ao escrever, não verifica o seguinte:
Esses problemas com o XmlTextWriter existem desde a v1.1 do .NET Framework e permanecerão para compatibilidade com versões anteriores. Se você não tiver preocupações com esses problemas, use o XmlTextWriter. Mas a maioria das pessoas gostaria de um pouco mais de confiabilidade.
Para conseguir isso, enquanto ainda suprime os espaços para nome durante a serialização, em vez de derivar do XmlTextWriter, defina uma implementação concreta do XmlWriter abstrato e de seus 24 métodos.
Um exemplo está aqui:
Em seguida, forneça uma classe derivada que substitua o método StartElement, como antes:
E então use este escritor assim:
Crédito por isso a Oleg Tkachenko .
fonte
LookupPrefix(string ns)
para sempre retornar uma string vazia para remover todas as declarações de esquema.XmlWriter
eXmlWriterSettings
.Depois de ler a documentação da Microsoft e várias soluções online, descobri a solução para esse problema. Ele funciona com a
XmlSerializer
serialização XML interna e personalizada viaIXmlSerialiazble
.Ou seja, usarei a mesma
MyTypeWithNamespaces
amostra XML usada nas respostas até agora.Isso é tudo nessa classe. Agora, alguns se opuseram a ter um
XmlSerializerNamespaces
objeto em algum lugar dentro de suas classes; mas, como você pode ver, coloquei-o ordenadamente no construtor padrão e expus uma propriedade pública para retornar os namespaces.Agora, quando chegar a hora de serializar a classe, você usaria o seguinte código:
Depois de fazer isso, você deverá obter a seguinte saída:
Usei esse método com êxito em um projeto recente com uma hierarquia profunda de classes serializadas em XML para chamadas de serviço da web. A documentação da Microsoft não é muito clara sobre o que fazer com o
XmlSerializerNamespaces
membro publicamente acessível depois que você a criou, e muitos pensam que é inútil. Porém, seguindo a documentação e usando-a da maneira mostrada acima, você pode personalizar como o XmlSerializer gera XML para suas classes sem recorrer a um comportamento não suportado ou a serialização "rolando sua própria" implementandoIXmlSerializable
.Espero que esta resposta descanse, de uma vez por todas, como se livrar do padrão
xsi
e dosxsd
namespaces gerados peloXmlSerializer
.ATUALIZAÇÃO: Eu só quero ter certeza de que respondi à pergunta do OP sobre como remover todos os espaços para nome. Meu código acima funcionará para isso; Deixa-me mostrar-te como. Agora, no exemplo acima, você realmente não pode se livrar de todos os namespaces (porque existem dois namespaces em uso). Em algum lugar do seu documento XML, você precisará ter algo parecido
xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo
. Se a classe no exemplo fizer parte de um documento maior, algum lugar acima de um espaço para nome deverá ser declarado para um (ou ambos)Abracadbra
eWhoohoo
. Caso contrário, o elemento em um ou em ambos os espaços para nome deve ser decorado com um prefixo de algum tipo (você não pode ter dois espaços para nome padrão, certo?). Portanto, para este exemplo,Abracadabra
é o namespace defalt. Eu poderia dentro da minhaMyTypeWithNamespaces
classe adicionar um prefixo de namespace para oWhoohoo
namespace da seguinte forma:Agora, na minha definição de classe, indiquei que o
<Label/>
elemento está no espaço"urn:Whoohoo"
para nome , portanto, não preciso fazer mais nada. Quando agora serializo a classe usando meu código de serialização acima inalterado, esta é a saída:Como
<Label>
está em um espaço para nome diferente do restante do documento, ele deve, de alguma maneira, ser "decorado" com um espaço para nome. Observe que ainda não existem espaços para nomexsi
exsd
.fonte
XmlWriter
que está contido noXmlMediaTypeFormatter
que força os namespaces xsi e xsd na minha saída independentemente. Isso afeta apenas aqueles que usam o padrão da WebApiXmlMediaTypeFormatter
. Copiei o código-fonte e modifiquei-o para passar minha propriedade Namespaces para o método Serialize, conforme necessário, para impedir aXmlWriter
adição automática dos dois padrões. Veja esta respostaXmlSerializerNamespaces
decorado com oXmlNamespacesDeclarationAttribute
. Isso foi tirado diretamente do MSDN e, essencialmente, usa os espaços para nome declarados no lugar dos espaços padrão fornecidos peloXmlSerializer
.Esta é a primeira das minhas duas respostas à pergunta.
Se você deseja um controle fino sobre os espaços para nome - por exemplo, se deseja omitir alguns deles, mas não outros, ou se deseja substituir um espaço para nome por outro, você pode fazer isso usando XmlAttributeOverrides .
Suponha que você tenha esta definição de tipo:
E esse pseudo-código de serialização:
Você obteria algo como este XML:
Observe que há um espaço para nome padrão no elemento raiz e também um espaço para nome distinto no elemento "Label". Esses namespaces foram determinados pelos atributos que decoram o tipo, no código acima.
A estrutura de serialização de XML no .NET inclui a possibilidade de substituir explicitamente os atributos que decoram o código real. Você faz isso com a classe XmlAttributesOverrides e amigos. Suponha que eu tenha o mesmo tipo e eu o serialize desta maneira:
O resultado é assim;
Você removeu os espaços para nome.
Uma pergunta lógica é: você pode retirar todos os namespaces de tipos arbitrários durante a serialização, sem passar pelas substituições explícitas? A resposta é SIM, e como fazê-lo está na minha próxima resposta.
fonte
fonte