Back-End

1 fev, 2012

Abordagens ao XML – Parte 01

Publicidade

Já faz um bom tempo que conhecemos o XML – acredito que seja algo em torno de treze anos. Agora, em termos computacionais, ele é já é um produto maduro. Então, será que ainda existe algo novo que eu poderia acrescentar a respeito? O modo como você aborda o assunto XML, realmente, depende de você e da sua situação, com ênfase na parte da situação. Em um extremo, você pode estar envolvido em um projeto interno, no qual um sistema interno tem que falar com o outro. Em outro extremo, você está em uma situação em que te entregam um XML schema que irá, um dia, abranger a conversa entre o seu sistema e um outro em um outro país, escrito por uma equipe diferente de desenvolvedores.

Para demonstrar diferentes abordagens no XML, irei pegar um cenário complemente inventado e ultrajante e nele você estará trabalhando para a “Pete’s Perfect Pizza”¹, que é uma pequena loja de entrega. Mas o dono da Pete’s tem ideias grandiosas, e a primeira coisa que ele quer é enviar os pedidos do balcão automaticamente para a cozinha. Então, ele pede para você escrever um pouco de código. A sua grande ideia é usar XML e você rabisca a rapidamente em um pedaço de papel e chega a um acordo com o chefe.

<?xml version="1.0" encoding="UTF-8"?>
<pizza>
<name>Capricciosa</name>
<base>thin</base>
<quantity>2</quantity>
</pizza>

A Pete’s é uma empresa muito pequena e você vai ter que fazer tanto a parte de atendimento (frontend), quanto a da cozinha (backend). Na sua primeira tentativa de XML, a parte da cozinha vai ficar assim:

public class OrderPizza {

private String pizzaName;
private String base;
private String quantity;

public void order(String xmlOrder) {

pizzaName = xmlOrder.substring(57, xmlOrder.indexOf("</", 58));
int index = xmlOrder.indexOf("<base>", 58);
int index2 = xmlOrder.indexOf("</", index);
base = xmlOrder.substring(index + 6, index2);
index = xmlOrder.indexOf("<quantity>", index2);
index2 = xmlOrder.indexOf("</", index);
quantity = xmlOrder.substring(index + 10, index2);
}

public String getPizzaName() {
return pizzaName;
}

public String getBase() {
return base;
}

public String getQuantity() {
return quantity;
}
}

E funciona muito bem nas unidades de testes:

public class OrderPizzaTest {

private static final String ORDER_XML = //
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
"<pizza>\n" + //
" <name>Capricciosa</name>\n" + //
" <base>thin</base>\n" + //
" <quantity>2</quantity>\n" + //
"</pizza>\n";

private OrderPizza instance;

@Before
public void setUp() throws Exception {

instance = new OrderPizza();
}

@Test
public void readOrderFromXML() {

instance.order(ORDER_XML);

assertEquals("Capricciosa", instance.getPizzaName());
assertEquals("thin", instance.getBase());
assertEquals("2", instance.getQuantity());
}
}

O tempo passa e Pete’s Perfect Pizza começa a expandir. A aplicação do balcão precisa de alguns ajustes, e o proprietário consegue um novo desenvolvedor. A primeira coisa que ele faz é decidir que seria mais eficiente se livrar dos espaço em branco entre caracteres na mensagem XML e envia à cozinha um código como este:

<?xml version="1.0" encoding="UTF-8"?><pizza><name>Capricciosa</name><base>thin</base><quantity>2</quantity></pizza>

O código da cozinha falha e rapidamente você compreende que cometeu o primeiro e mais fundamental erro ao lidar com XML: você agiu como se XML fosse uma string, mas ele não é! O XML é um modelo de documento orientado para o objeto, que pode ser exibido usando uma representação de string – uma lição que muitas pessoas aprendem da maneira mais difícil. E não é apenas a impressão bonita da string que pode te enganar; existe um monte de falcatruas nas formatações de documentos.

Pegue, por exemplo, o endereço “www.sitemaps.org”. Esse website define um XML schema que é suportado pelo Google, pelo Yahoo! e pela Microsoft, e também permite aos webmasters informar aos mecanismos de busca sobre páginas nos seus sites que estão disponíveis para crawling usando um documento XML. Dado o uso de namespaces no schema, um website pode retornar algo parecido com o código abaixo quando requisitado por seu sitemap:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>http://www.example.com/</loc>
<lastmod>2005-01-01</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>http://www.example.com/page1/</loc>
<lastmod>2006-01-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
</urlset>

Mas também poderia retornar assim:

<?xml version="1.0" encoding="UTF-8"?>
<sm:urlset xmlns:sm="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<sm:url>
<sm:loc>http://www.example.com/</sm:loc>
<sm:lastmod>2005-01-01</sm:lastmod>
<sm:changefreq>monthly</sm:changefreq>
<sm:priority>0.8</sm:priority>
</sm:url>
<sm:url>
<sm:loc>http://www.example.com/page1/</sm:loc>
<sm:lastmod>2006-01-02</sm:lastmod>
<sm:changefreq>weekly</sm:changefreq>
<sm:priority>0.8</sm:priority>
</sm:url>
</sm:urlset>

Ou assim:

<?xml version="1.0" encoding="UTF-8"?>
<sitemap:urlset xmlns:sitemap="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<sitemap:url>
<sitemap:loc>http://www.example.com/</sitemap:loc>
<sitemap:lastmod>2005-01-01</sitemap:lastmod>
<sitemap:changefreq>monthly</sitemap:changefreq>
<sitemap:priority>0.8</sitemap:priority>
</sitemap:url>
<sitemap:url>
<sitemap:loc>http://www.example.com/page1/</sitemap:loc>
<sitemap:lastmod>2006-01-02</sitemap:lastmod>
<sitemap:changefreq>weekly</sitemap:changefreq>
<sitemap:priority>0.8</sitemap:priority>
</sitemap:url>
</sitemap:urlset>

E todos eles são válidos, equivalentes e contêm a mesma informação. Somente a sua representação de string que se difere e é feita em conjunto.

De volta ao Pete’s Perfect Pizza… Você está se perguntando como pode consertar seu código, quando o dono da pizzaria chega e te pede para melhorar o sistema para que o seu documento XML possa pedir mais de uma pizza por vez. Você percebe que a manipulação de string não funciona e se depara com o SAX parsing na Internet, mas falaremos disso na segunda parte do artigo!

¹Usando o Google, você descobrirá que existem quatro páginas de Perfect Pizza de toda parte do mundo. Esta história é fictícia e qualquer semelhança a qualquer uma delas é mera coincidência.

²Ao ler os pedidos em XML você pode adivinhar que minha pizza favorita é a Capricciosa e a melhor de todas está disponível na Pizza Margherita

***

Texto original disponível em: http://www.captaindebug.com/2012/01/approaches-to-xml-part-1-xml-is-not.html