Java解析XML

Java解析XML
XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便. 
W3C定义了XML的语法以及XML的读写操作方法,任何计算机高级语言都可以实现对XML的读写操作, 本节将学习Java对XML的读写操作。
1. 两种解析方式
XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已。基本的解析方式有两种,一种是SAX(Simple API for XML),另一种是DOM(Document Object Model)。
 SAX: 用于XML处理的简单API
基于事件驱动的XML处理技术,使用SAX解析XML时,程序从XML文档的开头逐字逐句的读取,在此过程中激发事件(比如:文档开始,文档结束,元素开始,元素结束等事件),由应用程序对XML数据进行处理。例如,startElement()在每次SAX解析器遇到元素的起始标记时激发。endElement() 在元素的结束标记时激发。
 DOM:XML文档树结构的解析
DOM把XML文档中的元素、文本、属性视为节点,组成一种树结构,称为DOM树,通过DOM树可以访问所有的节点。也可以修改节点的内容,添加、删除节点等操作。W3C Dom是W3C推荐的用于解析的XML文件解析模型。W3C规定了DOM解析的接口和对象,用于对DOM进行标准操作。
两者的比较:
解析方法
优点
缺点
SAX
无需将整个文档加载到内存,减少内存消耗。
不能够随机访问XML文档。
不支持在原地修改XML。
不支持名字空间作用域。
DOM
丰富的API集合,可用于轻松地导航。
整棵树加载到内存,允许对XML文档进行随机访问。
整个XML文档必须一次解析完。
将整棵树加载到内存成本较高。
Java有丰富的组件提供对XML进行操作,常见的有4中操作方式:JAXP、JDOM、DOM4J、JAXB等。他们在不同的领域对XML进行方便操作。


1.1解析用的xml文档
为了演示各种操作的方式,需要准备一个xml文档
2. JAXP (Java API for XML Processing )
JAXP是使用JavaAPI对XML进行处理的一种规范,它提供接口来操作SAX和DOM。JAXP的API已经包含在JDK中,它包含了三个包:
org.w3c.dom:
W3C推荐的用于XML操作的标准文档对象模型的接口。
org.xml.sax:
用于对XML进行语法分析的事件驱动的XML简单API(SAX)
Javax.xml.parsers:
解析器工厂工具,程序员获得并配置特殊的语法分析器。
W3C DOM的常用对象及其方法有:
对象
说明
常用方法/属性
常用方法说明
Document
DOM最高层节点。
getDocumentElement
返回XML文档的根元素节点
Node
表示单一节点,包括XML中的元素、属性、文本等节点。
nodeName,nodeValue
返回节点的名称和值(属性)
parentNode,childNodes
返回父节点和子节点(属性)
firstChild,lastChild
返回第一个和最后一个子节点
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee id="1">
<name>张三</name>
<sex>女</sex>
<birthday>1981-04-16T00:00:00+08:00</birthday>
</employee>
<employee id="2">
<name>李四</name>
<sex>男</sex>
<birthday>1982-04-16T00:00:00+08:00</birthday>
</employee>
</employees>


appendChild(c)
在子节点结尾添加新节点。
Element
元素,Node子类。
getAttribute(n)
返回指定属性的值。
setAttribute(n,v)
设置指定属性的值。
Attr
属性,Node子类。
name,value
属性的名称和值(属性)
CharacterData
文本,Node子类。
——
——
NodeList
节点列表。
length
返回节点列表中的节点数。
item(index)
返回index位置的索引项。
下面开始解析上面的xml文档,新建一个java项目,不需要引入任何jar包,因为jdk中已经自带JAXP 的API
2.1加载XML文件
一般情况下我们将xml文件放到项目的src目录中,经过编译MyEclipse工具编译以后,放到了bin目录中,也就是程序运行的classpath路径中,从classpath路径下加载一个文件(不管是什么文件),可以使用Class类中的getResourceAsStream方法,这个方法返回一个InputStream文件流
2.2获得文档解析器工厂
2.3从工厂中获得解析器
public static void main(String[] args) {
//XML文件输入流
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
}
public static void main(String[] args) {
//XML文件输入流
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
//文档解析器构建工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
}
public static void main(String[] args) {
//XML文件输入流
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
//文档解析器构建工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//获取文档解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
}


2.4取得文档
注意:这里为了演示方便,没有处理异常
2.5获取根元素
2.6使用递算法归遍历根元素下所有的子元素
parseElement方法是遍历一个元素中的信息。
首先是元素的标记名称,这可以使用getNodeName方法来获取。接着获取属性,getAttributes()方法可以获取所有的属性,然后遍历每一个属性,显示属性的名称和值
接着考察该元素下所有的子元素,如果子元素只有一个并且节点类型是文本节点,判断方法为:
public static void main(String[] args) {
//XML文件输入流
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
//文档解析器构建工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//获取文档解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//获取文档,传入文档流
Document document=builder.parse(xmlInputStream);
}
public static void main(String[] args) {
//XML文件输入流
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
//文档解析器构建工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//获取文档解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//获取文档,传入文档流
Document document=builder.parse(xmlInputStream);
//取得根元素
Element root=document.getDocumentElement();
System.out.println("根元素名称:"+root.getNodeName());
}


nodeList.getLength()==1&&nodeList.item(0).getNodeType()==Node.TEXT_NODE),则显示文本信息,方法调用结束(return),否则取出元素中所有的子元素,递归调用该方法继续遍历元素中的信息。
①由于xml文件是格式化的,带有空格和回车换行符,JAXP把这些字符也解析为一个文本节点(CharacterData),此处在遍历XML文件的节点时,需要把Element元素检索出来。
2.7在main方法中调用递归
private static void parseElement(Element element){
System.out.println("元素名称:"+element.getNodeName());
NamedNodeMap namedNodeMap=element.getAttributes();
for(int i=0;i<namedNodeMap.getLength();i++){
Node item=namedNodeMap.item(i);
System.out.println("属性名:"+item.getNodeName()+":"+item.getTextContent());
}
//子元素
NodeList nodeList=element.getChildNodes();
//有一个子元素,而且是文本节点
if(nodeList.getLength()==1 && nodeList.item(0).getNodeType()==Node.TEXT_NODE){
System.out.println("文本节点:"+nodeList.item(0).getNodeValue());
return;
}
for(int i=0;i<nodeList.getLength();i++){
if(!(nodeList.item(i) instanceof Element)){ ①
continue;
}
parseElement((Element)nodeList.item(i));
}
}


输出结果:
public static void main(String[] args) {
//XML文件输入流
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
//文档解析器构建工厂
DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
//获取文档解析器
DocumentBuilder builder=builderFactory.newDocumentBuilder();
//获取文档,传入文档流
Document document=builder.parse(xmlInputStream);
//取得根元素
Element root=document.getDocumentElement();
System.out.println("根元素名称:"+root.getNodeName());
parseElement(root);
}
根元素名称:employees
元素名称:employees
元素名称:employee
属性名:id:1
元素名称:name
文本节点:张三
元素名称:sex
文本节点:女
元素名称:birthday
文本节点:1981-04-16T00:00:00+08:00
元素名称:employee
属性名:id:2
元素名称:name
文本节点:李四
元素名称:sex
文本节点:男
元素名称:birthday
文本节点:1982-04-16T00:00:00+08:00


2.8DOM元素的创建和修改
关于DOM元素的创建和修改方式与我们在javaScript DOM编程中使用的方式是一样的,这里不再演示
2.9 小结
JAXP是一个规范接口,任何符合JAXP接口的解析器都可以进行统一的XML解析,W3C没有定义DOM对象输出为XML文件。JAXP根据W3C规范而定义操作接口,利用JAXP对XML进行解析,不依赖任何第三方的Jar包,但是W3C定义的XML操作需要顾及各种语言的通用性,因此操作比较麻烦,同时org.w3c.dom包中的解析器也没有提供对DOM对象的输出。如果把DOM对象输出为XML文件,需要程序员根据IO流,定义方法进行输出,也可以借助其他的XML操作组件操作,比如JDOM组件。
3. JDOM操作XML
JDOM是一个开源项目,它基于树型结构,利用JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来,实现对XML文档解析、生成、序列化等多种操作
JDOM全称 java Document Object Model,java文档对象模型。它用于快速开发XML应用程序。JDOM为java程序员提供了一套简单易用的操作XML的API。
3.1下载JDOM
我们可以在http://www.jdom.org下载JDOM提供的jar包,这里下载的是JDOM1.1.1 版本
将解压后得到的build 目录下的jdom.jar加入到我们项目的classpath中就可以使用了
3.2 JDOM的主要类
JDOM的jar文件中的类主要集中在7个包中:
org.jdom
这个包中的类对应到XML文档中的各个组成部分。如 元素,属性,文本节点,注释等等。
org.jdom.input
这个包中的类表示读取XML文档的类


org.jdom.output
这个包中的类表示输出XML文档的类
org.jdom.adapters
包含了与dom适配的java类
org.jdom.filter
包含了xml文档的过滤器类
org.jdom.transform
包含了将jdom xml文档接口转换为其他xml文档接口
org.jdom.xpath
包含了对xml文档xpath操作的类
Document表示文档,Element表示元素,DocType 表示文档类型,Comment表示注释内容,ProcessingInstruction表示处理指令,Text表示文本节点,Atrribute表示属性
JDOM对XML解析时,省略了对元素之间的空格、TAB符、回车换行符等特殊文本的解析,使操作更加方便、快捷。
3.3创建解析器
在JDOM中可以使用SAX解析器对XML进行解析、也可以使用DOM解析器进行解析,解析的结果都会生成一棵节点树(Document对象),由JDOM进行维护,SAX解析器解析速度比DOM解析器快。由于JDOM生成的节点树与W3C的DOM无关,因此普遍使用SAX解析器对XML进行解析。


JDOM提供了SAXBuilder和DomBuilder,两个解析器。这里我们使用SAXBuilder
3.4获取Document对象
通过SaxBuilder的 builder方法获得一个Document对象,注意这个对象就是JDOM封装过的Document,注意要与W3C中规定的document的区别。
3.5获取根元素
3.6使用递归算法遍历
首先获取元素的名称,然后去的元素的属性。JDOM将元素的属性封装成了Attribute对象。
然后取得其孩子节点,如果没有孩子节点,而且元素文本内容不为空,则取出文本内容(在W3C DOM中被称为文本节点),如:<name>张三</name>像这样的元素JDOM认为没有孩子节点,而W3C DOM则认为有孩子节点,节点的类型为文本节点,这里我们需要加以区别。如果还有孩子几点,则遍历这些孩子节点,递归调用parseElement方法
public static void main(String[] args) throws JDOMException, IOException {
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
SAXBuilder builder=new SAXBuilder();//使用Sax解析器
}
public static void main(String[] args) throws JDOMException, IOException {
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
SAXBuilder builder=new SAXBuilder();//使用Sax解析器
Document document=builder.build(xmlInputStream);
}
public static void main(String[] args) throws JDOMException, IOException {
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
SAXBuilder builder=new SAXBuilder();//使用Sax解析器
Document document=builder.build(xmlInputStream);
//取得根元素
Element root=document.getRootElement();
}


3.6 在main方法中调用自定义方法:parseElement
3.7 增加元素
增加一个编号为3,姓名为王五,性别为女,生日为系统当前时间的元素,并保存到xml文档中。
注意:保存后的结果放在了 bin目录中,这里使用的Class类中的getResource方法,该方法的参数是一个文件在classpath中的路径,返回一个文件的URL,通过调用URL的getFile方法可以获取文件的完成的路径名,这个路径经过了URL编码,如果路径中带有中文字符,就需要进行URL解码。
private static void parseElement(Element element){
System.out.println("元素名称:"+element.getName());
//解析属性
List<Attribute> attributeList=element.getAttributes();
for (Attribute attribute : attributeList) {
System.out.println("属性:"+attribute.getName()+"-->"+attribute.getValue());
}
//取得孩子节点
List<Element> children=element.getChildren();
if(children.size()==0 && element.getText()!=null){
System.out.println(element.getText());
}else{
for (Element child : children) {
parseElement(child);
}
}
}
public static void main(String[] args) throws JDOMException, IOException {
InputStream xmlInputStream=Test1.class.getResourceAsStream("/employee.xml");
SAXBuilder builder=new SAXBuilder();//使用Sax解析器
Document document=builder.build(xmlInputStream);
//取得根元素
Element root=document.getRootElement();
parseElement(root);
}


4. XPath
XPath是一种在 XML 文档中查找信息的语言。XPath 可用来在XML文档中对元素和属性进行遍历。XPath是W3C XSLT标准的主要内容之一,它使用路径表达式在XML文档中进行导航。XPath含有丰富的内建函数,这些函数用于字符串、数值,日期和时间比较,节点和QName处理、序列处理、逻辑处理等。QName是指一个合法的XML元素,由命名空间(namespace)前缀(prefix)以及冒号(:)和一个元素名称构成。
4.1XPath术语
 节点(Node)
public static void main(String[] args) throws JDOMException, IOException {
InputStream xmlInputStream = Test2.class
.getResourceAsStream("/employee.xml");
SAXBuilder builder = new SAXBuilder();// 使用Sax解析器
Document document = builder.build(xmlInputStream);
xmlInputStream.close();
// 取得根元素
Element root = document.getRootElement();
Element element=new Element("employee");//创建元素
element.setAttribute("id","3");//添加元素
element.addContent(new Element("name").setText("王五"));
element.addContent(new Element("sex").setText("女"));
element.addContent(new Element("birthday").setText(new Date().toString()));
//将创建的元素添加到根上
root.addContent(element);
//创建输出器,参数是一个输出的格式
XMLOutputter xmlOutputter=new XMLOutputter(Format.getPrettyFormat());
//输出路径
String filePath=URLDecoder.decode(Test2.class.getResource("/employee.xml").getFile(),"UTF-8");
File xmlFile=new File(filePath);
xmlOutputter.output(document,new FileOutputStream(xmlFile));
}
进行URL解码。
这个xml文件最终保存在了bin目录中


在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。
 基本值(或称原子值,Atomic value)
无父节点(根节点)或者无子节点(叶子节点)的节点
 项目(Item)
节点和基本值的总称。
 父节点(parent)
每一个元素有一个父节点。
 子节点(children)
每一个元素有零个、1个或者多个子节点。
 兄弟节点(sibling)[`sibliŋ]
拥有相同父节点的节点。
 先辈(Ancestor)[`ænsistə]
 某节点的父节点,父节点的父节点……
 后代(Descendant)[di’sendənt]
某节点的子节点,子节点的子节点……
4.2路径表达式
XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path)来选取的。
表达式
描述
nodename
选取此节点的所有子节点


/
从根节点选取
//
从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
.
选取当前节点
..
选取当前节点的父节点
@
选取属性
以上面的xml文档为例,下面列出了表达式的意义
路径表达式
结果
employees
选取 employees元素的所有子节点
/ employees
选取根元素 employees
注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
employees /employee
选取所有属于 employees的子元素的 employee元素。
// employee
选取所有 employee子元素,而不管它们在文档中的位置。
employees// employee
选择所有属于 employees元素的后代的 employee元素,而不管它们位于 employees之下的什么位置。
//@id
选取所有名为id的属性。
4.3查找某个特定的节点或者包含某个指定的值的节点
谓语用来查找某个特定的节点或者包含某个指定的值的节点。谓语被嵌在方括号中。
下面是一些使用的例子:


 /employees/employee[1]
选取employees下的第一个employee元素
 /employees/employee[last()]
选取employees下的最后一个employee元素
 /employees/employee[last()-1]
选取employees下的倒数第二个employee元素
 /employees/employee[position()<3]
选取employees下的第1个和第2个employee元素
 //employee[@id]
选取所有拥有名为id的属性的employee元素。
 //employee [@id='2']
选取所有拥有名为id的属性,并且值为2的employee元素。
 /employees/employee[sex=’男’]
选取所有employee元素,并且其中的sex元素的值为‘男’
 /employees/employee[sex=’男’]/name
选取所有employee下的name元素,并且其中的sex元素的值为‘男’
4.5使用通配符
XPath中可以使用通配符:*、@*、node()等:
通配符
描述
*
匹配任何元素节点
@*
匹配任何属性节点
node()
匹配任何类型的节点
例子:
路径表达式
结果
/employees /*
选取 employees元素的所有子节点
//*
选取文档中的所有元素
//employee [@*]
选取所有带有属性的 employee元素。
4.6 选取多个路径
通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
路径表达式
结果
//book/title | //book/price
选取所有 book 元素的 title 和 price 元素。
//title | //price
选取所有文档中的 title 和 price 元素。
/bookstore/book/title | //price
选取所有属于 bookstore 元素的 book 元素的 title 元素,以及文档中所有的 price 元素。
4.7运算符
同时XPath还支持算术运算符(+、-、*、div、mod)、关系运算符(>、<、>=、<=、=、!=)和逻辑运算符(or、and)。
4.8 JDOM中的xpath对象
JDOM中提供了Xpath对象来封装xpath表达式,然后调用selectNodes方法,该方法需要传递一个Document对象,这样就可以在文档中选出我们想要的元素了。在下面的例子中,我们修改 “张三”的生日为当前时间.
思路:我们需要修改的是生日,也就是birthday元素,所以我们可以使用表达式:
/employees/employee[name=’张三’]/birthday表达式


注意,这段代码在运行的过程中,需要有jaxen.jar 的支持,否则会报如下异常. (jaxen.jar文件在JDOM发行包的lib目录中)
5. JAXB操作XML
读取XML对于应用软件来说是一个必不可少的工作,JDK为我们提供了很好的XML处理方式,读写XML的组件也有很多(比如:JDOM),但都是对XML的解析工具,需要手工调用get和set方法操作对象属性,不能直接绑定到Java对象。
JAXB(Java Architecture ([`ɑ:kitektʃə] ,体系结构,层次结构)for XML Binding) 是一个业界的标准,可以根据XML Schema产生Java对象,也可以把Java类中的Annotation与XML文件绑定,通过操作Java类,自动完成对XML的操作。
public static void main(String[] args) throws JDOMException, IOException {
InputStream xmlInputStream = Test3.class
.getResourceAsStream("/employee.xml");
SAXBuilder builder = new SAXBuilder();// 使用Sax解析器
Document document = builder.build(xmlInputStream);
xmlInputStream.close();
XPath xpath=XPath.newInstance("/employees/employee[name='张三']/birthday");
List<Element> list=xpath.selectNodes(document);
Element birthdayElement=list.get(0);
//System.out.println(birthdayElement.getTextTrim());
//修改为当前日期
birthdayElement.setText(new Date().toString());
// 创建输出器,参数是一个输出的格式
XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
// 输出路径
String filePath = URLDecoder.decode(Test3.class.getResource(
"/employee.xml").getFile(), "UTF-8");
File xmlFile = new File(filePath);
xmlOutputter.output(document, new FileOutputStream(xmlFile));
}
Exception in thread "main" java.lang.NoClassDefFoundError: org/jaxen/JaxenException
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at org.jdom.xpath.XPath.newInstance(XPath.java:134)


该过程中,JAXB提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象内存树的内容重新写到XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。
JDK6中,定义了很多的Annotation,可以直接使用这些Annotation来完成 xml文档与JavaBean 的“绑定”,所以我们需要掌握这些Annotation所代表的意义。
5.1 @XmlAccessorType
作用:指明如何绑定(修饰Class或者包)
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee id="1">
<name>张三</name>
<sex>女</sex>
<birthday>1981-04-16T00:00:00+08:00</birthday>
</employee>
<employee id="2">
<name>李四</name>
<sex>男</sex>
<birthday>1982-04-16T00:00:00+08:00</birthday>
</employee>
</employees>
XML文件
public class Employee {
private Integer id;
private String name;
private String sex;
private Date birthday;
//省略Getter Setter
}
public class Employees {
public Employees() {
}
private List<Employee> employee=
new ArrayList<Employee>();
//省略getter setter
}
JavaBean
JavaBean


JavaBean有Filed(字段),用来保存数据。Filed有对应的Getter/Setter方法,那么是将Filed绑定到XML中的元素呢还是Getter/Setter方法绑定到XML元素呢,使用JDK6中定义好的@ XmlAccessorType可以明确指定,它完整的类型名是:
javax.xml.bind.annotation.XmlAccessorType:
标记在JavaBean类上,控制默认情况下是否对字段或 Javabean 属性与XML进行绑定),该Annotation有一个值是一个枚举值,定义在javax.xml.bind.annotation. XmlAccessType中。
 XmlAccessType.PROPERTY
表示默认情况下对JavaBean的属性(getter/setter方法)自动绑定到XML上。
 XmlAccessType. FIELD
表示默认情况下对JavaBean的字段(不包括静态、瞬态字段)自动绑定到XML上。
5.2 @XmlType
作用:将类或枚举类型映射到 XML 模式类型(修饰Class)
我们知道,xml schema可以定义xml中的元素是简单类型还是复杂类型。
简单类型元素的意思是只包含文本而不包含任何其它元素或者属性,比如<name>张三</name>,或者<age>20</age>,或者<birthday>2005-5-5</birthday>就是简单元素类型。
复杂类型元素的意思是:包含其它元素或者属性的元素,如<product id=”123”/>或者
<employ>
<firstName>张</firstName>
<lastName>三</lastName>
</employ>
javax.xml.bind.annotation.XmlType,它指明了将类或枚举类型映射到XML的Schema类型,如果是复杂类型还可以规定JavaBean的属性或字段映射到XML中元素出现的先后顺序。
使用方法是:
@XmlType(name = "Schema类型名称", propOrder = {
XML中元素的顺序
})


当缺省“XML中元素的顺序”时,则XML中元素顺序为无序。
@XmlType(name = "", propOrder = {})
要被映射,类必须拥有一个不带参数的公共构造方法,或者一个静态的不带参数的工厂方法。使用静态不带参数的工厂方法构造该JavaBean时,使用方法是:
@XmlType(name = "Schema类型名称", propOrder = {
XML中元素的顺序
},factoryClass=工厂类,factoryMethod="工厂方法名")
5.3 @XmlRootElement
作用:指定根元素(修饰Class)
如果要映射的JavaBean对象是xml文件中的根元素,则使用它,全称是
javax.xml.bind.annotation.XmlRootElement
5.4 @XmlElement
作用:指定类中的Filed或者属性到XML元素的映射(修饰Filed或者getter/setter方法)将JavaBean属性或者字段映射到XML 元素。这里的字段必须非static、非transient字段。
使用方法是:
@XmlElement(name="标记名称" required=true|false)
缺省name时,属性或者字段名将视为XML的标记名称。
5.5 @XmlAttribute
作用是:指定Filed或者属性到XML元素属性的映射(修饰Filed或者getter/setter方法)全称是:javax.xml.bind.annotation.XmlAttribute
将JavaBean属性或者字段映射到XML属性。如果字段或属性的类型是集合类型,则必须将集合项类型映射到基本类型。如果字段或属性的类型是非集合类型,则必须将属性或字段的类型映射到基本类型。Java的8种基本类型以及String类型、Date类型及他们的集合映射给XML时,不需要转换,称为简单类型。使用方法是:
@XmlAttribute(required = true|false,name="属性名")
缺省name时,属性或者字段名将视为XML的标记属性名称。
5.6 @XmlTransient
吴老师教学讲义 21
http://shop34513748.taobao.com/ Copyright©2010 吴青版权所有
作用:指明不需要做映射的字段或者属性(修饰Field或者Getter/Setter方法)
全称是:javax.xml.bind.annotation.XmlTransient
阻止将 JavaBean 属性或字段映射到 XML 表示形式。@XmlTransient注释可以解决 JavaBean 属性名称和字段名称之间的名称冲突,或者用于防止字段/属性的映射。
5.7 @XmlJavaTypeAdapter
作用:完成自定义映射(修饰Field或者Getter/Setter方法)
使用自定义编程完成XML与JavaBean的映射,需要实现 XmlAdapter 的适配器,经常作用在JavaBean的属性和字段中。
5.8@XmlSchemaType
作用 :将 Java 类型映射到一个简单的模式内置类型(修饰Field或者Getter/Setter方法)
常用简单类型有:
 xs:string
 xs:decimal
 xs:integer
 xs:boolean
 xs:date
 xs:time
 xs: dateTime
5.9实战
利用JAXB的Annotation完成XML文件与JavaBean及其字段、属性的映射绑定后,就可以对JavaBean进行操作,JAXB自动完成与XML的同步工作。
定义Employee类:
Employees类,该类映射xml文档的根元素
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "employeeType", propOrder = { "name", "sex", "birthday" })
public class Employee {
@XmlAttribute(name="id",required=true)
private Integer id;
@XmlElement(required=true)
private String name;
@XmlElement(required=true)
private String sex;
@XmlElement(required=true)
@XmlSchemaType(name="date")
private Date birthday;
//省略Getter Setter方法
public String toString(){
return "id:"+id+" name:"+name+" sex:"+sex+" birthday:"+birthday.toString();
}
}
使用字段绑定
映射为复杂元素,子元素出现的顺序
id为必须属性
Schema内置类型
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="employeesType",propOrder={"employee"})
@XmlRootElement(name="employees")
public class Employees {
public Employees() {
}
@XmlElement(required=true)
private List<Employee> employee=new ArrayList<Employee>();
public List<Employee> getEmployee() {
return employee;
}
public void setEmp(List<Employee> employee) {
this.employee = employee;
}
public void addEmployy(Employee employee){
this.employee.add(employee);
}
}




编写main方法测试:
获取JAXB上下文,用于对JAXB环境进行初始化。JAXBContext 类提供了 JAXB API 的客户端入口点。它提供了管理实现 JAXB 绑定操作所需的 XML/Java 绑定信息的抽象,这些操作包括:解组(unmarshal)、编组(marshal [`ma:ʃəl] 整理,编排)和验证(validate)。
1. 解组可以使客户端应用程序利用Unmarshaller 类将XML数据转换为Java对象。
2. 编组使客户端应用程序利用Marshaller 类将Java对象转换回 XML 数据。
JAXBContext的newInstance方法可以传入包名(String类型),也可以传入类名(Class类型)。
 JAXBContext.newInstance( "包名1:包名2" )
JAXBContext 实例根据冒号分隔的 Java 包名称的列表进行初始化。每个java包都包含 JAXB 映射类、用户注释类等。
 JAXBContext.newInstance( Class… cls )
JAXBContext 实例使用作为参数传递的类以及可从这些类静态获得的类来实现初始化。
添加一个元素,然后保存:
public static void main(String[] args) throws JAXBException {
JAXBContext context=JAXBContext.newInstance(Employees.class);
Unmarshaller unmarshaller=context.createUnmarshaller();
Employees employees=(Employees)
unmarshaller.unmarshal(Test.class.getResource("/employee.xml"));
for (Employee emp :employees.getEmployee()) {
System.out.println(emp);
}
}
5.10自定义映射
如果要为Employee再添加一个爱好属性,对应的元素是<favorite >音乐,足球,书法</favorite>,此时的xml文件为:
public static void main(String[] args) throws JAXBException, UnsupportedEncodingException {
JAXBContext context = JAXBContext.newInstance(Employees.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Employees employees = (Employees) unmarshaller.unmarshal(Test2.class.getResource("/employee.xml"));
Employee employee=new Employee();
employee.setId(3);
employee.setName("王五");
employee.setSex("男");
employee.setBirthday(new Date());
employees.addEmployy(employee);
// 输出路径
String filePath = URLDecoder.decode(Test2.class.getResource(
"/employee.xml").getFile(), "UTF-8");
File xmlFile = new File(filePath);
Marshaller marshaller=context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING,"UTF-8");
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
marshaller.marshal(employees,xmlFile);
}
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee id="1">
<name>张三</name>
<sex>女</sex>
<birthday>1981-04-16T00:00:00+08:00</birthday>
<favorite>音乐,足球,书法</favorite>
</employee>
<employee id="2">
<name>李四</name>
<sex>男</sex>
<birthday>1982-04-16T00:00:00+08:00</birthday>
<favorite>K歌,音乐,游戏</favorite>
</employee>
</employees>


对应的java类为:
FavoriteAdapter是一个自定义的元素转换器,它必须继承XmlAdapter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "employeeType", propOrder = { "name", "sex", "birthday",“favorite” })
public class Employee {
@XmlAttribute(name="id",required=true)
private Integer id;
@XmlElement(required=true)
private String name;
@XmlElement(required=true)
private String sex;
@XmlElement(required=true)
@XmlSchemaType(name="date")
private Date birthday;
@XmlJavaTypeAdapter(FavoriteAdapter.class)
private List<String> favorite=new ArrayList<String>();
//省略getter setter和构造方法
public String toString(){
return "id:"+id+" name:"+name+" sex:"+sex+" birthday:"+birthday.toString();
}
}
public class FavoriteAdapter extends XmlAdapter<String,List<String>> {
@Override
public String marshal(List<String> v) throws Exception {
StringBuilder sb=new StringBuilder();
for (int i = 0; i <(v==null?0:v.size()); i++) {
sb.append(v.get(i));
if(i<v.size()-1){
sb.append(',');
}
}
return sb.toString();
}
@Override
public List<String> unmarshal(String v) throws Exception {
return v==null?new ArrayList<String>():Arrays.asList(v.split(","));
}
}
自定义元素转换器
自定义元素顺序


6. 总结
 目前有两种流行的XML解析技术,即SAX和DOM。
 JAXP是使用JavaAPI对XML进行处理的一种方法,
它提供接口来使用SAX和DOM,可以使用任何与JAXP兼容的XML解析器对XML进行操作。
 JDOM使用Java语言自身特性维护一棵XML节点树。
并且提供了节点树的XML输出功能。
 XPath是一门在 XML 文档中查找信息的语言。
XPath 可用来在 XML 文档中对元素和属性进行遍历。
 JAXB是一个业界的标准,可以根据XML Schema产生Java对象
,也可以把Java对象中的Annotation与XML文件绑定
,通过操作Java对象,自动完成对XML的操作。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值