java里如何正确使用XML文件

本文详细介绍了在Java中如何正确使用XML文件,包括XML的结构、DTD和Schema的区别及使用,以及DOM、SAX、JDOM和DOM4J等解析XML的方法,并通过实例展示了XPath技术在获取XML节点中的应用。

什么是xml

xml是可扩展标记语言,简单理解,就是可预定义标签的编程语言。虽然和html类似,但主要是用于数据存储和传输数据;HTML用于显示数据。

XMl的结构:

<root>         <!-- 根结点-->
  <child> 			<!-- 子结点-->
    <subchild>		<!-- 根节点的孙子结点,子节点的子节点-->
        .....
    </subchild>
  </child>
  <child>   <!-- 上一个child的兄弟结点-->
    <subchild>
        .....
    </subchild>
  </child>  
</root>

XML的结构一定含有根节点/根元素,这个节点为所有节点的父节点

语法详解

  • XML以<?xml version="1.0" encoding="ISO-8859-1"?>开头,这句话用于定义XML的版本和所采用的字符集。
  • 标签以成对的方式出现,如:
  • XML的大小写敏感
  • 因为<>被用于当做语法标签的符号,所以文本的内容的< 号就失效了,所以我们使用 ;&lt 来表示小于号,使用;&gt表示大于号 ;&quto表示双引号
  • 使用 < !-- 注释内容 – >

示例:

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE books [
	<!ELEMENT books (book*)>
	<!ELEMENT book (name,author,price)>
	<!ELEMENT name (#PCDATA)>
	<!ELEMENT author (#PCDATA)>
	<!ELEMENT price (#PCDATA)>
	<!ATTLIST book id CDATA #REQUIRED>
]>
<books>
	<book id="1001">
		<name>java开发实战</name>
		<author>张小三</author>
		<price>98.5</price>
	
	</book>
	<book id="1002">
		<name>mysql从删库到跑路</name>
		<author>王一一</author>
		<price>89.7</price>
		
	</book>
</books>

找到这个xml文件,显示这样的形式就是没有问题的
在这里插入图片描述
案例解析
我们使用DTD验证去避免XML文件给出报错提示,去验证XML的有效性

 <!DOCTYPE books [
	<!ELEMENT books (book*)>
	<!ELEMENT book (name,author,price)>
	<!ELEMENT name (#PCDATA)>
	<!ELEMENT author (#PCDATA)>
	<!ELEMENT price (#PCDATA)>
	<!ATTLIST book id CDATA #REQUIRED>
]> 

PCDATA(Parsed Character DATA)的意思是:被解析的字符数据
CDATA(Unparsed Character Data)意思是:不应由 XML 解析器进行解析的文本数据

DTD的局限性

  • 不遵守XML语法
  • DTD数据类型有限
  • DTD不可以扩展
  • DTD不支持命名空间

DTD的代替技术 – Schema

Schema全称为XML Schema,用于描述XML文档结构,比DTD更加强大,最关键的特征就是,Schema支持数据类型
Schema特点

  • 是用于支持XML验证
  • 可以使用处理XML文档的工具进行操作
  • 扩充了数据类型,可以自定义数据类型
  • 支持元素的继承
  • 支持属性组

格式

<?xml version="1.0" encoding="UTF-8"?>
	<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
	
	</xs:schema>

注意要点

  • 所有的Schema文档使用schema作为根元素
  • http://www.w3.org/2001/XMLSchema:用于验证当前 Schema 文档的命名空间(用于验证 Schema 本身)
    同时它还规定了来 自命名空间http://www.w3.org/2001/XMLSchema的元素和数 据类型应该使用前缀 xs:
  • xmlns 相当于 java 中的 import, :xs“小名”,在使用时要写加 “小名”做前缀

使用Schema去验证XML文档的流程:

  1. 创建Schemafactory工厂
  2. 建立验证文件对象
  3. 利用SchemaFactory工厂对象,接收验证的文件对象,生成Schema对象
  4. 产生对此schema的验证器
  5. 要验证的数据
  6. 开始验证

示例代码

创建一个xsd文件,存放Schema

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
	<xs:element name="books">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="book" maxOccurs="unbounded">
					<xs:complexType>
						<xs:sequence>
							<xs:element name="name" type="xs:string"></xs:element>
							<xs:element name="author" type="xs:string"></xs:element>
							<xs:element name="price" type="xs:double"></xs:element>
						</xs:sequence>
						<xs:attribute name="id" type="xs:positiveInteger" use="required"></xs:attribute>
					</xs:complexType>
				</xs:element>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
</xs:schema>

在XML文件内引用xsd文件

<?xml version="1.0" encoding="UTF-8"?>

<books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="{book.xsd}">
	<book id="1001">
		<name>java开发实战</name>
		<author>张三</author>
		<price>98.5</price>
	</book>
	<book id="1002">
		<name>mysql开发</name>
		<author>李四</author>
		<price>89.7</price>
	</book>
</books>

对验证器进行验证

package com.bjsxt.schema;

import java.io.File;
import java.io.IOException;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.xml.sax.SAXException;

public class Test {
	public static void main(String[] args) throws SAXException {
		//创建SchemaFactory工厂
		SchemaFactory sch = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
		//建立验证文件对象
		File schemaFile = new File("book.xsd");
		//利用SchemaFactory工厂对象,接收验证的文件对象,生成Schema对象
		Schema schema = sch.newSchema(schemaFile);
		//产生对此schema的验证器
		Validator validator = schema.newValidator();
		//要验证的数据(准备数据源)
		Source source = new StreamSource("book.xml");
		//开始验证
		try {
			validator.validate(source);
			System.out.println("成功");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println("验证失败");
		}
	}
}

项目格式:
在这里插入图片描述
运行成功,也就是说,我们使用Schema对XML文件进行验证是可以的
在这里插入图片描述

使用DOM解析XML数据

DOM解析就是将其转换为一个对象模型的集合,用树这种数据结构对信息进行存储。

创建流程

  1. 创建一个DocumentBuilderFactory的对象
  2. 创建一个DocumentBuilder对象
  3. 通过DocumentBuilder的parse(…)方法得到Document对象
  4. 通过getElementsByTagName(…)方法获取到节点的列表
  5. 通过for循环遍历每一个节点
  6. 得到每个节点的属性和属性值
  7. 得到每个节点的节点名和节点值

创建项目:

在这里插入图片描述
XML文件

<?xml version="1.0" encoding="UTF-8"?>

<books>
	<book id="1001">
		<name>java开发实战</name>
		<author>张三</author>
		<price>98.5</price>
	</book>
	<book id="1002">
		<name>my开发</name>
		<author>李四</author>
		<price>89.7</price>
	</book>
</books>

创建DOM文件对XML文件进行验证:

package com.bjsxt.schema;

import java.io.IOException;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; 
import org.xml.sax.SAXException;

public class TestDOMParse {
	public static void main(String[]args) throws ParserConfigurationException, SAXException, IOException{
//		1. 创建一个DocumentBuilderFactory的对象
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//		2. 创建一个DocumentBuilder对象
		DocumentBuilder db = dbf.newDocumentBuilder();
//		3. 通过DocumentBuilder的parse(...)方法得到Document对象
		Document doc = db.parse("book.xml");
//		4. 通过getElementsByTagName(...)方法获取到节点的列表
		NodeList bookList = doc.getElementsByTagName("book");
		System.out.println("节点个数:"+bookList.getLength());
//		5. 通过for循环遍历每一个节点
		for(int i=0;i<bookList.getLength();i++) { 
//			6. 得到每个节点的属性和属性值
			Node book = bookList.item(i);
			NamedNodeMap attrs = book.getAttributes(); //得到了属性的集合
			//使用循环遍历每一个属性
			for(int j=0;j<attrs.getLength();j++) {
				//得到每一个属性
				Node id = attrs.item(j);
				System.out.println("属性的名称:"+id.getNodeName()+"\t"+id.getNodeValue());
			}
		}
		System.out.println("\n每个节点的名和节点的值");
//		7. 得到每个节点的节点名和节点值
		for(int i=0;i<bookList.getLength();i++) {
			//得到每个book节点
			Node book = bookList.item(i);
			NodeList subNode = book.getChildNodes();
			System.out.println("子节点的个数:"+subNode.getLength());
			for(int j=0;j<subNode.getLength();j++) {
				Node childNode = subNode.item(i);
				//System.out.println(childNode.getNodeName());
				short type = childNode.getNodeType();	//获取节点的类型
				if(type==Node.ELEMENT_NODE) {
					System.out.println("节点的名称:"+childNode.getNodeName()+"\t"+childNode.getTextContent());
				}
				
			}
		}
	}
}

验证结果:

在这里插入图片描述

使用SAX方式解析XML数据

SAX,是一种以事件驱动的XML API,SAX和DOMM不同的是它边扫描边解析,自顶向下以此解析,由于边扫描边解析,所以它解析XML速度快,占用内存少

创建流程

  1. 创建SAXParserFactory的对象
  2. 创建SAXParser对象(解析器)
  3. 创建一个DefaultHandler的子类
  4. 调用parse方法

示例:

项目结构:
在这里插入图片描述
book.xml

<?xml version="1.0" encoding="UTF-8"?>

<books>
	<book id="1001">
		<name>java开发实战</name>
		<author>张三</author>
		<price>98.5</price>
	</book>
	<book id="1002">
		<name>my开发</name>
		<author>李四</author>
		<price>89.7</price>
	</book>
</books>

TestSAXparse.java

package com.bjsxt.schema;

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class TestSAXparse {
	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
		//1.创建SAXParserFactory的对象 
		SAXParserFactory spf = SAXParserFactory.newInstance();
//		2. 创建SAXParser对象(解析器)
		SAXParser parser = spf.newSAXParser();
//		3. 创建一个DefaultHandler的子类
		BookDeaultHandler bdh = new BookDeaultHandler();
//		4. 调用parse方法
		parser.parse("book.xml",bdh);
		
	}
}

BookDeaultHandler .java

package com.bjsxt.schema;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class BookDeaultHandler extends DefaultHandler{
	//重写第一个方法
	/** 
	   *    解析XML文档,开始时调用
	 */
	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.startDocument();
		System.out.println("解析XML文档开始");
	}
	/**
	 * 解析XML文档,点击结束时调用
	 */
	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.endDocument();
		System.out.println("解析XML文档结束");
	}
	/**
	 * 解析XML文档中的节点开始时要用
	 */
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		// TODO Auto-generated method stub
		super.startElement(uri, localName, qName, attributes);
		//判断book节点,我们就获取节点的属性和属性值
		if("book".equals(qName)) {
			//获取所有的属性
			int count = attributes.getLength();//属性的个数
			//循环获取每个属性
			for(int i=0;i<count;i++) {
				String attName = attributes.getQName(i);	//属性名称
				String attValue = attributes.getValue(i);	//属性值
				System.out.print("属性名称:"+attName+"\t属性值:"+attValue+"\t");
			}
		}else if(!"book".equals(qName)&&!"book".equals(qName)) {
			System.out.print("节点的名称:"+qName+"\t");
		}
	}
	/**
	 * 解析XML文档内的节点结束时要用
	 */
	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName); 
	}
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		// TODO Auto-generated method stub
		super.characters(ch, start, length);
		String value = new String(ch,start,length);
		if("".equals(value.trim())) {
			System.out.print(value);
		}
	}
}

运行结果 :
在这里插入图片描述

使用JDOM解析XML

JDOM是一种解析XML的java工具包,它基于树型结构,利用纯java的技术对XML文档实现解析。所以是适用于java语言

创建流程

  1. 导入jdom.jar这个jar包
  2. 创建一个SAXBuilder对象
  3. 创建build方法,得到Document对象(通过IO流)
  4. 获取根节点
  5. 获取根节点的直接子节点的集合
  6. 遍历集合

示例:

项目结构:
在这里插入图片描述
导入jar包:这里导入的是 jdom.jar包

book.xml 内容同上

TestJDOM.java

package com.bjsxt.schema;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

public class TestJDOM {
	public static void main(String[] args) throws FileNotFoundException, JDOMException, IOException {
//		1. 创建一个SAXBuilder对象
		SAXBuilder sb = new SAXBuilder();
//		2. 创建build方法,得到Document对象(通过IO流)
		Document doc = sb.build(new FileInputStream("book.xml"));
//		3. 获取根节点
		Element root = doc.getRootElement();	//books元素
//		4. 获取根节点的直接子节点的集合
		List<Element> bookEle = root.getChildren();
//		5. 遍历集合 得到book的每一个子节点(子元素)
		for(int i=0;i<bookEle.size();i++) {
			Element book = bookEle.get(i);
			//得到属性集合
			List<Attribute> attList = book.getAttributes();
			//遍历属性的集合得到每一个属性 
			for(Attribute attr:attList) {
				System.out.println(attr.getName()+"\t"+attr.getValue());
			}
		}
		//得到每一个子节点
		System.out.println("\n-------------");
		for(int i=0;i<bookEle.size();i++) {
			Element book = bookEle.get(i);	//得到每一个book节点
			List<Element> subBook = book.getChildren();
			//遍历每一个节点,获取节点名称节点值
			for(Element ele:subBook) {
				System.out.println(ele.getName()+"\t"+ele.getValue());
			}
			System.out.println("=================");
		}
	}
}

运行结果:
在这里插入图片描述

使用DOM4J去解析XML(目前使用最多的一种)

DOM4J是一个java的XML API,是JDOM的升级品,是用来读写XML文件的

DOM4J解析XML的步骤

  1. 创建SAXReader对象
  2. 调用read方法
  3. 获取根元素
  4. 通过迭代器遍历直接节点

示例

项目目录:
在这里插入图片描述

导入jar包:这里导入的是dom4j-1.6.1.jar包

创建Book.java实体类

package com.bjsxt.entity;

public class Book {
	//私有属性
		private String name;
		private String author;
		private double price;
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getAuthor() {
			return author;
		}
		public void setAuthor(String author) {
			this.author = author;
		}
		public double getPrice() {
			return price;
		}
		public void setPrice(double price) {
			this.price = price;
		}
		public Book(String name, String author, double price) {
			super();
			this.name = name;
			this.author = author;
			this.price = price;
		}
		public Book() {
			super();
		}
		
	}

创建TestDOM4J.java

package com.bjsxt.schema;


import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.bjsxt.entity.Book;

public class TestDOM4J {
public static void main(String[] args) throws DocumentException {
//	1. 创建SAXReader对象
	SAXReader reader=new SAXReader();
//	2. 调用read方法
	Document doc=reader.read(new File("book.xml"));
//	3. 获取根元素
	Element root=doc.getRootElement();//books
//	4. 通过迭代器遍历直接节点
	for(Iterator<Element> iteBook=root.elementIterator();iteBook.hasNext();){
		Element bookEle=iteBook.next();
		//得到book的属性
		for(Iterator<Attribute> iteAtt=bookEle.attributeIterator();iteAtt.hasNext();){
			Attribute att=iteAtt.next();
			System.out.println(att.getName()+"\t"+att.getText());
		}
	}
	System.out.println("\n----------------------"); 
	List<Book> bookList=new ArrayList<Book>();
	for(Iterator<Element> iteBook =root.elementIterator();iteBook.hasNext();){
		//创建book对象
		Book book = new Book();
		 //得到每一个子元素
		Element bookEle = iteBook.next();	//得到每一个book
		//使用for循环继续遍历
		for(Iterator<Element> subBookEle=bookEle.elementIterator();subBookEle.hasNext();){
			//得到每一个元素
			Element subEle = subBookEle.next();
			System.out.println(subEle.getName()+"\t"+subEle.getText());
			/**
			 * 封装为book对象
			 */
			//获取节点的名称
			String nodeName=subEle.getName();//name,author,price
			//使用switch判断
			switch (nodeName) {
			case "name":
				book.setName(subEle.getText());
				break;
			case "author":
				book.setAuthor(subEle.getText());
				break;
			case "price":
				book.setPrice(Double.parseDouble(subEle.getText()));
				break;
		  }	
		}
		//添加到集合中
		bookList.add(book);
	}
	//遍历集合
	System.out.println("\n遍历集合-----------------------\n");
	for (Book b : bookList) {
		System.out.println(b.getName()+"\t"+b.getAuthor()+"\t"+b.getPrice());
	}
  }
}

去解析book.xml文件
运行结果:
在这里插入图片描述

使用XPATH技术去快速获取节点

引入原因

使用dom4j去查询较深的节点时,比较麻烦

作用

快速获取所需的节点对象

如何在dom4j内使用xPath技术

  1. 导入对应的jar包 : dom4j的jar包 Jaxen的jar包
  2. 创建一个SAXReader对象
  3. 读取读取XML文件
  4. 得到author节点

示例:

在这里插入图片描述
Test.java

package com.bjsxt.xpath;

import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

public class Test {
	public static void main(String[] args) throws DocumentException {
		//1. SAXReader对象
		SAXReader reader = new SAXReader();
		//2. 读取XML文件
		Document doc = reader.read("book.xml");
		//3. 得到第一个author节点
		Node node = doc.selectSingleNode("//author");
		System.out.println("节点的名称:"+node.getName()+"\t"+node.getText());
		System.out.println("-------------------");
		//获取所有的author
		List<Node> list = doc.selectNodes("//author");
		for(Node n:list) {
			System.out.println("节点的名称:"+n.getName()+"\t"+n.getText());
		}
		//选择有id属性的book元素
		List<Attribute> attList = doc.selectNodes("//book/@id");
		for(Attribute att:attList) {
			System.out.println("属性的名称:"+att.getName()+"\t"+att.getText());
		}
	}
}

运行结果
在这里插入图片描述
最后一种,最为方便

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值