Como ler e gravar arquivos xml?

Eu tenho que ler e escrever de e para um arquivo XML . Qual é a maneira mais fácil de ler e gravar arquivos XML usando Java?

Aqui está um exemplo rápido do DOM que mostra como ler e escrever um arquivo xml simples com seu dtd:

< ?xml version="1.0" encoding="UTF-8" standalone="no"?> < !DOCTYPE roles SYSTEM "roles.dtd">  User Author Admin   

e o dtd:

 < ?xml version="1.0" encoding="UTF-8"?> < !ELEMENT roles (role1,role2,role3,role4)> < !ELEMENT role1 (#PCDATA)> < !ELEMENT role2 (#PCDATA)> < !ELEMENT role3 (#PCDATA)> < !ELEMENT role4 (#PCDATA)> 

Primeiro importe estes:

 import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; import org.xml.sax.*; import org.w3c.dom.*; 

Aqui estão algumas variables ​​que você precisará:

 private String role1 = null; private String role2 = null; private String role3 = null; private String role4 = null; private ArrayList rolev; 

Aqui está um leitor (String xml é o nome do seu arquivo xml):

 public boolean readXML(String xml) { rolev = new ArrayList(); Document dom; // Make an instance of the DocumentBuilderFactory DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { // use the factory to take an instance of the document builder DocumentBuilder db = dbf.newDocumentBuilder(); // parse using the builder to get the DOM mapping of the // XML file dom = db.parse(xml); Element doc = dom.getDocumentElement(); role1 = getTextValue(role1, doc, "role1"); if (role1 != null) { if (!role1.isEmpty()) rolev.add(role1); } role2 = getTextValue(role2, doc, "role2"); if (role2 != null) { if (!role2.isEmpty()) rolev.add(role2); } role3 = getTextValue(role3, doc, "role3"); if (role3 != null) { if (!role3.isEmpty()) rolev.add(role3); } role4 = getTextValue(role4, doc, "role4"); if ( role4 != null) { if (!role4.isEmpty()) rolev.add(role4); } return true; } catch (ParserConfigurationException pce) { System.out.println(pce.getMessage()); } catch (SAXException se) { System.out.println(se.getMessage()); } catch (IOException ioe) { System.err.println(ioe.getMessage()); } return false; } 

E aqui um escritor:

 public void saveToXML(String xml) { Document dom; Element e = null; // instance of a DocumentBuilderFactory DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { // use factory to get an instance of document builder DocumentBuilder db = dbf.newDocumentBuilder(); // create instance of DOM dom = db.newDocument(); // create the root element Element rootEle = dom.createElement("roles"); // create data elements and place them under root e = dom.createElement("role1"); e.appendChild(dom.createTextNode(role1)); rootEle.appendChild(e); e = dom.createElement("role2"); e.appendChild(dom.createTextNode(role2)); rootEle.appendChild(e); e = dom.createElement("role3"); e.appendChild(dom.createTextNode(role3)); rootEle.appendChild(e); e = dom.createElement("role4"); e.appendChild(dom.createTextNode(role4)); rootEle.appendChild(e); dom.appendChild(rootEle); try { Transformer tr = TransformerFactory.newInstance().newTransformer(); tr.setOutputProperty(OutputKeys.INDENT, "yes"); tr.setOutputProperty(OutputKeys.METHOD, "xml"); tr.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); tr.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "roles.dtd"); tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); // send DOM to file tr.transform(new DOMSource(dom), new StreamResult(new FileOutputStream(xml))); } catch (TransformerException te) { System.out.println(te.getMessage()); } catch (IOException ioe) { System.out.println(ioe.getMessage()); } } catch (ParserConfigurationException pce) { System.out.println("UsersXML: Error trying to instantiate DocumentBuilder " + pce); } } 

getTextValue está aqui:

 private String getTextValue(String def, Element doc, String tag) { String value = def; NodeList nl; nl = doc.getElementsByTagName(tag); if (nl.getLength() > 0 && nl.item(0).hasChildNodes()) { value = nl.item(0).getFirstChild().getNodeValue(); } return value; } 

Adicione alguns accessors e mutators e pronto!

A resposta acima apenas lida com o analisador DOM (que normalmente lê o arquivo inteiro na memory e o analisa, o que para um arquivo grande é um problema), você poderia usar um analisador SAX que usa menos memory e é mais rápido (de qualquer maneira que depende do seu código).

Chamadas de retorno do analisador SAX algumas funções quando encontrar um início de elemento, fim de elemento, atributo, texto entre elementos, etc, para que possa analisar o documento e, ao mesmo tempo, obter o que você precisa.

Algum código de exemplo:

http://www.mkyong.com/java/how-to-read-xml-file-in-java-sax-parser/

Escrevendo XML usando JAXB (Arquitetura Java para Ligação XML):

http://www.mkyong.com/java/jaxb-hello-world-example/

 package com.mkyong.core; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Customer { String name; int age; int id; public String getName() { return name; } @XmlElement public void setName(String name) { this.name = name; } public int getAge() { return age; } @XmlElement public void setAge(int age) { this.age = age; } public int getId() { return id; } @XmlAttribute public void setId(int id) { this.id = id; } } package com.mkyong.core; import java.io.File; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; public class JAXBExample { public static void main(String[] args) { Customer customer = new Customer(); customer.setId(100); customer.setName("mkyong"); customer.setAge(29); try { File file = new File("C:\\file.xml"); JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // output pretty printed jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(customer, file); jaxbMarshaller.marshal(customer, System.out); } catch (JAXBException e) { e.printStackTrace(); } } } 

As respostas cobrem apenas DOM / SAX e uma implementação de colar de cópia de um exemplo de JAXB.

No entanto, uma grande área de quando você está usando XML está faltando. Em muitos projetos / programas, é necessário armazenar / recuperar algumas estruturas básicas de dados. Seu programa já tem aulas para seus objects de negócios / estruturas de dados agradáveis ​​e shinys, você só quer uma maneira confortável de converter esses dados em uma estrutura XML para poder fazer mais mágica (armazenar, carregar, enviar, manipular com XSLT) .

É aqui que XStream brilha. Você simplesmente anota as classs que contêm seus dados ou, se não quiser alterar essas classs, configura uma instância XStream para marshalling (objects -> xml) ou unmarshalling (xml -> objects).

Internamente, o XStream usa os methods reflection, readObject e readResolve da serialização padrão de objects Java.

Você tem um tutorial bom e rápido aqui :

Para dar uma breve visão geral de como funciona, eu também forneço um código de exemplo que organiza e desmarca uma estrutura de dados. O marshalling / unmarshalling acontece no método main , o resto é apenas código para gerar alguns objects de teste e preencher alguns dados para eles. É super simples configurar a instância xStream e o empacotamento / desmarque é feito com uma linha de código cada.

 import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import com.thoughtworks.xstream.XStream; public class XStreamIsGreat { public static void main(String[] args) { XStream xStream = new XStream(); xStream.alias("good", Good.class); xStream.alias("pRoDuCeR", Producer.class); xStream.alias("customer", Customer.class); Producer a = new Producer("Apple"); Producer s = new Producer("Samsung"); Customer c = new Customer("Someone").add(new Good("S4", 10, new BigDecimal(600), s)) .add(new Good("S4 mini", 5, new BigDecimal(450), s)).add(new Good("I5S", 3, new BigDecimal(875), a)); String xml = xStream.toXML(c); // objects -> xml System.out.println("Marshalled:\n" + xml); Customer unmarshalledCustomer = (Customer)xStream.fromXML(xml); // xml -> objects } static class Good { Producer producer; String name; int quantity; BigDecimal price; Good(String name, int quantity, BigDecimal price, Producer p) { this.producer = p; this.name = name; this.quantity = quantity; this.price = price; } } static class Producer { String name; public Producer(String name) { this.name = name; } } static class Customer { String name; public Customer(String name) { this.name = name; } List stock = new ArrayList(); Customer add(Good g) { stock.add(g); return this; } } } 

Ok, já tendo DOM, JaxB e XStream na lista de respostas, ainda há uma maneira completamente diferente de ler e gravar XML: Projeção de dados É possível desacoplar a estrutura XML e a estrutura Java usando uma biblioteca que fornece visualizações de leitura e graváveis aos dados XML como interfaces Java. Dos tutoriais :

Dado algum XML do mundo real:

      

Com projeção de dados, você pode definir uma interface de projeção:

 public interface WeatherData { @XBRead("/weatherdata/weather/@searchlocation") String getLocation(); @XBRead("/weatherdata/weather/current/@temperature") int getTemperature(); @XBRead("/weatherdata/weather/@degreetype") String getDegreeType(); @XBRead("/weatherdata/weather/current/@skytext") String getSkytext(); /** * This would be our "sub projection". A structure grouping two attribute * values in one object. */ interface Coordinates { @XBRead("@lon") double getLongitude(); @XBRead("@lat") double getLatitude(); } @XBRead("/weatherdata/weather") Coordinates getCoordinates(); } 

E use instâncias dessa interface como POJOs:

 private void printWeatherData(String location) throws IOException { final String BaseURL = "http://weather.service.msn.com/find.aspx?outputview=search&weasearchstr="; // We let the projector fetch the data for us WeatherData weatherData = new XBProjector().io().url(BaseURL + location).read(WeatherData.class); // Print some values System.out.println("The weather in " + weatherData.getLocation() + ":"); System.out.println(weatherData.getSkytext()); System.out.println("Temperature: " + weatherData.getTemperature() + "°" + weatherData.getDegreeType()); // Access our sub projection Coordinates coordinates = weatherData.getCoordinates(); System.out.println("The place is located at " + coordinates.getLatitude() + "," + coordinates.getLongitude()); } 

Isso funciona mesmo para criar XML, as expressões XPath podem ser graváveis.

SAX analisador SAX está funcionando de maneira diferente com um analisador DOM , não carrega nenhum documento XML na memory nem cria qualquer representação de object do documento XML . Em vez disso, o analisador SAX usa a function de retorno de chamada org.xml.sax.helpers.DefaultHandler para informar os clientes da estrutura do documento XML .

SAX Parser é mais rápido e usa menos memory que o analisador DOM . Veja os seguintes methods de retorno de chamada SAX :

startDocument() e endDocument() – Método chamado no início e no final de um documento XML. startElement() e endElement() – Método chamado no início e no final de um elemento do documento. characters() – Método chamado com o conteúdo do texto entre as tags inicial e final de um elemento de documento XML.

  1. Arquivo XML

Crie um arquivo XML simples.

 < ?xml version="1.0"?>   yong mook kim mkyong 100000   low yin fong fong fong 200000   
  1. Analisador de XML:

Arquivo Java Use o analisador SAX para analisar o arquivo XML.

 import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class ReadXMLFile { public static void main(String argv[]) { try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); DefaultHandler handler = new DefaultHandler() { boolean bfname = false; boolean blname = false; boolean bnname = false; boolean bsalary = false; public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException { System.out.println("Start Element :" + qName); if (qName.equalsIgnoreCase("FIRSTNAME")) { bfname = true; } if (qName.equalsIgnoreCase("LASTNAME")) { blname = true; } if (qName.equalsIgnoreCase("NICKNAME")) { bnname = true; } if (qName.equalsIgnoreCase("SALARY")) { bsalary = true; } } public void endElement(String uri, String localName, String qName) throws SAXException { System.out.println("End Element :" + qName); } public void characters(char ch[], int start, int length) throws SAXException { if (bfname) { System.out.println("First Name : " + new String(ch, start, length)); bfname = false; } if (blname) { System.out.println("Last Name : " + new String(ch, start, length)); blname = false; } if (bnname) { System.out.println("Nick Name : " + new String(ch, start, length)); bnname = false; } if (bsalary) { System.out.println("Salary : " + new String(ch, start, length)); bsalary = false; } } }; saxParser.parse("c:\\file.xml", handler); } catch (Exception e) { e.printStackTrace(); } } } 

Resultado

Start Element: empresa
Elemento Inicial: equipe
Elemento inicial: nome próprio
Primeiro nome: yong
Elemento final: nome próprio
Elemento inicial: sobrenome
Último Nome: mook kim
Elemento final: sobrenome
Elemento inicial: apelido
Nick Name: mkyong
Elemento final: apelido
e assim por diante…

Fonte (MyKong) – http://www.mkyong.com/java/how-to-read-xml-file-in-java-sax-parser/