如何读取和写入XML文件?

我必须读取和写入和从XML文件。 使用Java读取和写入XML文件最简单的方法是什么?

这是一个快速的DOM示例,展示了如何使用它的dtd读取和写入一个简单的xml文件:

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

和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)> 

首先导入这些:

 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.*; 

这里有一些你需要的变量:

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

这里是一个阅读器(字符串xml是您的XML文件的名称):

 public boolean readXML(String xml) { rolev = new ArrayList<String>(); 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; } 

在这里一个作家:

 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在这里:

 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; } 

添加一些accessor和mutators,你就完成了!

上面的答案只涉及DOM解析器(通常读取内存中的整个文件并解析它,对于大文件是一个问题),您可以使用SAX解析器,使用更少的内存,速度更快(无论如何,这取决于您的码)。

SAX解析器在找到元素的开始,元素的结尾,元素之间的属性,元素之间的文本等时会回调一些函数,因此它可以解析文档,同时获得所需的东西。

一些示例代码:

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

使用JAXB编写XML(用于XML绑定的Java体系结构):

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(); } } } 

答案只包括DOM / SAX和JAXB示例的复制粘贴实现。

但是,当您使用XML的一大块区域缺失。 在许多项目/程序中,需要存储/检索一些基本的数据结构。 你的程序已经有了一个适合你的漂亮而闪亮的业务对象/数据结构的类,你只需要一个舒适的方式来将这些数据转换为XML结构,这样你就可以做更多的魔术(存储,加载,发送和使用XSLT) 。

这是XStream的亮点。 您只需注解保存数据的类,或者如果您不想更改这些类,则可以配置用于编组(对象 – > xml)或解组(xml – >对象)的XStream实例。

内部XStream使用反射,即标准Java对象序列化的readObject和readResolve方法。

你在这里得到一个好的和快速的教程:

为了简要介绍它是如何工作的,我还提供了一些编组和解组数据结构的示例代码。 编组/解组发生在main方法中,剩下的只是生成一些测试对象的代码,并为它们填充一些数据。 配置xStream实例是非常简单的,编组/解组每一行代码完成。

 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<Good> stock = new ArrayList<Good>(); Customer add(Good g) { stock.add(g); return this; } } } 

好的,在答案列表中已经有了DOM,JaxB和XStream,但是仍然有一种完全不同的方式来读写XML: 数据投影您可以使用提供可读写视图的库来分离XML结构和Java结构到XML数据作为Java接口。 从教程 :

给定一些真实世界的XML:

 <weatherdata> <weather ... degreetype="F" lat="50.5520210266113" lon="6.24060010910034" searchlocation="Monschau, Stadt Aachen, NW, Germany" ... > <current ... skytext="Clear" temperature="46"/> </weather> </weatherdata> 

通过数据投影,您可以定义投影界面:

 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(); } 

和POJO一样使用这个接口的实例:

 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()); } 

这甚至可以用于创建XML,XPath表达式可以是可写的。

SAX解析器与DOM解析器的工作方式不同,既不会将任何XML文档加载到内存中,也不会创建任何XML文档的对象表示形式。 相反,SAX解析器使用回调函数(org.xml.sax.helpers.DefaultHandler)来通知客户端XML文档结构。

SAX解析器比DOM解析器速度更快,占用内存更少。 请参阅以下SAX回调方法:

startDocument()和endDocument() – 在XML文档的开始和结束处调用的方法。 startElement()和endElement() – 在文档元素的开始和结束处调用的方法。 characters() – 使用XML文档元素的开始和结束标记之间的文本内容调用的方法。 1. XML文件创建一个简单的XML文件。

 <?xml version="1.0"?> <company> <staff> <firstname>yong</firstname> <lastname>mook kim</lastname> <nickname>mkyong</nickname> <salary>100000</salary> </staff> <staff> <firstname>low</firstname> <lastname>yin fong</lastname> <nickname>fong fong</nickname> <salary>200000</salary> </staff> </company> 
  1. Java文件使用SAX解析器来解析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(); } } } 

结果

开始元素:公司
开始元素:工作人员
开始元素:名字
名:yong
结束元素:名字
开始元素:姓氏
姓氏:mook kim
结束元素:姓氏
开始元素:昵称
昵称:mkyong
结束元素:昵称
等等…

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