最近用得到xml的解析方式,于是就翻了翻自己的笔记同时从网上查找了资料,自己在前人的基础上总结了下,贴出来大家分享下。
首先介绍一下xml语言:
可扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。
xml的语法:
XML 分为两部分:头信息,主体信息
头信息是用来描述 XML 的一些属性,例如:版本,编码等,还可以提供 XML 显示的样式,和 dtd 编写格式。
主体信息中包含的是 XML 的具体数据。
头信息的语法:
<?xml version =”1.0” encoding =”GBK” ?>
其中 version 是必须加的,而 encoding 可以不写,则默认编码是 ISO8859-1 ,不支持中文。
除了这个功能外,头信息还可以进行编写格式的规定,通过 dtd 或 xsd 文件。
头信息还支持样式表的导入,允许通过样式表控制 XML 的显示。
这样可以使用 XML+ CSS 完成页面的显示,通过这种形式完成 MVC 中的 View 层:
优点:代码的安全性很高,可以很容易的替换模板。
缺点:开发成本太高
主体信息 就是由三种节点组成的,节点之间存在父与子的关系,注意的点:
一个节点只能有一个父节点,如果没有父节点,该节点称为根节点。
一个节点可以有多个子节点。只有元素节点可以拥有子节点。
元素节点的标记必须成对出现,或直接结束。
特殊字符必须转义。依据字符所处的位置是否对 XML 格式造成影响来决定是否进行转义
根节点只能有一个
xml常用的四种解析方式:
1)DOM(Document Object Model)
文档对象模型分析方式。以层次结构(类似于树型)来组织节点和信息片段,映射XML文档的结构,允许获取和操作文档的任意部分。是W3C的官方标准。
优点:
1、允许应用程序对数据和结构做出更改。
2、访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。
缺点:
1、通常需要加载整个XML文档来构造层次结构,消耗资源大
2)SAX(Simple API for XML)
流模型中的推模型分析方式。通过事件驱动,每发现一个节点就引发一个事件,通过回调方法完成解析工作,解析XML文档的逻辑需要应用程序完成。
优点:
1、不需要等待所有数据都被处理,分析就能立即开始。
2、只在读取数据时检查数据,不需要保存在内存中。
3、可以在某个条件得到满足时停止解析,不必解析整个文档。
4、效率和性能较高,能解析大于系统内存的文档。
缺点:
1、需要应用程序自己负责TAG的处理逻辑(例如维护父/子关系等),使用麻烦。
2、单向导航,很难同时访问同一文档的不同部分数据,不支持XPath。
3)JDOM(Java-based Document Object Model)
Java特定的文档对象模型。自身不包含解析器,使用SAX。
优点:
1、使用具体类而不是接口,简化了DOM的API。
2、大量使用了Java集合类,方便了Java开发人员。
缺点:
1、没有较好的灵活性。
2、性能较差。
4)DOM4J(Document Object Model for Java)
简单易用,采用Java集合框架,并完全支持DOM、SAX和JAXP。
优点:
1、大量使用了Java集合类,方便Java开发人员,同时提供一些提高性能的替代方法。
2、支持XPath。
3、有很好的性能。
缺点:
1、大量使用了接口,API较为复杂。
下面把四种解析方式的代码贴一下,首先是DOM方式
public class DOMXml { public static void createXML(String outputPath) { // 建立Document对象 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 创建DocumentBuilder try { DocumentBuilder db = factory.newDocumentBuilder(); // 创建Document,建立新的对象 Document doc = db.newDocument(); // 建立各个节点 // 元素节点 Element allplus = doc.createElement("allplus"); Element areaplus = doc.createElement("areaplus"); Element id = doc.createElement("id"); Element title = doc.createElement("title"); // 创建文本节点 Text idText = doc.createTextNode("1"); Text titleText = doc.createTextNode("123"); // 配置父子节点的关系 id.appendChild(idText); title.appendChild(titleText); areaplus.appendChild(id); areaplus.appendChild(title); allplus.appendChild(areaplus); // allplus是根节点,应该设置为doc的子节点 doc.appendChild(allplus); // 执行保存操作 TransformerFactory tf = TransformerFactory.newInstance(); Transformer t = tf.newTransformer(); // 包装要保存的doc DOMSource source = new DOMSource(doc); // 设置输出流 StreamResult sr = new StreamResult(new File(outputPath)); // 设置输出的属性 t.setOutputProperty("encoding", "UTF-8"); // t.setOutputProperty("version", "1.0"); // 输出 t.transform(source, sr); } catch (DOMException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void parseXML(String xmlPath) { /*优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能; * 缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间; * 使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。 * 10M文档导致内存溢出 */ // 建立Document对象 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 创建DocumentBuilder try { DocumentBuilder db = factory.newDocumentBuilder(); // 创建Document,形成树型结构 Document doc = db.parse(new File(xmlPath)); // 先取得所有的data NodeList datas = doc.getElementsByTagName("data"); // 循环取得每个data for (int i = 0; i < datas.getLength(); i++) { Node data = datas.item(i); // 由于直接取得第一个和最后一个不符合要求,因此使用取得全部子节点的方式 NodeList actorInfos = data.getChildNodes(); for (int j = 0; j < actorInfos.getLength(); j++) { Node actorInfo = actorInfos.item(j); NodeList allChild = actorInfo.getChildNodes(); for (int t = 0; t < allChild.getLength(); t++) { //判断节点 Node child = allChild.item(t); if (child.getNodeType() == Node.ELEMENT_NODE) { if (child.getNodeName().equals("id")) { //判断是否有孩子节点,然后再取值 if(child.hasChildNodes()) { System.out.println(child.getFirstChild().getNodeValue()); } } if (child.getNodeName().equals("name")) { //判断是否有孩子节点,然后再取值 if(child.hasChildNodes()) { System.out.println(child.getFirstChild().getNodeValue()); } } } } } } } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { parseXML("D:/actor_info.xml"); createXML("d:/fxb.xml"); }
SAX解析方式
public class SAXXml extends DefaultHandler { private List<Book> books = null; private Book book = null; private String preTag = null;// 作用是记录解析时的上一个节点名称 public List<Book> getBooks(InputStream xmlStream) throws Exception { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); SAXXml handler = new SAXXml(); parser.parse(xmlStream, handler); return handler.getBooks(); } public List<Book> getBooks() { return books; } @Override public void startDocument() throws SAXException { books = new ArrayList<Book>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ("book".equals(qName)) { book = new Book(); book.setId(Integer.parseInt(attributes.getValue(0))); } preTag = qName;// 将正在解析的节点名称赋给preTag } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("book".equals(qName)) { books.add(book); book = null; } preTag = null; /** * 当解析结束时置为空。这里很重要,例如,当图中画3的位置结束后,会调用这个方法 * ,如果这里不把preTag置为null,根据startElement(....)方法,preTag的值还是book,当文档顺序读到图 * 中标记4的位置时,会执行characters(char[] ch, int start, int * length)这个方法,而characters(....)方 * 法判断preTag!=null,会执行if判断的代码,这样就会把空值赋值给book,这不是我们想要的。 */ } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (preTag != null) { String content = new String(ch, start, length); if ("name".equals(preTag)) { book.setName(content); } else if ("price".equals(preTag)) { book.setPrice(Float.parseFloat(content)); } } } public static void main(String args[]) { SAXXml handler = new SAXXml(); // 定义SUN自带解析对象 SAXParser parser; try { parser = SAXParserFactory.newInstance().newSAXParser(); parser.parse(new File("D:/book.xml"), handler); } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } List<Book> books = handler.getBooks(); for (Book book : books) { System.out.println(book.toString()); } }
JDOM解析方式
public class JDOMXml { public static void createXML(String outputPath) { // 先建立Document对象 Document doc = new Document(); // 建立元素节点 Element allplus = new Element("allplus"); try { // 建立多个Element Element areaplus = new Element("areaplus"); Element id = new Element("id"); Element title = new Element("title"); // 设置节点内容 id.addContent("id"); title.addContent("title"); // 设置父子节点关系 areaplus.addContent(id); areaplus.addContent(title); allplus.addContent(areaplus); // 设置根节点 doc.setRootElement(allplus); // 使用IO流操作 FileWriter writer = new FileWriter(new File(outputPath)); // 定义输出对象 XMLOutputter outputter = new XMLOutputter(); // 设置编码 outputter.setEncoding("UTF-8"); // 输出 outputter.output(doc, writer); writer.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void parseXML(String xmlPath) { /* * 10M文档导致内存溢出 */ //完成解析功能。 SAXBuilder builder = new SAXBuilder(); try { Document doc = builder.build(new File(xmlPath)); // 开始解析,取得根节点 Element data = doc.getRootElement(); // 取得所有的areaplus List<Element> actorInfos = data.getChildren("actor_info"); if(actorInfos != null && actorInfos.size()>0) { for(Element actorInfo:actorInfos) { Element id = actorInfo.getChild("id"); Element name = actorInfo.getChild("name"); System.out.println(id.getTextTrim() + " --- " + name.getTextTrim()); } } } catch (JDOMException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { parseXML("D:/actor_info.xml"); createXML("d:/fdfdsf.xml"); }
DOM4J解析方式
package com.fxb.test; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import java.util.Iterator; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; /** * * @author hongliang.dinghl Dom4j 生成XML文档与解析XML文档 */ public class DOM4JXml { public void createXml(String fileName) { Document document = DocumentHelper.createDocument(); Element employees = document.addElement("data"); Element employee = employees.addElement("actor_info"); Element id = employee.addElement("id"); id.setText("1"); Element name = employee.addElement("name"); name.setText("你好"); Element message = employee.addElement("message"); message.setText("你好吗"); Element pic = employee.addElement("pic"); pic.setText("123"); Element sex = employee.addElement("sex"); pic.setText("男"); Element birthday = employee.addElement("birthday"); pic.setText("19881212"); try { Writer fileWriter = new FileWriter(fileName); XMLWriter xmlWriter = new XMLWriter(fileWriter); xmlWriter.write(document); xmlWriter.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } public void parserXml(String fileName) { File inputXml = new File(fileName); SAXReader saxReader = new SAXReader(); try { Document document = saxReader.read(inputXml); Element data = document.getRootElement(); for (Iterator i = data.elementIterator(); i.hasNext();) { Element actorInfo = (Element) i.next(); //System.out.println(employee.getName() + "->" + employee.getText()); for (Iterator j = actorInfo.elementIterator(); j.hasNext();) { Element child = (Element) j.next(); System.out.println(child.getName() + ":" + child.getText()); } System.out.println("================="); } } catch (DocumentException e) { System.out.println(e.getMessage()); } } public static void main(String args[]) { DOM4JXml dom = new DOM4JXml(); //dom.parserXml("d:/actor_info.xml"); dom.createXml("d:/fxb.xml"); } }