本文共 11704 字,大约阅读时间需要 39 分钟。
Java解析XML
本文介绍了使用JAXP和DOM4J解析java的方法.
编辑者:洋葱
引用来源 转载请注明所有引用地址.一.XML解析方式
1.DOM解析DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过 对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM 接口的机制也被称作随机访问机制。
DOM接口提供了一种通过分层对象模型来访问XML文档信息的方式,这些分层对象模型依据XML的文档 结构形成了一棵节点树。无论XML文档中所描述的是什么类型的信息,即便是制表数据、项目列表或一个文档,利用DOM所生成的模型都是节点树的形式。也就 是说,DOM强制使用树模型来访问XML文档中的信息。由于XML本质上就是一种分层结构,所以这种描述方法是相当有效的。
DOM树所提 供的随机访问方式给应用程序的开发带来了很大的灵活性,它可以任意地控制整个XML文档中的内容。然而,由于DOM分析器把整个XML文档转化成DOM树 放在了内存中,因此,当文档比较大或者结构比较复杂时,对内存的需求就比较高。而且,对于结构复杂的树的遍历也是一项耗时的操作。所以,DOM分析器对机 器性能的要求比较高,实现效率不十分理想。不过,由于DOM分析器所采用的树结构的思想与XML文档的结构相吻合,同时鉴于随机访问所带来的方便,因 此,DOM分析器还是有很广泛的使用价值的。
2.SAX 解析
SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对 XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件 驱动接口。
二.使用JAXP解析XML
/**1.DOM生成和解析XML文档为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构。优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。 对XML文档的操作1.获取/添加/修改/删除节点值2.获取/设置/修改/删除属性值3.层次遍历节点树*/public class DomDemo implements XmlDocument { public static void main(String[] args){ String fileName="book.xml"; DomDemo dom=new DomDemo(); dom.parserXml(fileName); dom.init(); dom.createXml("book.out.xml"); } //文档对象 private Document document; /** 创建一个空的文档对象 */ public void init() { try { //构建一个工厂 DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); //新建一个实例 DocumentBuilder builder = factory.newDocumentBuilder(); //获取文档对象 this.document = builder.newDocument(); } catch (ParserConfigurationException e) { System.out.println(e.getMessage()); } } /** 创建一个XML文件 */ public void createXml(String fileName) { //创建一个元素,并作为根节点 Element root = this.document.createElement("books"); this.document.appendChild(root); //创建一个节点 Element book = this.document.createElement("book"); //创建一个子节点,并设置子节点的文本内容 Element bookName = this.document.createElement("书名"); bookName.appendChild(this.document.createTextNode("Java编程思想第4版")); book.appendChild(bookName); Element price = this.document.createElement("定价"); //设置属性 price.setAttribute("单位", "元"); price.appendChild(this.document.createTextNode("108.00")); book.appendChild(price); //如上 Element author = this.document.createElement("作者"); author.setAttribute("性别", "男"); author.appendChild(this.document.createTextNode("Bruce Eckel")); book.appendChild(author); //如上 Element isbnNo = this.document.createElement("ISBN编号"); isbnNo.appendChild(this.document.createTextNode("9787111213826")); book.appendChild(isbnNo); root.appendChild(book); //保存 save(document,fileName, "gbk"); } /** 从文件解析XML文档 */ public void parserXml(String fileName) { try { // 创建工厂,构建示例,加载文件,获取文档树对象 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse(fileName); // 获取所有直接子节点 NodeList books = document.getChildNodes(); // 遍历,第一层 for (int i = 0; i < books.getLength(); i++) { Node book = books.item(i); System.out.println(book.getNodeName()); NodeList bookInfo = book.getChildNodes(); // 遍历,第二层 for (int j = 0; j < bookInfo.getLength(); j++) { Node node = bookInfo.item(j); System.out.println("\t"+node.getNodeName()); NodeList bookMeta = node.getChildNodes(); // 遍历,第三层 for (int k = 0; k < bookMeta.getLength(); k++) { System.out.print("\t\tnode>>" + bookMeta.item(k).getNodeName() + ":" + bookMeta.item(k).getTextContent()); // 输出示例 书名:Java编程思想第4版 /** * 获取属性,而且可以设置属性 */ NamedNodeMap map = bookMeta.item(k).getAttributes(); if (map != null) { for (int l = 0; l < map.getLength(); l++) { Node att = map.item(l); System.out.println(" "+att.getNodeName() + "=" + att.getTextContent()); //设置属性 att.setTextContent("changed"); } } } } } /** * 通过输出结果我们可以发现,JAVA使用DOM解析时, <标签> 与 <标签> 之间也是节点 */ System.out.println("解析完毕"); //将修改的结果保存 save(document,fileName, "gbk"); } catch (FileNotFoundException e) { System.out.println(e.getMessage()); } catch (ParserConfigurationException e) { System.out.println(e.getMessage()); } catch (SAXException e) { System.out.println(e.getMessage()); } catch (IOException e) { System.out.println(e.getMessage()); } } public void save(Document document, String fileName, String encoding) {// System.out.println("encoding="+document.getXmlEncoding()); // 实例化转换器工厂 TransformerFactory tf = TransformerFactory.newInstance(); try { // 实例一个转换器 Transformer transformer = tf.newTransformer(); // 构建一个文档源 DOMSource source = new DOMSource(document); // 设置字符编码 transformer.setOutputProperty(OutputKeys.ENCODING, encoding); // 设置缩排 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); PrintWriter pw = new PrintWriter(new FileOutputStream(fileName)); StreamResult result = new StreamResult(pw); // 通过转换器将文档树源写入文件 transformer.transform(source, result); System.out.println("XML文件保存成功!"); } catch (TransformerConfigurationException e) { System.out.println(e.getMessage()); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); } catch (FileNotFoundException e) { System.out.println(e.getMessage()); } catch (TransformerException e) { System.out.println(e.getMessage()); } }} // 标签> 标签>
/**2.SAX生成和解析XML文档为解决DOM的问题,出现了SAX。SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。优点: 不用事先调入整个文档,占用资源少; SAX解析器代码比DOM解析器代码小,适于Applet,下载。缺点: 不是持久的;事件过后,若没保存数据,那么数据就丢了; 无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少; */public class SaxDemo implements XmlDocument { public static void main(String[] args){ SaxDemo demo=new SaxDemo(); String fileName="book.out.xml"; demo.parserXml(fileName); } public void createXml(String fileName) { System.out.println("<<"+fileName+">>"); } //解析 public void parserXml(String fileName) { //实例化一个工厂 SAXParserFactory saxfac = SAXParserFactory.newInstance(); try { //实例化一个解析器 SAXParser saxparser = saxfac.newSAXParser(); InputStream is = new FileInputStream(fileName); //使用MySAXHandler处理文档 saxparser.parse(is, new MySAXHandler()); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public void save(Document document, String fileName, String encoding) { // TODO Auto-generated method stub } } class MySAXHandler extends DefaultHandler { boolean hasAttribute = false; Attributes attributes = null; //解析开始事件 public void startDocument() throws SAXException { System.out.println("文档解析开始"); } //解析结束事件 public void endDocument() throws SAXException { System.out.println("文档解析结束"); } //解析到一个元素的起始标签 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { System.out.println("elementStart> "+qName); if (attributes.getLength() > 0) { this.attributes = attributes; this.hasAttribute = true; } } //解析到一个元素的结束标签 public void endElement(String uri, String localName, String qName) throws SAXException { //打印属性 if (hasAttribute && (attributes != null)) { for (int i = 0; i < attributes.getLength(); i++) { System.out.println("attr> "+attributes.getQName(0)+"="+ attributes.getValue(0)); } } System.out.println(qName+">elementEnd"); } //解析到元素内容 public void characters(char[] ch, int start, int length) throws SAXException { //输出内容 System.out.println("content> "+new String(ch, start, length)); } }
三.使用Dom4j 解析XML
百度百科上有大量的说明,这里写一个很小的应用
/*** * 使用Dom4j操作XML文档. * 操作列表: * 加载,解析,读取,添加,修改,保存. */public class Dom4jInstance { public static void main(String[] args) throws DocumentException, IOException { String outFile="Dom4jDemo.xml"; Dom4jInstance ins=new Dom4jInstance(); ins.load(outFile); ins.iterator(); ins.addNode(); ins.save(outFile); } private Document doc=null; //1.从文件加载XML文档 public void load(String fileName) throws DocumentException{ File file=new File(fileName); if(!file.exists()){ System.out.println("文件不存在!"); return ; } SAXReader reader = new SAXReader(); doc= reader.read(file); System.out.println("加载成功!"); } //2.遍历xml public void iterator(){ doc.accept(new MyVisitor()); } private class MyVisitor extends VisitorSupport { //访问元素 public void visit(Element element) { System.out.println("\t"+element.getName()); } //访问属性 public void visit(Attribute attr) { System.out.print("\t"+attr.getName()+"="+attr.getValue()+" "); } //访问元素内值 public void visit(Text node) { System.out.println("\t\t"+node.getText()); } } //3.使用XPath获取某个元素 public void update(String xpath){ Listlist=doc.selectNodes(xpath); for(Node node : list){ System.out.println(node.getName()+"="+node.getText()); } } //4.添加一个节点并设置属性 public void addNode(){ List list=doc.selectNodes("//books/book"); for(Node n : list){ Element e=(Element)n; e.addElement("出版社").addAttribute("地址", "北京").setText("清华大学出版社"); } } //5.选择编码格式并保存到文件 public void save(String outFile) throws IOException{ XMLWriter writer; // 美化格式 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding(doc.getXMLEncoding()); writer = new XMLWriter(new FileOutputStream(outFile), format ); System.out.println("已写入文件"+outFile); writer.write(doc); }}