14 de maio de 2009

Trabalhando com XML - parte 4

Para finalizar essa série sobre a criação de XML através da implementação DOM do C#, falo aqui da exportação desse DOM para o formato texto.

A chave para a exportação é uma classe chamada XmlTextWriter que fica no namespace System.Xml. Ela possui um construtor que aceita dois parâmetros : um stream onde a gravação deve ser feita e o Encoding responsável pela gravação. Stream é uma classe abstrata que apenas define uma interface para auxiliar a gravação e a leitura de bytes; por isso, devemos usar uma das heranças que faça efetivamente o trabalho.

A declaração a seguir é um exemplo que usa a herança chamada MemoryStream, que faz a leitura e gravação em memória:
Encoding enc = Encoding.UTF8;
MemoryStream ms = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter (ms, enc);

No contexto que utilizei esse código na ABC71, usar o MemoryStream era a opção mais conveniente. No entanto, há um construtor do XmlTextWriter que aceita um nome de arquivo como parâmetro. Nesse caso, o texto resultante será enviado diretamente para o arquivo.

Quando criei o cabeçalho para o XML no post anterior, informei o Encoding UTF-8, conforme especifica a documentação da Receita Federal. Porque, então, tenho que informá-lo novamente na gravação ? A questão é que a classe XmlTextWriter usará o Encoding para "transformar" os textos contidos no DOM e, se não o informarmos, um encoding padrão será utilizado para tal "transformação". Isto pode gerar caracteres incorretos, além de fazer com que o cabeçalho exportado contenha o nome do Encoding padrão ao invés daquele que informamos na montagem do XML, tornando-o inválido para a Receita Federal.

Então, informando novamente o Encoding para forçar o XmlTextWriter a gravar o cabeçalho com o valor que precisamos. Simultaneamente, nenhuma transformação é aplicada no conteúdo, preservando a integridade do XML. A classe Encoding usada no exemplo fica no namespace System.Text.

O próximo passo é configurar o XmlTextWriter para que o resultado atenda nossas necessidades. Veja o exemplo:
writer.Formatting = Formatting.Indented;
writer.Indentation = 2;
writer.Namespaces = true;

A primeira linha indica que a gravação deve ser feita de forma estruturada, identando os elementos do XML. A segunda estabelece quantos espaços em branco devem ser usados para identar os elementos. Se não quiser usar identação para que o tamanho do texto exportado seja menor, use Formatting.None na propriedade Formatting: todo o XML será gerado sem quebra de linhas e sem espaços em branco extras. Por fim, indico que há namepaces na estrutura e que eles devem constar no texto exportado. Na verdade, sem essa configuração o .NET levantará uma exceção (Exception) e não executará a exportação pois, se há namespaces informados no DOM, eles devem mesmo constar no texto resultante.

Para finalizar a exportação, falta ainda chamar o comando específico. Estou considerando que a variável doc é do tipo XmlDocument e contém a estrutura XML já montada, nos moldes descritos nos outros posts sobre XML (veja parte 2 e parte 3).
doc.WriteTo(writer);
writer.Flush();
writer.Close();

O resultado disso tudo é que o MemoryStream de nome ms agora contém todo o XML em formato texto, pronto para ser enviado, por exemplo, no corpo de um email ou exibido em tela.

Nenhum comentário :

Postar um comentário

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.

Observação: somente um membro deste blog pode postar um comentário.