XML的编程

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.japx
import 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{

	//当前元素是否是作者元素 ,默认为false
	boolean isAuthor = false;
	//当前的元素是否是第二个,默认为第一个
	int authorIndex = 0;
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		System.out.println(qName+"-----------------");
		if("作者".equals(qName)){
			isAuthor = true;
		}
	}
	
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		//当当前的元素为“作者”且是第二个的时候就打印里面的内容
		if(authorIndex==1&&isAuthor)
			System.out.println(new String(ch,start,length));
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		//当当前结束的标签为作者,就将元素authorIndex加1
		if("作者".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本书的作者
	@Test
	public 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
	@Test
	public 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-8
		format.setEncoding("UTF-8");
		XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
		writer.write(document);
		writer.close();
	}
	
	//	4、向指定元素节点中增加子元素节点:第1本书增加内部价
	@Test
	public 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-8
		XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
		wrier.write(document);
		wrier.close();
		
	}
	
	//	5、向指定元素节点上增加同级元素节点:第1个售价前面加上批发价
	@Test
	public 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-8
		XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
		wrier.write(document);
		wrier.close();
	}
	
//	6、删除指定元素节点:批发价
	@Test
	public 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-8
		XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
		wrier.write(document);
		wrier.close();
	}
	
	
//	7、操作XML文件属性
	@Test
	public 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-8
		XMLWriter wrier = new XMLWriter(new FileOutputStream("src/book.xml"),format.createPrettyPrint());
		wrier.write(document);
		wrier.close();
	}
	
	
	//8、利用dom4j创建xml文档
	@Test
	public 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</售价> 
  </书> 
</书架>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值