1 XML Sistemas de Informação Sistemas de Informação: XML- Java Todos os exemplos bem como o conteúdo teórico tem por base o livro: Steven Holzner, SAMS Teach Yourself XML, SAMS Publishing, 2004 JCFJ 2 XML Java e XML Documentos XML podem ser abordados de dois modos – W3C DOM (Document Object Model): documento tratado como uma árvore de Sistemas de Informação nós – SAX (Simple API for XML): documento tratado como um arquivo texto Com DOM é necessário construir na memória a árvore completa que representa o documento XML para depois se poder manipulá-lo Com SAX os elementos são recuperados a medida que o documento XML é lido Os elementos não são automaticamente mantidos na memória JCFJ 3 XML – XML, Java e DOM ch16_01.xml Sistemas de Informação Ler um Documento XML com Java (DOM) <?xml version="1.0" encoding="UTF-8"?> <session> <committee type="monetary"> <title>Finance</title> <number>17</number> <subject>Donut Costs</subject> <date>7/15/2005</date> <attendees> <senator status="present"> <firstName>Thomas</firstName> <lastName>Smith</lastName> </senator> <senator status="absent"> <firstName>Frank</firstName> <lastName>McCoy</lastName> </senator> <senator status="present"> <firstName>Jay</firstName> <lastName>Jones</lastName> </senator> </attendees> </committee> </session> JCFJ 4 XML – XML, Java e DOM Ler um Documento XML com Java (DOM) public class Ch16_02 { static String displayText[] = new String[1000]; static int numberLines = 0; Ch16_02.java Sistemas de Informação package ismt; import javax.xml.parsers.*; import org.w3c.dom.*; Objeto que é criado para fazer a leitura do documento XML. public static void main(String args[]) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = null; try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) {} Document document = null; document = builder.parse(args[0]); Objeto que é criado para realizar o parsing do documento XML. Lê o nome documento XML que será analisado e cria o DOM. childLoop(document, ""); } catch (Exception e) { e.printStackTrace(System.err); } JCFJ Método que irá manipular o DOM. 5 XML – XML, Java e DOM Ler um Documento XML com Java (DOM) M Ch16_02.java – continuação... Sistemas de Informação for(int loopIndex = 0; loopIndex < numberLines; loopIndex++){ System.out.println(displayText[loopIndex]); } Apresenta o documento } após ele ter sido criado public static void childLoop(Node node, String indentation) { Se o documento estiver if (node == null) { vazio retorna return; } Recupera o tipo do nó int type = node.getNodeType(); Se o nó for o indicativo de documento switch (type) { adiciona o prólogo a displayText case Node.DOCUMENT_NODE: { displayText[numberLines] = indentation; displayText[numberLines] += "<?xml version=\"1.0\" encoding=\""+ "UTF-8" + "\"?>"; A partir do tipo do numberLines++; nó (tabela transp. childLoop(((Document)node).getDocumentElement(), ""); 10) executa tarefas break; específicas } Chama childLoop com o nó filho do nó tratado JCFJ 6 XML – XML, Java e DOM Ler um Documento XML com Java (DOM) Elemento é do tipo nó case Node.ELEMENT_NODE: { displayText[numberLines] = indentation; Verifica o displayText[numberLines] += "<"; Cria cada um dos nós número de displayText[numberLines] += node.getNodeName(); recuperando seu nome atributos do nó, int length = (node.getAttributes() != null) ? cria um vetor node.getAttributes().getLength() : 0; de atributos e Attr attributes[] = new Attr[length]; itera sobre ele for (int loopIndex = 0; loopIndex < length; loopIndex++) { attributes[loopIndex] = (Attr)node.getAttributes().item(loopIndex); } Ch16_02.java – continuação... Sistemas de Informação M for (int loopIndex = 0; loopIndex < attributes.length; loopIndex++) { Attr attribute = attributes[loopIndex]; displayText[numberLines] += " "; Armazena os displayText[numberLines] += attribute.getNodeName(); atributos no displayText[numberLines] += "=\""; vetor displayText[numberLines] += attribute.getNodeValue(); displayText[numberLines] += "\""; } displayText[numberLines] += ">"; numberLines++; JCFJ Cria a saída para representar o atributo. 7 XML – XML, Java e DOM Ler um Documento XML com Java (DOM) Verifica se o nó tem filhos M Ch16_02.java – continuação... Sistemas de Informação NodeList childNodes = node.getChildNodes(); if (childNodes != null) { Verifica o número length = childNodes.getLength(); de filhos do nó indentation += " "; for (int loopIndex = 0; loopIndex < length; loopIndex++ ) { childLoop(childNodes.item(loopIndex), indentation); } } Para cada um dos filhos chama break; recursivamente o método } case Node.TEXT_NODE: { displayText[numberLines] = indentation; String trimmedText = node.getNodeValue().trim(); if(trimmedText.indexOf("\n") < 0 && trimmedText.length() > 0) { displayText[numberLines] += trimmedText; numberLines++; } break; } Adiciona a saída o conteúdo (sem espaços) do nó de texto se ele for válido JCFJ XML – XML, Java e DOM Ler um Documento XML com Java (DOM) Ch16_02.java – continuação... Sistemas de Informação M JCFJ case Node.PROCESSING_INSTRUCTION_NODE: { displayText[numberLines] = indentation; displayText[numberLines] += "<?"; displayText[numberLines] += node.getNodeName(); String text = node.getNodeValue(); if (text != null && text.length() > 0) { displayText[numberLines] += text; } displayText[numberLines] += "?>"; numberLines++; As instruções de processamento são break; simplesmente copiadas apropriadamente na } saída (<? --- ?>) case Node.CDATA_SECTION_NODE: { displayText[numberLines] = indentation; displayText[numberLines] += "<![CDATA["; displayText[numberLines] += node.getNodeValue(); displayText[numberLines] += "]]>"; numberLines++; break; } } Sessões CDATA são simplesmente copiadas na saída 8 9 XML – XML, Java e DOM Ch16_02.java – continuação... Sistemas de Informação Ler um Documento XML com Java (DOM) M if (type == Node.ELEMENT_NODE) { displayText[numberLines] = indentation.substring(0, indentation.length() - 4); displayText[numberLines] += "</"; displayText[numberLines] += node.getNodeName(); displayText[numberLines] += ">"; numberLines++; indentation += " "; A o elemento de } fechamento ao marcador } } JCFJ 10 XML Campos do Objeto Node Sistemas de Informação Tipo de Campo Define static short ATTRIBUTE_NODE Um atributo static short CDATA_SECTION_NODE Uma seção CDATA static short COMMENT_NODE Um comentário static short DOCUMENT_FRAGMENT_NODE Um fragmento de documento static short DOCUMENT_NODE Declaração de um documento static short DOCUMENT_TYPE_NODE Um DTD static short ELEMENT_NODE Um elemento static short ENTITY_NODE Uma entidade static short ENTITY_REFERENCE_NODE Um referência a entidade static short NOTATION_NODE Uma notação static short PROCESSING_INSTRUCTION_NODE Uma instrução de processamento static short TEXT_NODE Um nó de texto JCFJ 11 XML – XML, Java e DOM Encontrando Elementos pelo Nome (DOM) Elementos específicos podem ser encontrados utilizando o método getElementByTagName Ex.: Procurar pelo elemento senator Sistemas de Informação no documento XML O programa deve ser chamado do seguinte modo: java Ch16_03 ch16_01.xml senator JCFJ 12 XML – XML, Java e DOM Encontrando Elementos pelo Nome (DOM) package ismt; Semelhante ao exemplo anterior mas executando somente para um nó específico public class Ch16_03 { static String displayText[] = new String[1000]; static int numberLines = 0; Ch16_03.java Sistemas de Informação import javax.xml.parsers.*; import org.w3c.dom.*; Igual ao primeiro exemplo public static void main(String args[]) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = null; try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) {} Recupera uma lista de nós, do tipo especificado, utilizando um método da API Document document = null; document = builder.parse(args[0]); NodeList nodeList = document.getElementsByTagName(args[1]); JCFJ 13 XML – XML, Java e DOM Encontrando Elementos pelo Nome (DOM) if (nodeList != null) { for (int loopIndex = 0; loopIndex < nodeList.getLength(); loopIndex++ ) { childLoop(nodeList.item(loopIndex), ""); } } Itera sobre a lista de nós do elemento } catch (Exception e) { e constrói o string de apresentação, e.printStackTrace(System.err); usando o método childLoop } Ch16_03.java – continuação... Sistemas de Informação M for(int loopIndex = 0; loopIndex < numberLines; loopIndex++){ System.out.println(displayText[loopIndex]); } } public static void childLoop(Node node, String indentation) { M Semelhante ao Apresenta o conteúdo M exemplo anterior do elemento } } JCFJ 14 XML Java e SAX Com SAX o processador trabalha sobre o documento e um método específico para realizar o tratamento SAX é dirigido por eventos, fazendo com que os métodos sejam chamados quando o processador encontrar os elementos específicos JCFJ ch17_01.xml Sistemas de Informação ao encontrar um nó, chama <?xml version="1.0" encoding="UTF-8"?> <session> <committee type="monetary"> <title>Finance</title> <number>17</number> <subject>Donut Costs</subject> <date>7/15/2005</date> <attendees> <senator status="present"> <firstName>Thomas</firstName> <lastName>Smith</lastName> </senator> <senator status="absent"> <firstName>Frank</firstName> <lastName>McCoy</lastName> </senator> <senator status="present"> <firstName>Jay</firstName> <lastName>Jones</lastName> </senator> </attendees> </committee> </session> 15 XML Ler um Documento XML com Java (SAX) import import import import Ch17_02.java Sistemas de Informação package ismt; Ch17_02 é uma sub-classe de um tratador padrão SAX. Este tratador tem uma série de métodos (transp. 21) que são chamados em resposta a eventos (nós específicos encontrados) Métodos específicos devem ser reimplementados para manipular elementos específicos java.io.*; org.xml.sax.*; javax.xml.parsers.*; org.xml.sax.helpers.DefaultHandler; public class Ch17_02 extends DefaultHandler { static int numberLines = 0; static String indentation = ""; static String displayText[] = new String[1000]; public static void main(String args[]) { Ch17_02 parser = new Ch17_02(); parser.childLoop(args[0]); Cria um objeto do tratador Chama o método que constrói a saída para o documento passado como argumento for (int loopIndex = 0; loopIndex < numberLines; loopIndex++) { System.out.println(displayText[loopIndex]); } } Apresenta a saída JCFJ 16 XML Ler um Documento XML com Java (SAX) Cria um tratador para o documento. Este elemento irá indicar ao SAX qual objeto chamar quando encontrar os diferentes nós. Cria uma fábrica para a criação do parser SAX Ch17_02.java – continuação... Sistemas de Informação M JCFJ public void childLoop(String uri) { DefaultHandler saxHandler = this; SAXParserFactory saxFactory = SAXParserFactory.newInstance(); try { Cria o parser que irá SAXParser saxParser = saxFactory.newSAXParser(); realizar o parsing do saxParser.parse(new File(uri), saxHandler); documento } catch (Throwable t) {} } Realiza o parsing do documento public void startDocument() Método chamado quando o início { do documento é encontrado displayText[numberLines] = indentation; displayText[numberLines] += "<?xml version=\"1.0\" encoding=\""+ "UTF-8" + "\"?>"; numberLines++; } 17 XML Ler um Documento XML com Java (SAX) public void processingInstruction(String target, String data) { displayText[numberLines] = indentation; displayText[numberLines] += "<?"; displayText[numberLines] += target; Método chamado para manipular uma if (data != null && data.length() > 0) { instrução de processamento displayText[numberLines] += ' '; Observar que os parâmetros já são displayText[numberLines] += data; passados automaticamente } displayText[numberLines] += "?>"; numberLines++; } Ch17_02.java – continuação... Sistemas de Informação M JCFJ 18 XML Ler um Documento XML com Java (SAX) Ch17_02.java – continuação... Sistemas de Informação M public void startElement(String uri, String localName, String qualifiedName, Attributes attributes) Método chamado para manipular um { elemento de início Observar que displayText[numberLines] = indentation; os parâmetros já são passados automaticamente indentation += " "; } JCFJ displayText[numberLines] += '<'; displayText[numberLines] += qualifiedName; Verifica se o elemento if (attributes != null) { tem atributos int numberAttributes = attributes.getLength(); for (int loopIndex = 0; loopIndex < numberAttributes; loopIndex++) { displayText[numberLines] += ' '; displayText[numberLines] += attributes.getQName(loopIndex); displayText[numberLines] += "=\""; displayText[numberLines] += attributes.getValue(loopIndex); displayText[numberLines] += '"'; } } displayText[numberLines] += '>'; numberLines++; Se existirem atributos constrói sua apresentação 19 XML Ler um Documento XML com Java (SAX) Método utilizado para manipular texto public void characters(char characters[], int start, int length) { String characterData = (new String(characters, start, length)).trim(); if(characterData.indexOf("\n") < 0 && characterData.length() > 0) { displayText[numberLines] = indentation; Posição em que displayText[numberLines] += characterData; começa o texto do numberLines++; elemento } } Ch17_02.java – continuação... Sistemas de Informação M public void endElement(String uri, String localName, String qualifiedName) { indentation = indentation.substring(0, indentation.length() - 4); displayText[numberLines] = indentation; displayText[numberLines] += "</"; Método utilizado para displayText[numberLines] += qualifiedName; manipular o final do elemento displayText[numberLines] += '>'; numberLines++; } JCFJ 20 XML Ler um Documento XML com Java (SAX) public void warning(SAXParseException exception) { System.err.println("Warning: " + exception.getMessage()); } Ch17_02.java – continuação... Sistemas de Informação M public void error(SAXParseException exception) { System.err.println("Error: " + exception.getMessage()); } public void fatalError(SAXParseException exception) { System.err.println("Fatal error: " + exception.getMessage()); } } JCFJ Métodos utilizados para manipular os erros que possam ocorrer durante a manipulação do documento XML 21 XML Métodos da Classe DefaultHandler Sistemas de Informação Método Objetivo DefaultHandler() Construtor characters(char[] ch, int start, int length) Manipula nós de texto void endocument() Manipula o final do documento void endElement(String uri, String localName, String qName) Manipula o final do elemento void error(SAXParseException e) Manipula um erro recuperável void fatalError(SAXParseException e) Avisa de um erro fatal void ignorableWhitespace(char[] ch, int start, int length) Manipula “espaços descartáveis” void processingInstruction(String target, String data) Manipula inst. processamento void startDocument Manipula início do documento void startElement(String uri, String localName, String qName, Attributes attributes) Manipula o início de um elemento void startPrefixMapping(String prefix, String uri) Manipula o início de um namespace Outros existem: consultar http://java.sun.com/javase/6/docs/api/org/xml/sax/helpers/DefaultHandler.html JCFJ 22 XML – XML, Java e DOM Encontrando Elementos pelo Nome (SAX) package ismt; Ch17_03.java Sistemas de Informação import import import import java.io.*; org.xml.sax.*; javax.xml.parsers.*; org.xml.sax.helpers.DefaultHandler; public class Ch17_03 extends DefaultHandler { static int numberLines = 0; static String indentation = ""; static String displayText[] = new String[1000]; Variáveis que serão usadas para a busca pelo elemento static boolean displayBoolean; static String findNode; public static void main(String args[]) { Ch17_03 obj = new Ch17_03(); findNode = args[1]; obj.childLoop(args[0]); Argumento que identifica o elemento que será procurado for(int index = 0; index < numberLines; index++){ System.out.println(displayText[index]); } } JCFJ 23 XML – XML, Java e DOM Ch17_03.java – continuação... Sistemas de Informação Encontrando Elementos pelo Nome (SAX) M Idêntico ao anterior public void childLoop(String uri) { DefaultHandler saxHandler = this; SAXParserFactory saxFactory = SAXParserFactory.newInstance(); try { SAXParser saxParser = saxFactory.newSAXParser(); saxParser.parse(new File(uri), saxHandler); } catch (Throwable t) {} } JCFJ 24 XML – XML, Java e DOM Encontrando Elementos pelo Nome (SAX) M Ch17_03.java – continuação... Sistemas de Informação public void startElement(String uri, String localName, String qualifiedName, Attributes attributes) Verifica se o nó é o que se está { procurando. Caso seja, define if(qualifiedName.equals(findNode)){ displayBoolean=true; displayBoolean para verdadeiro } Se a variável displayBoolean for if (displayBoolean){ verdadeira o elemento será displayText[numberLines] = indentation; inserido indentation += " "; displayText[numberLines] += '<'; displayText[numberLines] += qualifiedName; if (attributes != null) { int numberAttributes = attributes.getLength(); for (int loopIndex = 0; loopIndex < numberAttributes; loopIndex++) { displayText[numberLines] displayText[numberLines] displayText[numberLines] displayText[numberLines] displayText[numberLines] } } displayText[numberLines] += '>'; numberLines++; } } JCFJ += += += += += ' '; attributes.getQName(loopIndex); "=\""; attributes.getValue(loopIndex); '"'; 25 XML – XML, Java e DOM Encontrando Elementos pelo Nome (SAX) public void characters(char characters[], int start, int length) { if(displayBoolean){ String characterData = (new String(characters, start, length)).trim(); if(characterData.indexOf("\n") < 0 && characterData.length() > 0) { displayText[numberLines] = indentation; displayText[numberLines] += characterData; numberLines++; } Se a variável displayBoolean } for verdadeira o elemento } de texto será inserido Ch17_03.java – continuação... Sistemas de Informação M public void endElement(String uri, String localName, String qualifiedName) { if(displayBoolean){ indentation = indentation.substring(0, indentation.length() - 4); displayText[numberLines] = indentation; displayText[numberLines] += "</"; displayText[numberLines] += qualifiedName; displayText[numberLines] += '>'; numberLines++; Após ter encontrado o } nó do final do elemento if(qualifiedName.equals(findNode)){ procurado, define-se displayBoolean=false; displayBoolean para } false para as próximas } buscas JCFJ 26 XML – XML, Java e DOM Encontrando Elementos pelo Nome (SAX) public void warning(SAXParseException exception) { System.err.println("Warning: " + exception.getMessage()); } Ch17_03.java – continuação... Sistemas de Informação M public void error(SAXParseException exception) { System.err.println("Error: " + exception.getMessage()); } public void fatalError(SAXParseException exception) { System.err.println("Fatal error: " + exception.getMessage()); } } JCFJ Semelhante ao do exemplo anterior 27 XML APIs para Manipulação de XML Existem diversas API para a serialização de objetos Java como documentos XML Uma bastante interessante é a Simple – XML Serialization: Sistemas de Informação http://simple.sourceforge.net/home.php APIs como esta podem ser usadas para a troca de informações entre sistema criando e lendo de forma bastante simples documentos XML que representam os objetos de uma aplicação. Para maiores informações: http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php JCFJ 28 XML Exercícios Exercíício 1: Exerc Sistemas de Informação Compilar os programas, analisar o código e verificar a saída de cada um deles. Exercí Exercício 2: Escrever um programa Java que leia o documento XML ch16_01.xml e que procure o elemento <firstName>Thomas</firstName>. Quando o encontrar o elemento, o programa deve escrever na saída de texto == > Encontrei o Thomas < ==. Exercí Exercício 3: Escrever um programa Java que leia o documento XML ch16_01.xml e que apresente uma mensagem indicando quantos elementos do tipo senator existem no documento. JCFJ