通过Java解析xml文档 柔情只为你懂 2022-05-18 03:19 146阅读 0赞 # 一、xml解析方式概叙 # ## 1、解析方法 ## XML解析方式分为两种:dom和sax dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式。 sax: (Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。 ## 2、解析器 ## Crimson、Xerces 、Aelfred2 ## 3、解析开发包 ## Jaxp、Jdom、dom4j ## 4、解析方法比较 ## ### 1.dom方法 ### 优点:使用dom解析xml文档,实现crud特别方便,操作速度也比较快。 缺点:使用dom解析xml文档,如果文件比较大,对内存消耗就特别大,极容易导致内存溢出,所以dom方式不适合操作大的xml文档。 ### 2.sax方法 ### 优点:解析速度快、对内存占用少,查找数据特别方便 缺点:只适合查找数据,不适合作增删改操作 # 二、使用jaxp解析 # ## 1、dom方法解析 ## ### 1、方法介绍 ### javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象 , DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法 ,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。 ### 2、解析对象 ### book.xml <?xml version="1.0" encoding="utf-8" standalone="no"?> <书架> <书 name="yyyyyyy"> <售价>109</售价> <售价>39元</售价> <书名>Java就业培训教程</书名> <作者>张孝祥</作者> </书> <书> <书名>JavaScript网页开发</书名> <作者>张孝祥</作者> <售价>28.00元</售价> </书> </书架> ### 3、运用详情 ### package jaxp; import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class Demo { /** * 使用jaxp操作xml文档 * @param args * @throws ParserConfigurationException * @throws IOException * @throws SAXException */ public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { //1.获取工厂 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //2.产生解析器 DocumentBuilder builder = factory.newDocumentBuilder(); //3.解析xml文档,得到代表文档的document Document document = builder.parse(new File("src/book.xml")); //遍历 list(document); } //遍历,得到所有标签 public static void list(Node node){ //判断得到的结点是否为标签 if(node.getNodeType()==Node.ELEMENT_NODE){ System.out.println(node.getNodeName()); } //进行遍历 NodeList list = node.getChildNodes(); for(int i=0;i<list.getLength();i++){ Node child = list.item(i); list(child); } } //------------------------对结点进行操作 //得到售价结点的值 @Test public void read() throws Exception{ //1.获取工厂 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new File("src/book.xml")); //2.得到第一个售价节点 NodeList list = document.getElementsByTagName("售价"); Node price = list.item(0); //3.得到该结点的值 String value = price.getTextContent(); System.out.println(value); } //修改结点的值:<售价>39.00元</售价>改为109 @Test public void update() throws Exception{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new File("src/book.xml")); Node price = document.getElementsByTagName("售价").item(0); price.setTextContent("109"); //把内存中的document写到xml文档 TransformerFactory tf = TransformerFactory.newInstance(); //得到转换器 Transformer ts = tf.newTransformer(); ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml"))); } //向指定节点中增加孩子节点(售价节点) @Test public void add() throws Exception{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new File("src/book.xml")); //创建需要增加的节点 Node price = document.createElement("售价"); price.setTextContent("59元"); //得到需要增加的节点的父亲 Node parent = document.getElementsByTagName("书").item(0); //把需要增加的节点挂到父结点上 parent.appendChild(price); TransformerFactory tf = TransformerFactory.newInstance(); Transformer ts = tf.newTransformer(); ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml"))); } //向指定位置上插入售价节点 @Test public void add2() throws Exception{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new File("src/book.xml")); //新建要插入的结点 Node node = document.createElement("售价"); node.setTextContent("39元"); Node parent = document.getElementsByTagName("书").item(0);//获取要插入的父节点 parent.insertBefore(node, document.getElementsByTagName("书名").item(0));//在该节点的前边插入 TransformerFactory tf = TransformerFactory.newInstance(); Transformer ts = tf.newTransformer(); ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml"))); } //删除xml文档的售价结点 @Test public void delete() throws Exception{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new File("src/book.xml")); Node node = document.getElementsByTagName("售价").item(2); node.getParentNode().removeChild(node); TransformerFactory tf = TransformerFactory.newInstance(); Transformer ts = tf.newTransformer(); ts.transform(new DOMSource(document), new StreamResult(new File("src/book1.xml"))); } //--------------------------该标签属性 //操作xml文档属性 @Test public void updateAttribute() throws Exception{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(new File("src/book.xml")); //操作xml文档的元素时,一般都把元素当作node对象,但是程序员如果发现node不好使时,就应把node强转成相应类型 Node node = document.getElementsByTagName("书").item(0); Element book = null; if(node.getNodeType()==Node.ELEMENT_NODE){ //在作结点转换之前,最好先判断结点类型 book = (Element)node; } //修改 book.setAttribute("name", "yyyyyyy"); //增加 book.setAttribute("password", "123"); //删除 book.removeAttribute("password"); TransformerFactory tf = TransformerFactory.newInstance(); Transformer ts = tf.newTransformer(); ts.transform(new DOMSource(document), new StreamResult(new File("src/book.xml"))); } } ### 4、案例解析 ### **资料** <?xml version="1.0" encoding="UTF-8" standalone="no"?> <exam> <student idcard="111" examid="222"> <name>张三</name> <location>沈阳</location> <grade>89</grade> </student> <student idcard="333" examid="444"> <name>李四</name> <location>大连</location> <grade>97</grade> </student> </exam> **要求** 1.需求分析 ![70][] 2.详细设计 添加用户: ![70 1][] 删除用户: ![70 2][] 查询成绩: ![70 3][] 3.程序实现 javaben:student.java public class Student { /* <student idcard="111" examid="222"> <name>张三</name> <location>沈阳</location> <grade>89</grade> </student> */ private String idcard; private String examid; private String name; private String location; private double grade; } 工具类:Utils.java import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.xml.sax.SAXException; public class XmlUtils { /** * 工具类中的方法一般都是静态方法 * @return * @throws ParserConfigurationException * @throws SAXException * @throws IOException */ //得到document public static Document getDocument() throws ParserConfigurationException, SAXException, IOException{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); return builder.parse(new File("src/exam.xml")); } //将结果写入到xml文件 public static void write2Xml(Document document) throws TransformerException{ TransformerFactory factory = TransformerFactory.newInstance(); Transformer tf = factory.newTransformer(); tf.transform(new DOMSource(document), new StreamResult(new File("src/exam.xml"))); } } 持久化操作:StudentsDao.java import java.io.IOException; import javax.management.RuntimeErrorException; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.shen.mode.Student; import com.shen.utils.XmlUtils; public class StudentsDao { /* <student idcard="111" examid="222"> <name>张三</name> <location>沈阳</location> <grade>89</grade> </student> */ public void add(Student student){ try{ Document document = XmlUtils.getDocument(); //student_node //ctrl+1 rename in file Element student_node = document.createElement("student"); student_node.setAttribute("examid", student.getExamid()); student_node.setAttribute("idcard", student.getIdcard()); Element name = document.createElement("name"); name.setTextContent(student.getName()); Element location = document.createElement("location"); location.setTextContent(student.getLocation()); Element grade = document.createElement("grade"); grade.setTextContent(student.getGrade()+""); student_node.appendChild(name); student_node.appendChild(location); student_node.appendChild(grade); //得到exam结点,并把student挂上去 document.getElementsByTagName("exam").item(0).appendChild(student_node); XmlUtils.write2Xml(document); }catch (Exception e) { throw new RuntimeException(e); } } public void delete(String name){ try { Document document=XmlUtils.getDocument(); NodeList list=document.getElementsByTagName("name"); for(int i=0;i<list.getLength();i++) { Node node=list.item(i); if(node.getTextContent().equals(name)){ node.getParentNode().getParentNode().removeChild(node.getParentNode()); XmlUtils.write2Xml(document); return; } } throw new RuntimeException("对不起,你要删除的学生不存在");//异常也是一个返回值 } catch (Exception e) { throw new RuntimeException(e); } } public Student find(String examid){ try{ Document document=XmlUtils.getDocument(); NodeList list=document.getElementsByTagName("student"); for (int i = 0; i < list.getLength(); i++) { Element student=(Element)list.item(i); String s_examid=student.getAttribute(examid); if(s_examid.equals(examid)) { //找到 Student s=new Student(); s.setExamid(student.getAttribute("examid")); s.setExamid(student.getAttribute("idcard")); s.setName(student.getElementsByTagName("name").item(0).getTextContent()); s.setLocation(student.getElementsByTagName("location").item(0).getTextContent()); s.setGrade(Double.parseDouble(student.getElementsByTagName("garde").item(0).getTextContent())); return s; } } return null; }catch(Exception e){} return null; } } 主方法:Main.java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import com.shen.dao.StudentsDao; import com.shen.mode.Student; public class Main { public static void main(String[] args) throws IOException { System.out.println("添加学生 (a) 查找学生(b) 删除学生(c)"); System.out.print("请输入操作类型:"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String type = br.readLine(); if (type.equalsIgnoreCase("a")) { // 添加学生 try { System.out.print("请输入学生姓名:"); String name = br.readLine(); System.out.print("请输入学生准考证号:"); String examid = br.readLine(); System.out.print("请输入学生身份证号:"); String idcard = br.readLine(); System.out.print("请输入学生所在地:"); String location = br.readLine(); System.out.print("请输入学生成绩:"); String grade = br.readLine(); Student student = new Student(); student.setExamid(examid); student.setGrade(Double.parseDouble(grade)); student.setIdcard(idcard); student.setLocation(location); student.setName(name); StudentsDao dao = new StudentsDao(); dao.add(student); System.out.println("恭喜,录入成功!!!"); } catch (Exception e) { System.out.println("对不起,录入失败!!"); } } else if (type.equalsIgnoreCase("b")) { // 查找学生 System.out.println("请输入学生的准考证号:"); String examid=br.readLine(); StudentsDao dao=new StudentsDao(); Student student=dao.find(examid); if(student==null){ System.out.println("对不起,你要查找的学生不存在!!!"); }else{ System.out.println("你要查找的学生信息如下:"); System.out.println("姓名:"+student.getName()); System.out.println("身份证:"+student.getIdcard()); System.out.println("准考证:"+student.getExamid()); System.out.println("所在地:"+student.getLocation()); System.out.println("成绩"+student.getGrade()); } } else if (type.equalsIgnoreCase("c")) { // 删除学生 try{ System.out.println("请输入要删除学生的姓名:"); String name=br.readLine(); StudentsDao dao=new StudentsDao(); dao.delete(name); System.out.println("删除成功"); }catch(Exception e){System.out.println("删除失败");} } else { System.out.println("不支持此类操作!!!"); } } } ## 2、sax方法解析 ## ### 1、方法介绍 ### 在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。 ### 2、解析对象 ### book.xml <?xml version="1.0" encoding="utf-8" standalone="no"?> <书架> <书 name="yyyyyyy"> <售价>109</售价> <售价>39元</售价> <书名>Java就业培训教程</书名> <作者>张孝祥</作者> </书> <书> <书名>JavaScript网页开发</书名> <作者>张孝祥</作者> <售价>28.00元</售价> </书> </书架> ### 3、运用详情 ### import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; public class Demo1 { /** *sax方式解析book1.xml文件 * @throws SAXException * @throws ParserConfigurationException * @throws IOException */ public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { //1.创建工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //2.用工厂创建解析器 SAXParser sp = factory.newSAXParser(); //3.利用解析器得到reader XMLReader reader = sp.getXMLReader(); //4、在解析xml文档之前,设置好事件处理器 reader.setContentHandler(new MyContentHandler2()); //4.利用reader读取 xml文档 reader.parse("src/book1.xml"); } } //用于获取第一个售价节点的值:<售价>109</售价> class MyContentHandler2 extends DefaultHandler{ private boolean isOk = false; private int index = 1; @Override public void characters(char[] ch, int start, int length) throws SAXException { if(isOk==true && index==1){ System.out.println(new String(ch,start,length)); } } @Override public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { if(name.equals("售价")){ isOk = true; } } @Override public void endElement(String uri, String localName, String name) throws SAXException { if(name.equals("售价")){ isOk = false; index++; } } } //得到xml文档内容的事件处理器 class MyContentHandler implements ContentHandler{ //开始标签(Attributes表示属性) public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException { System.out.println("当前解析到了:" + name + ",这个标签是开始标签"); for(int i=0;i<atts.getLength();i++){ String attname = atts.getQName(i); String attvalue = atts.getValue(i); //打印出各个属性 System.out.println(attname + "=" + attvalue); } } public void endElement(String uri, String localName, String name) throws SAXException { System.out.println("当前解析到了:" + name + ",这个标签是结束标签"); } public void characters(char[] ch, int start, int length) throws SAXException { System.out.println("当前解析到了内容:" + new String(ch,start,length)); } public void endDocument() throws SAXException { // TODO Auto-generated method stub } public void endPrefixMapping(String prefix) throws SAXException { // TODO Auto-generated method stub } public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { // TODO Auto-generated method stub } public void processingInstruction(String target, String data) throws SAXException { // TODO Auto-generated method stub } public void setDocumentLocator(Locator locator) { // TODO Auto-generated method stub } public void skippedEntity(String name) throws SAXException { // TODO Auto-generated method stub } public void startDocument() throws SAXException { // TODO Auto-generated method stub } public void startPrefixMapping(String prefix, String uri) throws SAXException { // TODO Auto-generated method stub } } # 三、使用dom4j解析 # 注意:使用dom4j解析需要自己引入jar包,引入该包可能不够 ## 1、解析对象 ## book.xml <?xml version="1.0" encoding="utf-8" standalone="no"?> <书架> <书 name="yyyyyyy"> <售价>109</售价> <售价>39元</售价> <书名>Java就业培训教程</书名> <作者>张孝祥</作者> </书> <书> <书名>JavaScript网页开发</书名> <作者>张孝祥</作者> <售价>28.00元</售价> </书> </书架> ## 2、实现代码 ## public class Main { //读取xml文档数据:<书名>Java就业培训教程</书名> @Test public void read() throws Exception{ SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/book.xml")); Element root = document.getRootElement(); Element bookname = root.element("书").element("书名"); System.out.println(bookname.getText()); } //<书 name="yyyyyyy"> @Test public void readAttr() throws Exception{ SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/book.xml")); Element root = document.getRootElement(); String value = root.element("书").attributeValue("name"); System.out.println(value); } //向xml文档中添加<售价>19元</售价> @Test public void add() throws Exception{ SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/book.xml")); Element price = DocumentHelper.createElement("售价"); price.setText("19元"); document.getRootElement().element("书").add(price); OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format); writer.write(document); //utf-8 writer.close(); } //修改:<售价>109</售价> 为209 @Test public void update() throws Exception{ SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/book1.xml")); Element price = (Element) document.getRootElement().element("书").elements("售价").get(1); price.setText("209元"); OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format); writer.write(document); //utf-8 writer.close(); } //删除:<售价>109</售价> @Test public void delete() throws Exception{ SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/book.xml")); Element price = (Element) document.getRootElement().element("书").elements("售价").get(0); price.getParent().remove(price); OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format); writer.write(document); //utf-8 writer.close(); } //向指定位置增加售价结点 @Test public void add2() throws Exception{ SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/book.xml")); Element price = DocumentHelper.createElement("售价"); price.setText("19元"); List list = document.getRootElement().element("书").elements(); list.add(1, price); //格式化输出(保持原来的样式) OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format); writer.write(document); //utf-8 writer.close(); } } ## 3、使用xpath技术实现查找 ## ### 1.代码示例 ### import java.io.File; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.junit.Test; public class Mais { @Test public void findWithXpath() throws Exception{ SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/book.xml")); Element e = (Element) document.selectNodes("//书名").get(1); System.out.println(e.getText()); } } ### 2.运用举例 ### 通过匹配用户信息进行登陆 users.xml <?xml version="1.0" encoding="UTF-8"?> <users> <user username="aaa" password="123"/> <user username="bbb" password="123"/> <user username="ccc" password="123"/> </users> login.java @Test public void findUser() throws Exception{ String username = "aaa"; String password = "1233"; SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/users.xml")); //single单一的 Element e = (Element) document.selectSingleNode("//user[@username='"+username+"' and @password='"+password+"']"); if(e!=null){ System.out.println("让用户登陆成功!!"); }else{ System.out.println("用户名和密码不正确!!"); } } [70]: /images/20220518/d77630796fab42dc96966937f3e0b16e.png [70 1]: /images/20220518/0e3cfc68280f47cd9939a88c0f828f1d.png [70 2]: /images/20220518/1eb1ca200c8646adbf36ee84921870ff.png [70 3]: /images/20220518/570284540dff466c89c18dbdedb069f8.png
还没有评论,来说两句吧...