XML的编程

来源:互联网 发布:笔记本外置光驱 知乎 编辑:程序博客网 时间:2024/06/05 10:34
XML的编程

1、DOM   Document Object Model文档对象模型。W3C推荐的解析方式。(一系列的接口和抽象类)

         Jaxp解析XML文档(dom解析方法,它是将整个xml文档加载到内存,对于xml文档的curd操作方便)

         属于JDK的一部分。由以下包构成

         org.w3c.dom:提供DOm方式解析的接口或抽象类

         org.xml.sax:提供SAX方式解析的接口或抽象类

         javax.xml:提供了解析XML的标准实现

Package com.test.japximport java.io.File;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.transform.Transformer;import javax.xml.transform.TransformerFactory;import javax.xml.transform.dom.DOMSource;import javax.xml.transform.stream.StreamResult;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;/** * jaxp解析xml文档 * @author yxx * */public class DomDemo {public static void main(String[] args)throws Exception {getAttr();}//1、得到某个具体的节点内容public static void getText() throws Exception{Document document = getDocument();NodeList list = document.getElementsByTagName("书架");Node no = list.item(0);System.out.println(no.getTextContent());}//2、遍历所有元素节点public static void list(Node node){if(node.getNodeType()==Node.ELEMENT_NODE){System.out.println(node.getNodeName());}NodeList nl = node.getChildNodes();for(int i=0;i<nl.getLength();i++){list(nl.item(i));}}//4、向指定元素节点中增加子元素节点public static void setNode() throws Exception{Document document = getDocument();Element d = (Element) document.getElementsByTagName("书").item(0);Element newEl = document.createElement("编号");newEl.setTextContent("sss");d.appendChild(newEl);write(document);}//6、删除指定元素节点public static void delNode() throws Exception{Document document = getDocument();Node node = document.getElementsByTagName("书名").item(0);//System.out.println(node.getNodeName());System.out.println(node.getParentNode());node.getParentNode().removeChild(node);write(document);}//7、操作XML文件属性public static void getAttr()throws Exception{Document document = getDocument();Node n = document.getElementsByTagName("书名").item(0);Element e = (Element)n;System.out.println(e.getAttribute("name"));}/** * *  返回document对象(公共方法,得到document对象) * @return * @throws Exception */public static Document getDocument() throws Exception{DocumentBuilderFactory factoy = DocumentBuilderFactory.newInstance();DocumentBuilder bui = factoy.newDocumentBuilder();Document document = bui.parse("src/book.xml");return document;}/** * 向xml文件中写入数据(公共方法,将修改的内容写入到xml文件中) * @param node * @throws Exception */public static void write(Document node) throws Exception{TransformerFactory factory = TransformerFactory.newInstance();Transformer tf = factory.newTransformer();tf.transform(new DOMSource(node),new StreamResult(new File("src/book.xml")) );}}

2、SAX:Simple APIfor XML。开源社区。非官方标准。(此方式不会讲整个xml文档整个加载到内存中,而只是边读取边操作,适合xml的读取,不适合对xml文档操作)

         1. Java Sax解析是按照xml文件的顺序一步一步的来解析,在解析xml文件之前,我们要先了解xml文件的节点的种类,一种是ElementNode,一种是TextNode。


<?xml version="1.0" encoding="UTF-8"?>  <books>      <book id="12">          <name>thinking in java</name>          <price>85.5</price>      </book>      <book id="15">          <name>Spring in Action</name>          <price>39.0</price>      </book>  </books>  

其中,像<books>、<book>这种节点就属于ElementNode,而thinking in java、85.5这种就属于TextNode。

下面结合一张图来详细讲解Sax解析。


xml文件被Sax解析器载入,由于Sax解析是按照xml文件的顺序来解析,当读入<?xml.....>时,会调用startDocument()方法,当读入<books>的时候,由于它是个ElementNode,所以会调用startElement(String uri, String localName, String qName, Attributes attributes) 方法,其中第二个参数就是节点的名称,注意:由于有些环境不一样,有时候第二个参数有可能为空,所以可以使用第三个参数,因此在解析前,先调用一下看哪个参数能用,第4个参数是这个节点的属性。这里我们不需要这个节点,所以从<book>这个节点开始,也就是图中1的位置,当读入时,调用startElement(....)方法,由于只有一个属性id,可以通过attributes.getValue(0)来得到,然后在图中标明2的地方会调用characters(char[] ch, int start, int length)方法,不要以为那里是空白,Sax解析器可不那么认为,Sax解析器会把它认为是一个TextNode。但是这个空白不是我们想要的数据,我们是想要<name>节点下的文本信息。这就要定义一个记录当上一节点的名称的TAG,在characters(.....)方法中,判断当前节点是不是name,是再取值,才能取到thinking in java。

来看一个具体的实例

import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.DefaultHandler;/** * 打印第2本书的作者的主体内容 * @author yxx * */public class SaxDemo2 {public static void main(String[] args)throws Exception {SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();XMLReader reader = saxParser.getXMLReader();reader.setContentHandler(new MyHandlers());reader.parse("src/book.xml");}}class MyHandlers extends DefaultHandler{//当前元素是否是作者元素 ,默认为falseboolean isAuthor = false;//当前的元素是否是第二个,默认为第一个int authorIndex = 0;@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {System.out.println(qName+"-----------------");if("作者".equals(qName)){isAuthor = true;}}@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {//当当前的元素为“作者”且是第二个的时候就打印里面的内容if(authorIndex==1&&isAuthor)System.out.println(new String(ch,start,length));}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {//当当前结束的标签为作者,就将元素authorIndex加1if("作者".equals(qName)){isAuthor = false;authorIndex++;}}}

2、Dom4j解析方法,集合了dom和sax两种解析方式的优点,在对xml读取的时候不会将整个xml文档加载到内存。三个xml文档共用

import java.io.FileOutputStream;import java.util.List;import org.dom4j.Document;import org.dom4j.DocumentHelper;import org.dom4j.Element;import org.dom4j.Node;import org.dom4j.io.OutputFormat;import org.dom4j.io.SAXReader;import org.dom4j.io.XMLWriter;import org.junit.Assert;import org.junit.Test;/** * dom4j练习   * 采用junit测试 * 1.junit测试的方法必须为public的, * 2.junit测试的方法不能有返回值, * 3.junit测试方法不能有参数 * @author yxx * */public class Dom4jDemo1 {//1、得到某个具体的节点内容:第1本书的作者@Testpublic void test1() throws Exception{SAXReader reader = new SAXReader();Document document = reader.read("src/book.xml");Element el =document.getRootElement();Element el1 = el.element("书");Element el2 = el1.element("作者");String name = el2.getText();Assert.assertEquals("张三", name);}//2、遍历所有元素节点@Test()public void test2() throws Exception{SAXReader reader = new SAXReader();Document document = reader.read("src/book.xml");Element el =document.getRootElement();treeWalk(el);}public void treeWalk(Element root){//得到根节点的所有孩子个数int count = root.nodeCount();//遍历孩子个数for(int i=0;i<count;i++){Node node = root.node(i);//如果node为Element元素,就将其转换为Element然后自调if(node.getNodeType()==Node.ELEMENT_NODE)treeWalk((Element)node);}}//3、修改某个元素节点的主体内容:第2本书售价改为5.1@Testpublic void test3() throws Exception{SAXReader reader = new SAXReader();Document document = reader.read("src/book.xml");Element el =document.getRootElement();//得到所有孩子节点,但不包括孙子节点List<Element> l = el.elements();Element e = l.get(1);Element e1 = e.element("售价");e1.setText("5.1");OutputFormat format = new OutputFormat();//用字节流 默认为UTF-8format.setEncoding("UTF-8");XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());writer.write(document);writer.close();}//4、向指定元素节点中增加子元素节点:第1本书增加内部价@Testpublic void test4() throws Exception{SAXReader reader = new SAXReader();Document document = reader.read("src/book.xml");Element el =document.getRootElement();Element e = el.element("书");e.addElement("内部价").setText("100.00");OutputFormat format = new OutputFormat();//用字节流 默认为UTF-8XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());wrier.write(document);wrier.close();}//5、向指定元素节点上增加同级元素节点:第1个售价前面加上批发价@Testpublic void test5() throws Exception{SAXReader reader = new SAXReader();Document document = reader.read("src/book.xml");Element el =document.getRootElement();//通过DocumentHelper来创建一个元素Element price = DocumentHelper.createElement("批发价");price.setText("100");List<Element> e = el.element("书").elements();e.add(2,price);OutputFormat format = new OutputFormat();//用字节流 默认为UTF-8XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());wrier.write(document);wrier.close();}//6、删除指定元素节点:批发价@Testpublic void test6() throws Exception{SAXReader reader = new SAXReader();Document document = reader.read("src/book.xml");Element el =document.getRootElement();Element el1 = el.element("书");Element el2 = el1.element("批发价");el2.getParent().remove(el2);OutputFormat format = new OutputFormat();//用字节流 默认为UTF-8XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());wrier.write(document);wrier.close();}//7、操作XML文件属性@Testpublic void test7() throws Exception{SAXReader reader = new SAXReader();Document document = reader.read("src/book.xml");Element el =document.getRootElement();Element el1 = el.element("书");el1.addAttribute("出版商", "清华出版社");OutputFormat format = new OutputFormat();//用字节流 默认为UTF-8XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());wrier.write(document);wrier.close();}//8、利用dom4j创建xml文档@Testpublic void test8()throws Exception{//DocumentHelper对象用于创建对象Document document = DocumentHelper.createDocument();// 向文档中添加元素Element el = document.addElement("school");//设置元素属性el.addAttribute("name", "清华大学");//添加子元素el.addElement("students").addAttribute("name", "李四");OutputFormat format = new OutputFormat();XMLWriter writer = new XMLWriter(new FileOutputStream("src/school.xml"),format.createPrettyPrint());writer.write(document);writer.close();}}

共用的xml文档:
<?xml version="1.0" encoding="UTF-8"?><书架>   <书>     <书名>JavaOOP</书名>      <作者>张三</作者>      <售价>5.00</售价>    </书>    <书>     <书名>JavaScript</书名>      <作者>李四</作者>      <售价>5.1</售价>   </书> </书架>