11 de maio de 2009

Trabalhando com XML - parte 2

Como eu havia informado no post anterior sobre XML, vou mostrar aqui como criar um documento XML usando C#. O XML a ser criado será um fragmento do layout exigido pela Receita Federal para o envio de Notas Fiscais Eletrônicas; para facilitar, reproduzo novamente aqui o documento a ser criado :
<?xml version="1.0" encoding="UTF-8" ?>
<enviNFe versao="1.10" xmlns="http://www.portalfiscal.inf.br/nfe">
<idLote>71</idLote>
<NFe>
<infNFe Id="NFe3508059978"versao="1.10">
<cUF>35</cUF>
<cNF>518005127</cNF>
<natOp>Venda a vista</natOp>
<mod>55</mod>
<serie>1</serie>
<dEmi>2008-05-06</dEmi>
<tpAmb>2</tpAmb>
</infNFe>
</NFe>
</enviNFe>
Para iniciar, o pacote onde estão as classes para manipulação de XML através de DOM é o System.Xml. Portanto, é preciso informar isso no início do fonte.

using System.Xml;

O documento XML em si é representado por uma instância da classe XmlDocument. Também vamos usar bastante o namespace definido pela Receita Federal para suas estruturas, então, vou declarar uma constante para facilitar. Inclua as linhas abaixo na sua classe :
static string NFeNamespace = "http://www.portalfiscal.inf.br/nfe";
private XmlDocument doc = new XmlDocument();

O primeiro passo na criação é criar o nó raiz. No nosso exemplo, é como segue :
XmlElement raiz, no, noNFe, noInfNFe;
XmlAttribute att;
raiz = doc.CreateElement("enviNFe", NFeNamespace);
// Atributos do nó de enviNFe
att = doc.CreateAttribute("versao");
att.Value = "1.10";
raiz.Attributes.Append(att);

Note que criei manualmente apenas o atributo versao enquanto o xmlns (namespace) é colocado automaticamente pelo parâmetro passado ao CreateElement. Todos os "nós filhos" compartilharão essa informação de namespace.

Vamos criar agora o elemento idLote, que possui um valor associado :
XmlText noText;
no = doc.CreateElement("idLote", NFeNamespace);
noText = doc.CreateTextNode("71");
no.AppendChild(noText);
// "Nó" é filho de raiz :
raiz.AppendChild(no);

Observe que continua imprescindível passar o namespace na criação do nó idLote; se não for informado, subentende-se que um novo namespace (vazio) deve ser usado.

As mesmas regras vistas até agora valem para criar o nó NFe e o nó infNFe e seus filhos:
// infNFE
noInfNFe = doc.CreateElement("infNFe", NFeNamespace);
att = doc.CreateAttribute("Id");
att.Value = "NFe3508059978";
noInfNFe.Attributes.Append(att);

att = doc.CreateAttribute("versao");
att.Value = "1.10";
noInfNFe.Attributes.Append(att);

// Filhos do infNFE
no = doc.CreateElement("cUF", NFeNamespace);
noText = doc.CreateTextNode("35");
no.AppendChild(noText);
noInfNFe.AppendChild(no);

no = doc.CreateElement("cNF", NFeNamespace);
noText = doc.CreateTextNode("518005127");
no.AppendChild(noText);
noInfNFe.AppendChild(no);

// *** Inclua os demais campos aqui ....

// Hierarquia de nós

noNFe = doc.CreateElement("NFe", NFeNamespace);
noNFe.AppendChild(noInfNFe);
raiz.AppendChild(noNFe);

Para finalizar, é preciso ainda informar ao XmlDocument quem é seu nó raiz:
doc.AppendChild (raiz);

Para não me estender muito, publico no próximo post como incluir o cabeçalho para o XML e como transformar a estrutura DOM num texto que possa ser salvo em arquivo ou transmitido como parâmetro num WebService.

5 comentários :

akantos disse...

Marcelo, achei legal a forma que você monta XML. Eu fiz de uma forma diferente usando Annotation em interfaces e classes.

[XmlRoot("infNFe")]
public class infNFe
{ }

Depois do objeto populado, mandei serializar. Através de interfaces, consegui mandar as instâncias desses objetos serializaveis para as funcionalidades de banco de dados e web services... além de mais semântico, ficou fácil dar manutenção e extender...

Valeu o Post! Legal saber como as pessoas estão fazendo também.

Anônimo disse...

Opa vc ainda esta usando esse blog? segui o exemplo e fiquei com um duvida, se tiver respondendo ainda por favor avise.

Luís Gustavo Fabbro disse...

A forma de usar o DOM exposta no post é mais padrão pois ela acaba indenpendendo da linguagem que você está usando. Deve haver apenas pequenas diferenças nos nomes das funções - como no uso de maiúsculas e minúsculas. Assim, é possível adotar o mesmo tipo de lógica de programação em .NET, Delphi ou Java.

Anônimo disse...

Não seria melhor serializar sua classe e gerar o xml ?
ou usar XmlTextWriter?

Luís Gustavo Fabbro disse...

Outras pessoas tb levantaram essa questão. Na verdade, qualquer solução que gere corretamente o XML é válida. Optei pela sintaxe do DOM por ser padrão e permitir o uso de forma praticamente idêntica em outras linguagens, mesmo aquelas que não possuem serialização.

[]s

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.