Caro(a) Leitor(a) hoje eu vou falar e mostrar a solução de gerar XML na mĂŁo. Existem várias soluções para gerar XML, mas as existentes nĂŁo servia pra mim ou era muito complicado de se fazer. Preciso gerar um XML de forma simples, com dados dinâmicos e criando tags de acordo com o que gostaria de criar. 

        Imagine que vocĂŞ precisa gerar um XML com os dados do banco de dados, mas as tags do XML precisam ser de acordo com o padrĂŁo do cliente, ele mandou por e-mail. Esse XML precisa ser gerado e gravado dependendo da quantidade informada tambĂ©m pelo cliente; isto Ă©; dependendo da quantidade de imagem informada pelo cliente.

        Vamos ao problema: Eu tenho alguns valores escritos no banco de dados, esses valores me levam a arquivos de imagem e, para certo conjunto de imagens eu tenho que gerar um XML armazenando valores dentro.

        Todos os dados dentro do arquivo faz referĂŞncia direta aos dados da imagem. Quero dizer que, para cada imagem eu preciso colocar os dados dela dentro do XML e o que foi passado pelo cliente Ă© que o conjunto de imagens Ă© de 1000 em 1000. Isso significa que para 1000 imagens precisam ser referenciadas dentro do XML, as prĂłximas 1000 preciso gerar outro XML e assim sucessivamente. 

        Dentro do mesmo XML, vou precisar repetir a tag principal para cada imagem. Uma tag principal por imagem frente e verso. Por exemplo: A imagem começa com a tag <PRINCIPAL> e lá existem os dados da imagem, quando termino de ler os dados preciso fechar a tag </PRINCIPAL>. A prĂłxima imagem, que fica ainda dentro do mesmo XML, precisa ser gerada com outra tag <PRINCIPAL> e depois fechá-la </PRINCIPAL>. 

<PRINCIPAL>
<DADOS>IMAGEM 1</DADOS>
</PRINCIPAL>
<PRINCIPAL>
<DADOS>IMAGEM 2</DADOS>
</PRINCIPAL>

        Isso quer dizer que todos os dados, desde a primeira tag atĂ© a Ăşltima precisam ser re-gerados usando dados diferentes. Como o DataTable me dá a opção de gerar um XML com os valores pensei em usá-lo. Com isso o meu problema seria resolvido.

        Mas como as coisas nĂŁo sĂŁo tĂŁo simples assim, o cliente precisava que o XML respeitasse o padrĂŁo dele, isto Ă©, com várias tags, sub-tags e nomes especĂ­ficos. Isso deixa claro que nĂŁo vou poder gerar o XML com o objeto DataTable e sim na mĂŁo.

        Depois de fazer uma pesquisa na web, percebi que a maioria dos artigos falam de gerar XML com objetos ou apenas uma vez, sem poder regerar as tags, principalmente as tags principais. NĂŁo serve para o que precisava fazer. Veja o que o cliente gostaria que fosse o XML.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<PRINCIPAL>
<NOME>Nome</NOME>
<EMAIL>EMAIL</EMAIL>
<CLIENTENOME>CLIENTE NOME</CLIENTENOME>
<ATRIBUTOS>
<INFORMACOES>DADOS DOS CLIENTES</INFORMACOES>
<VALOR>VALOR DA IMAGEM</VALOR>
<DATA>DATA DA GERACAO</DATA>
<IMAGENS>
<IMAGEMFRENTE>
<IMAGEM>C:\ENDERECO\</IMAGEM>
<TIPOIMAGEM>TIF</TIPOIMAGEM>
<NOMEIMAGEM>TESTEF.TIF</NOMEIMAGEM>
</IMAGEMFRENTE>
<IMAGEMVERSO>
<IMAGEM>C:\ENDERECO\</IMAGEM>
<TIPOIMAGEM>TIF</TIPOIMAGEM>
<NOMEIMAGEM>TESTEV.TIF</NOMEIMAGEM>
</IMAGEMVERSO>
</IMAGENS>
</ATRIBUTOS>
</PRINCIPAL>
Listagem: 1 – XML

Essas tags servem para cada imagem com frente e verso. Tenho que criar um XML para cada 1000 imagens. 

Os artigos encontrados na busca que fiz não poderiam regerar as tags, ou seja, não poderia regerar as tags dentro do mesmo XML (desde a primeira até a última). Como o meu objeto DataTable já estava preenchido com as informações que queria, buscados diretamente do banco de dados, precisava agora criar um loop e para cada loop gerar um XML com todos os dados obedecendo a regra.

O cálculo que fiz foi que, diariamente são 79.000 mil imagens que chegam do nosso cliente. Todo esse cálculo eu preciso fazer para gerar de mil em mil.

Depois que fiz uma classe toda baseada em um artigo, percebi que as tags não poderiam ser regeradas dentro de um mesmo XML. Comecei a fazer de outra maneira, mais dinâmica e simples. Segue um passo a passo de como fiz.

O exemplo que vou mostrar aqui é bem simples, mas serve de base para que você siga e crie o XML de forma rápida na mão. O projeto que utilizei é do tipo Windows Forms para teste. Depois de testado, a classe e a forma de fazer pode ser jogada dentro de um Windows Service sem qualquer problema. Windows Services é um tipo de projeto que fica executando de tempos em tempos de forma automática. Imagem 1.



Imagem 1- Criando projeto Windows Forms.

Usando o Visual Studio 2010, cliquei no menu file >> new Project e pedi para gerar um novo projeto do tipo Windows Forms Application.

Logo na classe criada, comecei a escrever alguns métodos. A classe form1. Imagem 2.




Imagem 2 – Classe Form1.

Cliquei com o botão em cima da classe chamada Form1.cs e apareceu o formulário na tela. Imagem 3.


Imagem 3 – Formulário simples.

No método Form1_Load é o primeiro método que o programa passa usando o nosso exemplo. Dentro dele gerei dois loops para regerar várias tags para dois XML. Listagem 1.

Listagem 1- Loops para gerar o XML.
[Code]
private void Form1_Load(object sender, EventArgs e)
{
for (int j = 0; j < 2; j++)
       {
       for (int i = 0; i < 5; i++)
             {
             geraXML(i, 4);
             }
        }
}
[/Code]

Note que existem dois loops, um loop dentro do outro. O primeiro loop corresponde a quantidade de arquivos que preciso gerar; isto Ă©; 2 arquivos para teste.

O segundo loop é responsável por chamar o método que gera o XML passando alguns parâmetros. O nome que dei ao método responsável por gerar XML é geraXML. Preciso passar dois parâmetros: a quantidade de imagens e o total, isso serve para detectar se o arquivo deve ser fechado ou aberto no caso de ser o primeiro e o último loop.

Como estou criando o arquivo na mĂŁo, tenho que fazer todo controle de abrir o arquivo, gerar tag e fechar Ă  escrita. Se estivesse usando objetos como DataTable, nĂŁo precisaria ter esse controle.

O mĂ©todo geraXML Ă© o grande responsável por criar o arquivo e adicionar as tags. Para cada loop ele repete todas as tags. 

Listagem 2 – Método que gera o XML
[Code]
private void geraXML(int i, int total)
        {
//se for a primeira vez, entĂŁo ele gera o xml chamado product0.xml
            if (i == 0)
            {
                writer = new XmlTextWriter("product" + i +".xml", System.Text.Encoding.UTF8);
                writer.WriteStartDocument(true);
                writer.Formatting = Formatting.Indented;
                writer.Indentation = 2;
            }

//ele cria a tag principal dentro do arquivo XML
            writer.WriteStartElement("PRINCIPAL");

//é necessário criar um node com os parâmetros
//aqui pode ser colocado os dados do objeto DataTable.
            criarNode("1", "Product 1", "1000", writer);
            criarNode ("2", "Product 2", "2000", writer);
            criarNode ("3", "Product 3", "3000", writer);
            criarNode ("4", "Product 4", "4000", writer);

//depois de escrever todos os nodes, é necessário fechar a tag PRINCIPAL com o comando WriteEndElement().
            writer.WriteEndElement();

//se for a primeira vez, ele fecha o documento
            if (i == 0)
                writer.WriteEndDocument();

//se for a Ăşltima vez, entĂŁo ele fecha a escrita do documento
            if (total == i)
                writer.Close();

        }
[/Code]
Dentro do método XML existe outro método responsável por criar os “nodes” chamado criarNode. Nele eu passos os valores e o objeto de escrita chamada “writer”. Ele vai regerar sempre as informações para cada loop.

Verifico se Ă© a primeira vez. Se for, ele finaliza o XMLTextWriter criado dentro do XML com o nome que eu quiser. Lembro que esse Ă© um exemplo que preciso para regerar tags. 

Note que é gerado o arquivo usando o encode UTF8 para deixar um padrão bom para qualquer plataforma. Antes de criar o “node” (tags) escrevo o elemento principal chamando StartElement. O nome que passei (PRINCIPAL) é o nome da tag que será criada.

Analisando o método criarNode, eu posso passar os valores que eu quiser de acordo com o método. Re-organizei o código gerando um método para ficar mais fácil o entendimento. Listagem 3.

Listagem 3 – Criando os “nodes”
[Code]
private void criarNode(string pID, string pName, string pPrice, XmlTextWriter writer)
        {
//gerando a tag <PRODUTO> que está dentro da tag <PRINCIPAL>
            writer.WriteStartElement("Produto");

//gerando outra tag <ID> dentro da de <PRODUTO>
            writer.WriteStartElement("id");

//escrevendo o valor da tag <ID> por exemplo: <ID>valor</ID>
            writer.WriteString(pID);

//fechando a tag </ID>
            writer.WriteEndElement();

            writer.WriteStartElement("ProdutoNome");
            writer.WriteString(pName);
            writer.WriteEndElement();

            writer.WriteStartElement("ProdutoPreco");
            writer.WriteString(pPrice);
            writer.WriteEndElement();

            writer.WriteStartElement("Atributo");
            writer.WriteStartElement("SubAtributo");
            writer.WriteString("valor subatributo");
            writer.WriteEndElement(); //fecha a tag subatributo

            writer.WriteStartElement("Nome");
            writer.WriteString("valor nome");
            writer.WriteEndElement(); //fecha a tag nome
            
            writer.WriteEndElement(); //fecha a tag atributo
            
            writer.WriteEndElement(); //fecha a tag produto
        }
[/Code]

Note que uso o mesmo mĂ©todo chamado WriteStartElement para gerar tag (elemento) e depois gero o valor com o comando WriteString. Para fechar o elemento basta usar o WriteEndElement. 

Para colocar um elemento dentro do outro, basta abrir dois elementos, colocar o valor, abrir mais um elemento e depois fechar os trĂŞs abertos. Como feito na (Listagem 3). Gerei primeiro o elemento atributo, depois um subatributo, coloquei o valor, gerei outro elemento chamado nome, coloquei o valor, fechei a tag e no final fechei a tag de atributo.

Antes de fechar as tags, tudo que colocar vai ficar dentro da primeira tag aberta. É bem simples esse conceito. Depois de gerar esses elementos, preciso fechar o arquivo.

Listagem 4 – Fechando o arquivo.
[Code]
            if (total == i)
                writer.Close();
[/Code]

Para fechar o arquivo na parte da escrita, verifico se o total é igual ao valor passado, se for igual ele usa o objeto write com o método Close(). É bem simples.

O próximo loop1 que está fora do loop 2 começa a gerar outro arquivo. Vamos rodar o exemplo pra ver como vai funcionar. Veja como ficou um arquivo XML. Listagem 4.

Listagem 4 – Resultado final de um XML (arquivo 1)
[Code]
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<PRINCIPAL>
  <Product>
    <Product_id>1</Product_id>
    <Product_name>Product 1</Product_name>
    <Product_price>1000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>2</Product_id>
    <Product_name>Product 2</Product_name>
    <Product_price>2000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>3</Product_id>
    <Product_name>Product 3</Product_name>
    <Product_price>3000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>4</Product_id>
    <Product_name>Product 4</Product_name>
    <Product_price>4000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
</ PRINCIPAL >< PRINCIPAL >
  <Product>
    <Product_id>1</Product_id>
    <Product_name>Product 1</Product_name>
    <Product_price>1000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>2</Product_id>
    <Product_name>Product 2</Product_name>
    <Product_price>2000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>3</Product_id>
    <Product_name>Product 3</Product_name>
    <Product_price>3000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>4</Product_id>
    <Product_name>Product 4</Product_name>
    <Product_price>4000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
</ PRINCIPAL >
< PRINCIPAL >
  <Product>
    <Product_id>1</Product_id>
    <Product_name>Product 1</Product_name>
    <Product_price>1000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>2</Product_id>
    <Product_name>Product 2</Product_name>
    <Product_price>2000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>3</Product_id>
    <Product_name>Product 3</Product_name>
    <Product_price>3000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>4</Product_id>
    <Product_name>Product 4</Product_name>
    <Product_price>4000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
</ PRINCIPAL >
< PRINCIPAL >
  <Product>
    <Product_id>1</Product_id>
    <Product_name>Product 1</Product_name>
    <Product_price>1000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>2</Product_id>
    <Product_name>Product 2</Product_name>
    <Product_price>2000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>3</Product_id>
    <Product_name>Product 3</Product_name>
    <Product_price>3000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>4</Product_id>
    <Product_name>Product 4</Product_name>
    <Product_price>4000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
</ PRINCIPAL >
< PRINCIPAL >
  <Product>
    <Product_id>1</Product_id>
    <Product_name>Product 1</Product_name>
    <Product_price>1000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>2</Product_id>
    <Product_name>Product 2</Product_name>
    <Product_price>2000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>3</Product_id>
    <Product_name>Product 3</Product_name>
    <Product_price>3000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
  <Product>
    <Product_id>4</Product_id>
    <Product_name>Product 4</Product_name>
    <Product_price>4000</Product_price>
    <Elemento>
      <SubElemento>valor subelemento</SubElemento>
      <Nome>valor nome</Nome>
    </Elemento>
  </Product>
</PRINCIPAL>
[/Code]

Note que a tag <PRINCIPAL> repetiu várias vezes dentro do mesmo arquivo XML, conforme estava precisando. Executando todo o código, o programa gerou dois arquivos XML. Imagem 4.


Imagem 4 – Mostrando os XMLs gerados.

Bom, espero que tenha gostado e qualquer dúvida pode entrar em contato. Com esse artigo, você tem a base para construir qualquer XML na mão que necessitar. De forma simples e fácil.