Guia de Consulta Rápida Java e XML Processamento de documentos XML com Java 2a edição Renê Rodrigues Veloso Novatec Copyright 2007 da Novatec Editora Ltda. Todos os direitos reservados e protegidos pela Lei 9.610 de 19/02/1998. É proibida a reprodução desta obra, mesmo parcial, por qualquer processo, sem prévia autorização, por escrito, do autor e da Editora. Editor: Rubens Prates ISBN: 978-85-7522-111-2 Primeira impressão: Abril/2003 (ISBN: 85-7522-036-5) Segunda edição: Julho/2007 (ISBN: 978-85-7522-111-2) Novatec Editora Ltda. Rua Luís Antônio dos Santos 110 02460-000 São Paulo SP – Brasil Tel.: +55 11 6959-6529 Fax: +55 11 6950-8869 E-mail: [email protected] Site: www.novatec.com.br Sumário Introdução..............................................................................5 Por que utilizar Java?.........................................................5 O que é XML?...................................................................5 Analisando documentos XML.................................................7 Parsers XML.....................................................................8 Processadores XML...........................................................9 Diferenças entre parser e processador XML....................... 10 Diferenças entre SAX e DOM........................................... 10 Trabalhando com JAXP..........................................................11 As APIs JAXP.................................................................. 12 Parser DOM.................................................................... 13 Parser SAX...................................................................... 16 Validando com Schema em JAXP..................................... 22 Trabalhando com Xerces........................................................ 25 Instalação....................................................................... 25 Parser DOM.................................................................... 25 Parser SAX......................................................................26 Manipulando Namespaces...............................................26 Validação DTD...............................................................26 Validação Schema............................................................26 Tratando erros......................................................................26 A Interface ErrorHandler................................................. 27 Utilizando o tratador de erros criado...............................28 Removendo espaços em branco..............................................28 Removendo espaços em branco com JAXP.......................29 Removendo espaços em branco com Xerces......................29 API DOM.............................................................................30 Módulos de DOM...........................................................30 Hierarquia de Classes/Interfaces...................................... 32 Interface Node................................................................ 33 Interface NodeList...........................................................38 Interface Element............................................................ 39 Interface NamedNodeMap.............................................. 41 Interface Attr...................................................................42 Interface Document.........................................................42 Interface CharacterData...................................................44 Interface Text . ................................................................ 45 Interface DocumentType . ...............................................46 Interface Entity............................................................... 47 Interface Notation........................................................... 47 Interface ProcessingInstruction ....................................... 47 Interface DOMImplementation........................................48 Classe DOMException....................................................48 Módulo DOM Traversal........................................................50 Interface NodeIterator......................................................51 Interface fábrica DocumentTraversal................................ 52 Interface NodeFilter.........................................................54 Interface TreeWalker........................................................56 Gerando documentos XML...................................................58 Criando uma árvore DOM..............................................58 Criando um objeto Document.........................................58 Criando e adicionando nós-filho......................................58 Sumário Serialização...........................................................................60 Serializando com JAXP....................................................60 Serializando com Xerces..................................................64 Classe OutputFormat......................................................64 XPath e XSLT........................................................................68 XPath.............................................................................68 Funções de processamento XPath..................................... 73 XPath em Java.................................................................77 XSLT............................................................................... 81 Exemplos práticos.................................................................84 Trabalhando com DOM4J.....................................................90 Instalação.......................................................................90 Parsing XML...................................................................90 Criando um Novo Documento XML................................ 91 Percorrendo o documento XML....................................... 93 Navegação com Xpath..................................................... 93 Convertendo de String para Árvore DOM4J.....................94 Principais Interfaces do Pacote org.dom4j.........................95 Serialização de Objetos em XML......................................... 100 Serializando com XStream............................................. 100 Serializando com XMLEncoder/XMLDecoder................ 102 Informações adicionais (links)............................................. 104 Sobre o autor................................................................ 105 Índice remissivo.................................................................. 106 Introdução Introdução Por que utilizar Java? A frase “escreva um e rode em qualquer lugar” é um bom motivo para começar a pensar em Java como sendo a plataforma de desenvolvimento de aplicações poderosas, seguras e que funcionam em qualquer ambiente computacional. Java é uma linguagem popular e de recursos fantásticos; com ela é possível fazer quase tudo o que se queira, é ideal para a implementação de aplicativos baseados em Intranet e Internet e em qualquer outro software para dispositivos que se comunicam em uma rede (como telefones celulares, pagers e PDAs – Personal Digital Assistants), e possui recursos importantes como manipulação de strings, imagens gráficas, componentes de interface gráfica com o usuário, tratamento de exceções, multitarefa, multimídia (áudio, imagens, animação e vídeo), processamento de arquivos, processamento de banco de dados, computação distribuída e estruturas de dados pré-empacotadas. Os recursos de Java são exatamente o que as empresas e organizações estão procurando para atender aos requisitos de processamento de informações atuais. A linguagem Java foi desenvolvida pela Sun Microsystems e está disponível gratuitamente na Internet no site da Sun:. http://java.sun.com. O que é XML? A XML (Extensible Markup Language, ou Linguagem de Marcação Extensível, com extensível significando expansível), é uma metalinguagem de marcação definida pelo W3C (World Wide Web Consortium) em www.w3.org, que lhe permite criar a sua própria linguagem (baseada em marcações – tags) e seguindo as regras que você definir em um determinado contexto. O W3C não é um órgão de padronização como a ISO, mas de recomendações. Isso significa que ele indica o que é melhor, e não o que deverá, necessariamente, ser utilizado. Por exemplo, a recomendação XML 1.1. Interoperabilidade É muito comum encontrarmos, principalmente em ambientes empresariais,grandes redes de comunicação de dados interligando aplicativos distribuídos entre máquinas com arquiteturas e sistemas operacionais diferentes. E para que isso aconteça, é necessário que as aplicações sejam capazes de conversar entre si, ou melhor, é fundamental que haja interoperabilidade entre elas. Para que ocorra interoperabilidade, também é preciso que as aplicações aceitem uma especificação comum de protocolos e formato de dados e que sejam, o máximo possível, baseadas Introdução em padrões abertos. A Internet é um bom exemplo de ambiente facilitador de interoperabilidade, e padronização é uma palavra importante na grande rede, pois nela devemos garantir que a informação transmitida será entendida pelo receptor, como os diversos browsers e aplicações clientes existentes. Uma das principais vantagens da XML é justamente promover a interoperabilidade ou a troca dos dados de maneira simples, barata e rápida entre os diversos tipos de computadores e sistemas. E isso se dá porque um arquivo XML é baseado em formato texto, contribuindo até mesmo para a leitura e maior entendimento. Organização e personalização XML representa os dados de maneira hierárquica e organizada. Essa representação é feita por meio de uma árvore que trata cada elemento como sendo um nó, facilitando o entendimento e a busca de informações. Uma outra função de XML é a capacidade de separar o conteúdo da apresentação; preocupa-se com “o que mostrar”, enquanto HTML se preocupa em “como mostrar” a informação. Veja a tag <p>, por exemplo; em HTML, essa tag significa o início de um parágrafo, já em XML, essa mesma tag poderia representar um preço, um parâmetro, uma pessoa etc., dependendo do contexto em que se encontra. Existem várias linguagens de marcação que foram criadas a partir de XML e que se tornaram recomendações do W3C, como a MathML (Mathematical Markup Language) em. www.w3.org/Math, que fornece uma maneira padrão de descrever equações, símbolos e expressões matemáticas, e a CML (Chemical Markup Language) em www.xml-cml.org, que descreve informações moleculares, gerencia problemas de equações químicas e ajuda os químicos a manipular átomos e moléculas como tags. Autodescrição dos dados Os dados em um documento XML são autodescritíveis, já que as tags informam o tipo de informação que está por vir. Por exemplo, em um documento XML, como o mostrado a seguir: livro.xml <?xml version=”1.0” encoding=”UTF-8”?> <LIVRO> <TITULO> Java e XML </TITULO> <ASSUNTO> Processamento de documentos XML com Java </ASSUNTO> </LIVRO> Introdução Tomando como base somente os nomes das tags ou elementos XML, podemos descobrir de que se trata o documento apresentado. Neste caso, o documento livro.xml descreve informações sobre um livro cujo título é “Java e XML” e o assunto é “Processamento de documentos XML com Java”. Documentos bem formados Um bom documento XML precisa ser bem formado, ou seja, deve seguir as regras de sintaxe estabelecidas para a XML pelo W3C na especificação XML 1.1. O documento XML precisa conter um ou mais elementos (tags); deve haver somente um elemento raiz, que deve conter todos os demais elementos. Cada elemento deve estar aninhado corretamente dentro de outro elemento. Cada elemento deve ter a sua tag de fechamento correspondente. Diferentemente do HTML que pode ter tags abertas, embaralhadas e sem raiz, o documento XML deve ser sintaticamente correto. Documentos válidos Um documento XML é dito válido se houver uma definição de tipo de documento (DTD) ou Schema associado a ele. DTD/Schema dita as regras que o documento deve seguir, quais são seus elementos, os seus nomes e que tipo de dados suporta. Veja um exemplo de DTD para o documento livro.xml mostrado anteriormente: <!ELEMENT LIVRO (TITULO, ASSUNTO)> <!ELEMENT TITULO (#PCDATA)> <!ELEMENT ASSUNTO (#PCDATA)> O arquivo com esse texto pode ser chamado de livro.dtd. Observação Um documento bem formado nem sempre é válido, mas um documento válido é sempre bem formado. Analisando documentos XML Para trabalhar com documentos no formato XML, de maneira que se tenha acesso a todos os elementos que constituem o documento, precisamos ter em mãos algumas ferramentas que nos permitirão realizar a parsing ou análise dos dados. Essas ferramentas são as chamadas APIs (Application Programming Interface), disponíveis para Java, com as quais construíremos os parsers e processadores XML. Analisando documentos XML Parsing É o processo de leitura e divisão do documento em elementos, atributos, entidades, comentários e outros tipos de dados, por meio do qual poderão ser analisados e validados. Parsers XML O parser é uma biblioteca de software (uma classe em Java) que lê o documento XML e verifica se ele é bem formado e válido. Validante e não-validante Os parsers XML são categorizados como validantes e nãovalidantes: • Validante: Um parser validante deve checar as restrições de validação e boa formação do documento de acordo com o DTD/Schema associado. • Não-validante: Quando lemos um documento XML, um parser não-validante checa a sua boa formação de acordo com a especificação XML1.1 e informa quaisquer violações ou erros quanto à estrutura do documento. Java 1.4 foi a primeira versão de Java a incluir um parser XML. Em outras versões, é necessário fazer o download do parser na web e instalá-lo normalmente como qualquer outra biblioteca Java, bastando adicioná-lo ao seu CLASSPATH. Mesmo em Java 1.4 é possível substituir o parser-padrão por um diferente que contenha uma característica adicional, mais simples ou mais rápida em seus documentos. Parsers disponíveis Existem vários tipos de analisadores ou parsers XML, todos com características e implementações distintas, podendo ser encontrados disponíveis para download na internet ou comercializados. A seguir serão citados os mais comuns. Ælfred O Ælfred (http://www.microstar.com/aelfred.html) é um pequeno e rápido parser especialmente desenvolvido para o uso em applets Java. Foi projetado para programadores Java que querem processar XML em seus applets e outras aplicações sem aumentar excessivamente o tamanho do projeto. Alfred consiste em somente duas classes, com um total de 26K de tamanho, e necessita de pouca memória para executar. Suporta a API SAX. Analisando documentos XML Crimson Antes conhecido como “Projeto Java X” (http://xml.apache. org/crimson/), é o parser que a Sun empacota com o JDK 1.4. Crimson suporta mais ou menos as mesmas APIs e especificações que a Xerces – SAX2, DOM2, JAXP, XML 1.0, Namespaces em XML e schema. Oracle XML Parser Encontrado em http://technet.oracle.com/tech/xml/. É um parser que permite a análise de documentos XML por meio das APIs SAX ou DOM, usando os modos validante ou não-validante. Piccolo Piccolo de Yuval Oren é um parser pequeno, rápido e nãovalidante. No entanto, faz a leitura de DTDs externas e as aplica ao documento ajustanto valores de atributos e resolvendo referências a entidades externas. Suporta exclusivamente a API SAX. Não possui implementação DOM. Mais informações podem ser obtidas em http://piccolo.sourceforge.net/. Xerces Um dos melhores e mais completos parsers disponíveis atualmente é Xerces-J do Projeto XML Apache, disponível em http://xerces.apache.org/. Atualmente, na versão 2.x, possui a melhor adaptação à especificação XML 1.1. Fornece suporte completo às APIs SAX2 e DOM Level 3, e até JAXP. Xerces-J é altamente configurável e adaptável para quase tudo de que um parser necessita. Xerces-J também suporta W3C XML Schema Language e Namespaces. XP Encontrado em http://www.jclark.com/xml/xp/index.html. XP é um parser que suporta a especificação 1.0 da XML. É capaz de detectar documentos bem formados, no entanto, atualmente, é um parser não-validante. Suporta a API SAX. Processadores XML Basicamente um processador XML é um módulo de software que faz a leitura de documentos XML e fornece os aplicativos necessários para acessar o conteúdo e a estrutura desses documentos. A especificação XML 1.0 do W3C (http://www. w3.org) define precisamente as funções de um processador XML. Um processador XML (Figura 1) funciona como uma ponte entre um documento XML e uma aplicação, podendo, além de analisar, também gerar documentos XML. A aplicação utiliza uma API para acessar objetos que representam parte do documento XML. 10 Analisando documentos XML Documento XML Processador XML Árvore DOM Eventos SAX Aplicação Análise Geração Acesso com DOM e SAX Figura 1 – Processador XML. Diferenças entre parser e processador XML Um parser XML tem a função de fazer a análise do conteúdo de um documento XML e verificar se esse documento é bem formado e válido. Já um processador XML, além de fazer a parsing ou a análise dos dados, pode navegar por entre os nós da árvore XML, acessar todos os elementos e campos, como também gerar documentos em formato XML e quaisquer outros formatos. Diferenças entre SAX e DOM O objetivo das APIs SAX e DOM é tornar a interpretação XML fácil e satisfatória para programas de computador. Para fazer essa interpretação, existem duas técnicas conhecidas como Simple API for XML (SAX) e Document Object Model (DOM), baseadas em abstrações dos conjuntos de informação de um documento XML (Figura 2). Essas técnicas projetam esses conjuntos e informações em um modelo de objetos que permite aos programadores manipulá-los. SAX SAX (Simple API for XML) é um conjunto de interfaces que decompõe um documento XML em uma sucessão linear de chamadas de métodos. DOM DOM (Document Object Model) é um conjunto de interfaces que decompõe um documento XML em uma árvore transversal hierárquica de nós/objetos. 11 Analisando documentos XML <?xml version="1.0" encoding="UTF-8"?> <livro> <nome>Java e XML</nome> <editora>Novatec</editora> </livro> PARSING livro nome editora Java e XML Novatec startElement: livro startElement: nome characters: Java e XML endElement: nome startElement: editora characters: Novatec endElement: editora endElement: livro Figura 2 – Diferenças entre DOM e SAX, respectivamente. Comparando DOM e SAX • DOM é uma solução natural para lidar com dados que são mais bem descritos como uma árvore. • Para trabalhar principalmente com dados estruturados ou gerados pelo computador, SAX pode ser mais conveniente. • SAX possui métodos e estruturas de dados mais simples do que os de DOM, podendo muitas vezes alcançar alta performance. • DOM agiliza a pesquisa por elementos, bastando apenas indicar o caminho de nós na árvore (por exemplo, com expressões XPath). • SAX utiliza menos memória que DOM, pois não precisa manipular uma estrutura de dados complexa, como uma árvore em memória. Trabalhando com JAXP Nas versões mais recentes de J2SE e J2EE, é incluído um conjunto-padrão de APIs para XML, conhecido como JAXP (Java APIs for XML Processing). Essas APIs também estão disponíveis separadamente, em um pacote de bibliotecas Java chamado JAX Pack (Java XML Pack), no site da Sun (http://java.sun.com), contendo várias outras APIs relacionadas a XML e Web Services. JAXP suporta os analisadores-padrão SAX (Simple API for XML Parsing) e DOM (Document Object Model), assim como o padrão XSLT (XML Stylesheet Language Transformation), dando maior controle sobre a apresentação dos dados e capacitando a conversão dos dados para outro documento XML ou para outros formatos, como HTML. JAXP também trabalha com DTD/Schema e suporta namespaces. 12 Trabalhando com JAXP As APIs JAXP As principais APIs JAXP são definidas no pacote javax.xml.parsers. Esse pacote contém duas fábricas de classes: SAXParserFactory e DocumentBuilderFactory, que fornecem instâncias para um objeto SAXParser e um objeto DocumentBuilder, respectivamente. A vantagem é que essas fábricas de classes, SAXParserFactory e DocumentBuilderFactory, permitem utilizar uma implementação XML oferecida por outros fornecedores sem a necessidade de mudar o código. Uma visão geral dos pacotes As APIs SAX e DOM são definidas pelo grupo XML-DEV e pelo W3C, respectivamente. As bibliotecas que definem essas APIs são: Pacotes DOM Pacote Descrição org.w3c.dom Define a interface de programação DOM para documentos XML (especificação W3C). Define a classe-fábrica DocumentBuilderFactory e a classe DocumentBuilder, que constroem um objeto implementando a interface Document do W3C. A fábrica utilizada para criar o construtor é determinada pelas propriedades do pacote javax.xml.parsers, que podem ser ajustadas por um comando de linha ou ativadas quando se invocar o método new Instance. Esse pacote também define a classe ParserConfigurationException para informar erros. javax.xml.parsers Pacotes SAX Pacote org.xml.sax Descrição Define as interfaces SAX. O nome org.xml é o prefixo do pacote que foi estabelecido pelo grupo que definiu a API SAX. org.xml.sax.ext Define as extensões SAX que são utilizadas em um processamento SAX mais sofisticado, por exemplo, para processar um DTD ou para ver a sintaxe detalhada de um arquivo. org.xml.sax.helpersContém classes auxiliares que facilitam a utilização de SAX. Javax.xml.parsers Define a classe SAXParserFactory que retorna o SAXParser.Também define classes de exceções para informar erros. 13 Trabalhando com JAXP Pacotes XSLT Pacote Descrição javax.xml.transform Define as classes TransformerFactory e Transformer , que são utilizadas para obter um objeto capaz de fazer transformações em um documento XML seguindo as regras contidas em uma folha de estilo. Depois de criar um objeto transformer, é invocado o método transform(), fornecendo uma entrada (source) e uma saída (output). javax.xml.transform.dom Classes para criar objetos de entrada (input) e saída (result) de um DOM. javax.xml.transform.sax Classes para criar a entrada (input) de um parser SAX e objetos de saída (output) de um manipulador de eventos SAX. javax.xml.transform.streamClasses para criar objetos de entrada (input) e saída (output) de uma stream de I/O. Parser DOM O Document Object Model (DOM) é uma interface de programação especificada pelo W3C para o tratamento e manipulação de dados em documentos XML. DOM sugere um meio de abordar documentos XML como sendo uma árvore de nós, e essa é a maneira mais correta, visto que o documento XML organiza-se também em forma de árvore. A Figura 3 apresenta o processo de construção e funcionamento de um parser DOM JAXP. Para mais informações sobre DOM, visite o site www.w3.org. DocumentBuilder Factory DocumentBuilder Dados XML Objeto Document Árvore DOM Figura 3 – Construção e funcionamento de um parser DOM JAXP. 14 Trabalhando com JAXP DocumentBuilder e DocumentBuilderFactory Para construir um parser DOM em JAXP, é necessário utilizar as classes javax.xml.parsers.DocumentBuilderFactory e javax.xml.parsers. DocumentBuilder e configurá-las corretamente. import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import org.w3c.dom.Document; String nome_arquivo; ... DocumentBuilderFactory factory = DocumentBuilderFactory. newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(nome_arquivo); É necessário seguir alguns passos para obter um parser DOM JAXP: 1. Utilize o método-fábrica estático DocumentBuilderFactory. n e w I n s t a n c e ( ) p a r a r e to r n a r u m o b j e to DocumentBuilderFactory. 2. Utilize o método newDocumentBuilder() do objeto DocumentBuilderFactory para retornar uma instância da classe DocumentBuilder. 3. Utilize um dos cinco métodos parse() de DocumentBuilder para ler o documento XML e retornar um objeto org. w3c.dom.Document. 4. Lembre-se de colocar tudo em um bloco try-catch para tratar possíveis exceções. Exemplo completo import javax.xml.parsers.*; import org.w3c.dom.Document; import java.io.*; public class ParserExemplo { public static void main(String args[]) { String nomeArquivo = “”; if(args.length > 0) nomeArquivo = args[0]; else { System.out.println(“Use: ParserExemplo seu_arquivo_XML”); System.exit(0); } try{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(nomeArquivo); } catch(Exception e){e.printStackTrace();} } } 15 Trabalhando com JAXP Métodos parse() public Document parse(InputSource fonte) throws SAXException, IOException public Document parse(String uri) throws SAXException, IOException public Document parse(File arquivo) throws SAXException, IOException public Document parse(InputStream entrada) throws SAXException, IOException public Document parse(InputStream entrada,String systemID) throws SAXException,IOException Configurando DocumentBuilderFactory A classe DocumentBuilderFactory possui métodos de ajuste set...(), que permitem determinar exatamente como o parser criado deve se comportar. Ignorando comentários public boolean isIgnoringComments(); public void setIgnoringComments(boolean ignora); Esses métodos determinam se o parser produzido por esse factory irá gerar nós de comentários que serão vistos na entrada do documento. O valor default, false, significa que os nóscomentário serão produzidos. Ignorando espaços em branco public boolean isIgnoringElementContentWhitespace(); public void setIgnoringElementContentWhitespace(boolean ignorarWS); Esses métodos determinam se o parser irá gerar nós-texto para os chamados “espaços em branco ignoráveis”, isto é, espaço em branco que ocorre entre os elementos onde o DTD especifica que os caracteres de dados analisados não podem aparecer. O valor default (padrão) é false, isto é, inclui nós-texto para espaços em branco ignoráveis. Para que essa propriedade seja aplicada, ou seja, para que se possa atribuir true ao argumento ignoraWS, o documento deve ter um DTD associado a ele e deve ser válido. De outra forma, o parser não pode saber qual espaço em branco é ignorável e qual não é. Reconhecendo Namespaces public boolean isNamespaceAware(); public void setNamespaceAware(boolean namespaceAware); Esses métodos determinam se o parser produzido é namespace aware, ou seja, se reconhece namespaces. Essa característica irá ajustar as propriedades de prefixo e URI namespace dos nós-elemento e atributos. O valor default (padrão) é sempre para true. Por exemplo: false, DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); mas deve ser ajustado