XML APIs Material parcialmente extraído de: Alan Robinson em http://industry.ebi.ac.uk/~alan/xmlworkshop/presentations/ Dickson K.W. Chiu em http://www.cse.cuhk.edu.hk/~kwchiu/csc3530/ Curso de Mestrado/Doutorado DCC/NCE UFRJ http://genesis.nce.ufrj.br/dataware Agenda Introdução Níveis de especificação DOM Navegando e editando uma árvore DOM Tipos de Nó DOM Criando uma árvore DOM Exercícios 1
Introdução Objetivo W3C: prover uma interface de programação padrão para aplicações que manipulam XML. Portabilidade: projetado para ser usado com qualquer linguagem de programação e em qualquer sistema operacional. Funcionalidade: criar um documento XML navegar na estrutura de um documento XML adicionar, modificar ou remover elementos nesta estrutura XML API Dois tipos: tree-based e event-based Tree-based API (eg., DOM) transforma um documento XML em um estrutura em árvore na memória => uso extensivo da memória. Event-based API (eg., SAX) identifica eventos ao efetuar a análise do documento (parsing) e notifica a aplicação, como por exemplo para informar que um tag foi aberto sem o /tag correspondente. 2
DOM vs. SAX XML document DOM XML parser parse Application DOM get information XML document SAX parse XML parser Application Event handlers information DOM (W3C) a platform- and language-neutral interface that will allow programs and scripts to dynamically access and update the content, structure and style of documents. Application DOM API XML parser XML document 3
Árvore DOM Document Node <bibliografia> <livro id= 123 >DOM em 1h!</livro> </bibliografia> Element Node NodeList <bibliografia> id= 123 DOM em 1h! Attr Node Text CharacterData Node Named NodeMap NodeList NodeList Element Node <livro> Interfaces DOM Figure as from The XML Companion - Neil Bradley Node DocumentFragment Document Text CDATASection CharacterData Attr Comment Element DocumentType Notation NodeList NamedNodeMap Entity EntityReference DocumentType ProcessingInstruction 4
Node Interface Objeto básico do DOM Vários objetos herdam desta interface 3 tipos de métodos Básicos name, type, value Navegação parents, siblings, children, ancestors, descendants Manipulação Edit, delete, re-arrange child nodes Métodos básicos short getnodetype(); String getnodename(); String getnodevalue(); void setnodevalue(string value); if (mynode.getnodetype() == Node.ELEMENT_NODE) { //process node 5
Métodos de navegação Somente os seguintes tipos de nó podem ter filhos: Document, DocumentFragment, Element Verificando a presença de nós filhos if (mynode.haschildnodes()) { //process children of mynode Métodos de Navegação Encontrando filhos,pais e irmãos Node getfirstchild(); Node getlastchild(); Node getnextsibling(); Node getprevioussibling(); Node getparentnode(); NodeList getchildnodes(); 6
Navegando pelos nós Figure as from The XML Companion - Neil Bradley getparentnode() parent A B C D getnextsibling() E F getprevioussibling() getlastchild() getchildnodes() getfirstchild() Node mynode = parent.getfirstchild(); mynode = mynode.getnextsibling(); if (mynode.haschildren()) { NodeList children = mynode.getchildnodes(); Navegando pelos nós É possível também recuperar uma lista de nós com mesmo tag através do método getelementsbytagname() do objeto Document NodeList resultado = mydoc.getelementsbytagname( book ); for (I=0; I<resultado.length();I++) {... 7
Métodos de Manipulação Filhos de um nó em uma árvore DOM podem ser adicionados, removidos, substituidos, copiados, movidos, etc. Node removechild(node old) Node insertbefore(node new, Node ref) Node appendchild(node new) Node replacechild(node new, Node old) Node clonenode(boolean deep); Manipulando nós Figure as from The XML Companion - Neil Bradley Ref Old New New insertbefore replacechild Deep = 'false' clonenode Deep = 'true' 8
Document::Node Interface Raiz da árvore DOM: representa todo o documento XML Métodos básicos //Information from DOCTYPE - See 'DocumentType' DocumentType getdocumenttype(); //Information about capabilities of DOM implementation DOMImplementation getimplementation(); //Returns reference to root node element Element getdocumentelement(); //Searches for all occurrences of 'tagname' in nodes NodeList getelementsbyname(string tagname); Document::Node Interface (2) Métodos para criação de outros tipos de nó Element createelement(string tagname); Text createtextnode(string data); Comment createcomment(string data); CDATASection createcdatasection(string data); ProcessingInstruction createprocessinginstruction (String target, String data); Attr createattribute(string name); 9
Element::Node Interface Métodos básicos String gettagname(); NodeList getelementsbytagname(); void normalize(); Métodos para manipulação de atributos String getattribute(string name); void setattribute(string name, String value) ; void removeattribute(string name) ; Attr getattributenode(string name); void setattributenode(attr new); void removeattributenode(attr old) ; Para obter a lista de atributos é preciso usar o método NamedNodeMap getattributes() Attr::Node Interface Interface para tratar atributos //Get name of attribute String getname(); //Get value of attribute String getvalue(); //Change value of attribute void setvalue(string value); //if 'true' - attribute defined in element, else in DTD boolean getspecified(); 10
Attr::Node Interface (2) É possível criar objetos Attr através dos métodos de criação de nós da interface Document //Create the empty Attribute node Attr newattr = mydoc.createattribute("status"); //Set the value of the attribute newattr.setvalue("secret"); //Attach the attribute to an element myelement.setattributenode(newattr); Text::Node Interface Representa o conteúdo textual dos nós Element Usualmente aparece como filho destes nós Sempre são nós folha Único método próprio (não herdado) Text splittext(int offset) Também pode ser criado a partir de método na interface Document O método normalize() em um objeto Nó, concatena os objetos Text das folhas a partir deste nó, sem deixar dois textos adjacentes. 11
Comment::Text Interface Representa Comentários Todos os caracteres entre '<!--' e '-->' Também pode ser criado a partir de método na interface Document Comment newcomment = mydoc.createcomment(" my comment "); ProcessingInstruction::Node Interface Representa as declarações de instruções de processamento Name of node is target application name Value of node is target application command //Get the content of the processing instruction String getdata() //Set the content of the processing instruction void setdata(string data) //The target of this processing instruction String gettarget(); Pode ser criado a partir do objeto Document ProcessingInstruction newpi = mydoc.createprocessinginstruction("acme", "page-break"); 12
NodeList Interface Representa uma coleção ordenada de objetos Node Métodos //Find number of Nodes in NodeList int getlength(); //Return the i-th Node Node item(int index); Percorrendo os nós filho de um elemento Node child; NodeList children = elemento.getchildnodes()' for (int i = 0; i < children.getlength(); i++) { child = children.item(i); if (child.getnodetype() == Node.ELEMENT_NODE) { System.out.println(child.getNodeName()); NamedNodeMap Interface Coleção não ordenada de objetos Node E.g. Attribute, Entity and Notation Acesso depende de nome único NamedNodeMap myattributes = myelement.getattributes(); NamedNodeMap myentities = mydocument.getentities(); NamedNodeMap mynotations = mydocument.getnotations(); ------------------------------------------------------ int getlength(); Node item(int index); Node getnameditem(string name); Node setnameditem(node node) ; Node removenameditem(string name) ; 13
DOMImplementation Interface É possível verificar as funcionalidades da implementação DOM através do método: hasfeature(string feature, String version); if (theparser.hasfeature("xml", "1.0") { //XML is supported Utilização do DOM (Java) Processo em 3 passos Criar o DocumentBuilderFactory. Este objeto criará o DocumentBuilder. Criar o DocumentBuilder. O DocumentBuilder fará o parsing para criar o objeto Document. Fazer o parsing do arquivo para criar o objeto Document. 14
Exemplo de aplicação básica import javax.xml.parsers.documentbuilder; import javax.xml.parsers.documentbuilderfactory; import java.io.file; import org.w3c.dom.document; public class OrderProcessor { public static void main (String args[]) { File docfile = new File("orders.xml"); Document doc = null; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newdocumentbuilder(); doc = db.parse(docfile); catch (Exception e) { System.out.print( Erro ao analisar o arquivo."); Exemplo Básico import javax.xml.parsers.documentbuilder; import javax.xml.parsers.documentbuilderfactory; import java.io.file; import org.w3c.dom.document; import org.w3c.dom.element; public class OrderProcessor { System.exit(1); //Recupera o elemento raiz (root) Element root = doc.getdocumentelement(); System.out.println( O elemento raiz é " + root.getnodename()); 15
Exemplo Básico import org.w3c.dom.nodelist; //Recupera o elemento raiz(root) Element root = doc.getdocumentelement(); System.out.println( O elemento raiz é "+root.getnodename()); //Recupera os filhos (children) NodeList children = root.getchildnodes(); System.out.println( Existem "+children.getlength()+" nós neste documento."); Exemplo Básico import org.w3c.dom.node; //recuperando o nome e valor dos filhos (children) for (Node child = root.getfirstchild(); child!= null; child = child.getnextsibling()) { System.out.println(child.getNodeName()+" = "+child.getnodevalue()); 16
Exemplo Básico public class OrderProcessor { private static void stepthrough (Node start) { System.out.println(start.getNodeName()+" = "+start.getnodevalue()); for (Node child = start.getfirstchild(); child!= null;child = child.getnextsibling()) { //Recuperando os filhos recursivamente stepthrough(child); public static void main (String args[]) { File docfile = new File("orders.xml"); System.out.println( Existem "+children.getlength() +" nós neste documento."); stepthrough(root); Manipulando Atributos import org.w3c.dom.namednodemap; private static void stepthroughall (Node start) { System.out.println(start.getNodeName()+" = "+start.getnodevalue()); if (start.getnodetype() == start.element_node) { NamedNodeMap startattr = start.getattributes(); for (int i = 0; i < startattr.getlength(); i++) { Node attr = startattr.item(i); System.out.println(" Atributo: "+ attr.getnodename() +" = "+attr.getnodevalue()); for (Node child = start.getfirstchild(); child!= null; child = child.getnextsibling()) { stepthroughall(child); 17
SAX SAX 2.0 (Maio 2000) SAX = Simple API for XML Suporta namespaces e a consulta/edição de propriedades do parser Domínio público (XML-DEV mailing list) Usa um modelo baseado em eventos Notificações (eventos) ocorrem à medida em que o documento é analizado ( parsed ) 18
Event-Based API Considere o documento <doc> <para>hello, world!</para> </doc> Umainterface baseadaem eventosgerauma lista de eventos como a que se segue: start document start element: doc start element: para characters: Hello, world! end element: para end element: doc end document Métodos invocados pelo SAX parser Método setdocumentlocator startdocument enddocument startelement endelement characters ignorablewhitespace processinginstruction Descrição Invocado no início do parsing. Invocado quando o parser encontra o início de um documento XML Invocado quando o parser encontra o fim de um documento XML Invocado quando a tag de inicio de um elemento é encontrada Invocado quando a tag de fim de um elemento é encontrada. Invocado quando text characters são encontrados. Invocado quando whitespace que pode ser ignorado é encontrado. Invocado quando um PI é encontrada. 19
Como SAX funciona? Processamento em SAX envolve os seguintes passos 1. Criar um event handler 2. Criar o SAX parser 3. Associar o event handler ao parser criado 4. Fazer o parsing do documento, enviando cada evento ao event handler. Exemplo: Uma pesquisa de opinião <?xml version="1.0"?> <surveys> <response username="bob"> <question subject="appearance">a</question> <question subject="communication">b</question> <question subject="ship">a</question> <question subject="inside">d</question> <question subject="implant">b</question> </response> <response username="sue"> <question subject="appearance">c</question> <question subject="communication">a</question> <question subject="ship">a</question> <question subject="inside">d</question> <question subject="implant">a</question> </response> <response username="carol"> <question subject="appearance">a</question> <question subject="communication">c</question> <question subject="ship">a</question> <question subject="inside">d</question> <question subject="implant">c</question> </response> </surveys> 20
Criando um event handler import org.xml.sax.helpers.defaulthandler; public class SurveyReader extends DefaultHandler { public SurveyReader() { System.out.println("Object Created."); public void showevent(string name) { System.out.println("Hello, "+name+"!"); public static void main (String args[]) { SurveyReader reader = new SurveyReader(); reader.showevent( Nick"); import org.xml.sax.helpers.defaulthandler; import javax.xml.parsers.saxparser; import javax.xml.parsers.saxparserfactory; import org.xml.sax.xmlreader; public class SurveyReader extends DefaultHandler { Criando o Parser SAX public SurveyReader() { public static void main (String args[]) { XMLReader xmlreader = null; try { SAXParserFactory spfactory = SAXParserFactory.newInstance(); SAXParser saxparser = spfactory.newsaxparser(); xmlreader = saxparser.getxmlreader(); catch (Exception e) { System.err.println(e); System.exit(1); 21
Associando o event handler ao parser xmlreader = saxparser.getxmlreader(); xmlreader.setcontenthandler(new SurveyReader()); catch (Exception e) { Executando o parser do documento import org.xml.sax.inputsource; xmlreader = saxparser.getxmlreader(); xmlreader.setcontenthandler(new SurveyReader()); InputSource source = new InputSource("surveys.xml"); xmlreader.parse(source); catch (Exception e) { 22
Criando um ErrorHandler import org.xml.sax.saxparseexception; public class SurveyReader extends DefaultHandler { public SurveyReader() { public void error (SAXParseException e) { System.out.println("Error parsing the file: "+e.getmessage()); public void warning (SAXParseException e) { System.out.println("Problem parsing the file: "+e.getmessage()); public void fatalerror (SAXParseException e) { System.out.println("Error parsing the file: "+e.getmessage()); System.out.println("Cannot continue."); System.exit(1); public static void main (String args[]) { Associando o ErrorHandler xmlreader.setcontenthandler(new SurveyReader()); xmlreader.seterrorhandler(new SurveyReader()); InputSource source = new InputSource("surveys.xml"); 23
Eventos: startdocument() import org.xml.sax.saxexception; public class SurveyReader extends DefaultHandler { public void fatalerror (SAXParseException e) { System.out.println("Error parsing " + "the file: "+e.getmessage()); System.out.println("Cannot continue."); System.exit(1); public void startdocument() throws SAXException { System.out.println("Tallying survey results"); public static void main (String args[]) { Eventos: startelement() import org.xml.sax.attributes; public class SurveyReader extends DefaultHandler { public void startdocument() throws SAXException { System.out.println("Tallying survey results"); public void startelement( String namespaceuri, String localname, String qname, Attributes atts) throws SAXException { System.out.print("Start element: "); System.out.println(localName); public static void main (String args[]) { 24
startelement(): recuperando atributos public void startelement( String namespaceuri, String localname, String qname, Attributes atts) throws SAXException { System.out.print("Start element: "); System.out.println(localName); for (int att = 0; att < atts.getlength(); att++) { String attname = atts.getlocalname(att); System.out.println(" " + attname + ": " + atts.getvalue(attname)); Obtendo Dados: characters() // ch inclui o documento inteiro public void characters(char[] ch, int start, int length) throws SAXException { if (thiselement == "question") { printindent(4); System.out.print(thisQuestion + ": "); System.out.println(new String(ch, start, length)); 25
Obtendo Dados: characters() public void printindent(int indentsize) { for (int s = 0; s < indentsize; s++) { System.out.print(" "); String thisquestion = ""; String thiselement = ""; public void startelement(string namespaceuri, String localname, String qname, Attributes atts) throws SAXException { if (localname == "response") { System.out.println("User: "+ atts.getvalue("username")); else if (localname == "question") { thisquestion = atts.getvalue("subject"); thiselement = localname; public void endelement(string namespaceuri,string localname,string qname)throws SAXException { thisquestion = ""; thiselement = ""; public void characters(char[] ch, int start, int length) throws SAXException { if (thiselement == "question") { printindent(4); System.out.print(thisQuestion + ": "); System.out.println(new String(ch, start, length)); Referências Especificações DOM http://www.w3.org/dom outros recursos encontrados em http://www.oasisopen.org/cover/dom.html Tutorial para JavaScript e VBScript http://www.w3schools.com/dom Tutorial para Java: Understanding DOM http://www.ibm.com Microsoft.XMLDOM (exemplos em script e vbscript) http://msdn.microsoft.com Apache XML project http://xml.apache.org/ 26