文章目录
一、XML文件概述
1、XML文件
(1)介绍
- 可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。XML 的设计宗旨是传输数据,而不是显示数据。
- XML文件可以直接使用解析器解析(IE浏览器)。
(2)作用
- 用于存放数据
- 用于配置文件
(3)基本语法
① 文档声明
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
- 文档声明必须以<?xml开头,以?>结束,中间没有空格,? 表示开始或者结束;
- 文档声明必须从文档的0行0列位置开始;
- xml 表示文件是xml格式,文件后缀是.xml;
- 文档声明只有两个属性,格式:属性名=“属性值”,属性值必须使用"";
- version 指定XML文档版本。必须属性,目前只有1.0版本;
- encoding 表示指定当前文档的编码。可选属性,默认值为UTF-8;
- standlone 表示文件是否独立,yes表示是,no表示不是。
2、XML 文件示例
<?xml version="1.0" encoding="utf-8" ?>
<中国>
<重庆>
<江北>江北</江北>
<渝北>渝北</渝北>
</重庆>
<四川>
<成都>成都</成都>
<南充>南充</南充>
</四川>
</中国>
② 元素(Element)和标签(Tag)
- 以尖括号括起来的就是元素(和html一致,但所有的标签名可以自定义)
- 元素体可以写也可以不写
- 元素体里面可以是文本也可以写其他标签
- 元素命名:
区分大小写
不能使用空格,冒号第特殊字符
不建议以XML、xml、Xml开头 - 格式化良好的xml文档,必须只有一个根元素
③ 属性(attribute):
- 属性是元素的一部分,写在开始标签的尖括号里面,并且多个属性用空格隔开
- 属性的定义格式:属性名=“属性值”,其中属性值必须使用单引号或双引号
- 一个元素可以有0-N个属性,但一个元素中不能出现同名属性
- 属性名不能使用空格、冒号等特殊字符,且必须以字母开头
④ 注释
<!-- 注释内容 -- >
⑤ CDATA区
- 原始数据,将所有的内容都作为原始数据。
- 语法:
<![CDATA][需要转译的字符]>
⑥ 转义字符:
< | < | 小于 |
---|---|---|
> | > | 大于 |
& | & | 和 |
' | ’ | 单引号 |
" | " | 双引号 |
⑦ 指令:引入标签 xml-stylesheet
如:在一个xml中引入css文件:
<?xml-stylesheet type="text/css" href="css文件名.css" ?>
二、XML文件的约束
1、约束概述
(1)介绍
- 按照一定的规则编写xml文件,指定位置只能存放固定的标签。
(2)DTD 约束
<!ELEMENT 根标签名 (数据类型或者子标签,如果标签名是相同的(标签+))>
<!ELEMENT 父标签名 (子标签名不同的情况下,直接列举,中间用逗号隔开)>
<!ELEMENT 子标签名 (#PCDATA)>
引入DTD约束:
<!DOCTYPE 根标签名 SYSYTEM "引入的文件">
(3)三种DTD约束
- 内部DTD,在XML文档内部嵌入DTD,只对当前XML有效
- 外部DTD-本地DTD,DTD文档在本地系统上,公司内部自己项目使用
- 外部DTD-公共DTD,DTD文档在网络上,一般由框架提供
2、DTD 约束示例
xml文件导入约束
① xml文件
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<!DOCTYPE 信息 SYSTEM "users.dtd">
<信息>
<用户>
<姓名>张三</姓名>
<性别>男</性别>
<年龄>12</年龄>
</用户>
<用户1>
<姓名>李四</姓名>
<性别>女</性别>
<年龄>23</年龄>
</用户1>
</信息>
② dtd 约束文件
<!ELEMENT 信息 (用户+)>
<!ELEMENT 用户 (姓名,性别,年龄)>
<!ELEMENT 姓名 (#PCDATA)>
<!ELEMENT 性别 (#PCDATA)>
<!ELEMENT 年龄 (#PCDATA)>
IE浏览器默认关闭了校验文件,需要使用脚本文件将其打开:
- 创建IE浏览器中的ActiveXObject对象,使用其对象中的控件(Microsoft.XMLDOM);
- 设置validateOnParse变量的值为false;
- 读取要校验的xml文件:load(“xml文件”)。
<html>
<head>
<script>
var xmldom = new ActiveXObject("Microsoft.XMLDOM");
xmldom.validateOnParse = true;
xmldom.load("users.xml");
//输出错误原因和行数
document.write(xmldom.parseError.reason+"<br />");
document.write(xmldom.parseError.line);
</script>
</head>
<body>
</body>
</html>
三、XML文件的解析
1、XML文件解析概述
(1)介绍
在java中提供了三种解析xml文件的开发包: JAXP
Jdom
dom4j
,后面两个其实可以合成一个。
2、DOM 解析
(1)介绍
- DOM解析方式属于JAXP开发包:
DocumentBuilderFactory
抽象类 - DOM解析首先将一个xml文件中的内容全部解析到内存中,然后在内存中构建Document树。
- 标签解析为Element,属性解析为 attr,内容解析为 text,但不管是属性或者是标签或者是文本内容都会解析为Node节点。
(2)优缺点
优点:元素与元素之间保留结构关系,可以进行增删改查操作,其查询比较快;
缺点:占用内存,XML文档过大时,可能出现内存溢出现象;
(3)DOM 解析过程:
① 创建解析xml文件的工厂:DocumentBuilderFactory
对象;
② 根据获取的工厂得到解析xml文档的解析器:DocumentBuilder
对象;
③ 获取解析器,真正开始解析xml文件:使用对象调用parse方法解析xml文档。
DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("文件路径"));
④ 解析节点属性名、节点属性值
对于节点个数未知
获取所有节点的集合
Nodelist klist = document.getElementByTagName("节点");
使用for循环通过item()方法遍历每个节点
Node node= list.item(i);
并获取节点的所有属性集合
NameNodeMap attrs = node.getAttribute();
使用for循环通过item()方法遍历节点的属性
Node attr = attrs.item(j);
获取属性名
attr.getNodeName();
获取属性值
attr.getNodeValue();
对于已经找到book节点只有一个ID属性可用以下方法,使用强制类型转换
Element node= (Element) list.item(i);
String attrValue = node.getAttribute("属性名");
获取id属性的属性值:attrValue;
⑤ 解析子节点名、子节点值
Nodelist childNodes = node.getChildNodes();
遍历childNodes获取每个节点的节点名和节点值,其中节点中包括空格和换行符
使用for循环遍历
区分text类型和element类型的node,通过getNodeType();
childNodes.item(k).getNodeType() == Node.ELEMENT_NODE
childNodes.item(k).getNodeName();
获取子节点的节点值
需要先获取book子节点,然后获得子节点的子节点的节点值
chileNodes.item(k).getFirstChild().getNodeValue();
getNodeValue()
与 getTextContent()
的区别
ChildNodes.item(i).getFirstChild().getNodeValue()与ChildNodes.item(i).getTextContent()的
区别:子节点中还包含其他子节点时,后者可以把子节点的值都显示出来。
getTextContent() 获取节点中的text内容(即节点值).
getNodeType()有text、element、attr三个
而Element如果要获取值,必须读取它的子节点,<name>content</name>认为content是name的子节点;
两种方法:
getFirstChild().getNodeName();(获取子节点再获取值)
getTextContent();(获取content方法)
⑥ 将内存中的xml修改的数据更新到文件中,使用Transformer()。
//将修改后的数据写到文件中
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer former = transFactory.newTransformer();
former.transform(new DOMSource(document), new StreamResult(new File(file)));
(4)DOM解析增删改查示例
public class XMLDemo1 {
public static void main(String[] args) throws Exception {
XMLDemo1 xml1 = new XMLDemo1();
xml1.read1();
//xml1.read2();
//update()
//delete()
//add()
}
//定义一个方法,获取标签中的文本内容(查询)
public void read() throws Exception {
//获取工厂
DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
//根据工厂,获取解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//调用parse开始解析xml文件
Document document = builder.parse(new File("D:\\JAVA.Document\\xml文件\\users.xml"));
//获取节点
NodeList list = document.getElementsByTagName("姓名");
//获取标签节点
Node node = list.item(0);
//获取标签中的文本内容
String userName = node.getTextContent();
System.out.println(userName);
}
//定义一个方法,获取标签中的id属性的值(查询)
public void read2() throws Exception {
//获取工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//获取解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//解析xml文件
Document document = builder.parse(new File("D:\\JAVA.Document\\xml文件\\users.xml"));
//获取节点
NodeList list = document.getElementsByTagName("姓名");
//获取标签节点
Element node = (Element)list.item(0);
String text = node.getAttribute("id");
System.out.println(text);
}
//更改
public void update() throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/users.xml"));
//现获取内容的父节点,再修改值
NodeList list = document.getElementsByTagName("姓名");
Node node = list.item(0);
//这种修改只是修改了内存中的对象,没有将修改后的数据写入到文件中
node.setTextContent("张三");
//将修改后的数据写到文件中
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer former = transFactory.newTransformer();
former.transform(new DOMSource(document), new StreamResult(new File("src/users.xml")));
}
//删除
public void delete() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/users.xml"));
//获取节点
Node node = document.getElementsByTagName("身高").item(0);
//删除节点:只能先获取父节点,再删除自己
node.getParentNode().removeChild(node);
//将修改后的数据写到文件中
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer former = transFactory.newTransformer();
former.transform(new DOMSource(document), new StreamResult(new File("src/users.xml")));
}
//增加
public void add() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("src/users.xml"));
Element node = document.createElement("用户");
//得到父节点
Node parentNode = document.getElementsByTagName("信息").item(0);
//用户挂载到信息
parentNode.appendChild(node);
Element nameNode = document.createElement("姓名");
nameNode.setTextContent("王五");
node.appendChild(nameNode);
}
}
3、SAX 解析
(1)SAX解析与DOM解析的差异
- 在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。
- SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。从xml文件的最上面开始逐一解析每一个节点,可以对于每一个节点做出其处理方式,逐一解析到内存中,寻找到符合要求的节点则结束解析。
(2)SAX解析优缺点
优点:处理速度快,可以处理大文件,节省内存。
缺点:只能读,逐行解析后将释放资源,其查询比较慢。
(3)SAX解析步骤:
① 创建SAX解析工厂、解析器对象、XML的读取器
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xmlReader = sp.getXMLReader();
② 设置读取器的事件处理器、解析xml文件
xmlReader.setContentHandler(new BookParserHandler());
xmlReader.parse("xml文件路径");
③ 创建 ParserHandler 的类
并且重写startDocument、endDocument、startElement、endElement的方法
startDocument:解析xml文件的标签开始
endDocument:解析xml文件的标签开始
startElement:解析xml文件开始
endElement:解析xml文件开始
characters:解析xml节点属性
可以定义全局变量int index = 0;为在main中设置解析每本书
④ 解析xml文件的节点属性
调用startElement(String url,String localName,String qName,Attributes attributes)方法;
开始解析book元素的属性
if(qName.equals("book")){
//已知book元素下属性名称,根据属性名称获取属性值
String value = attributes.getValue("id");
//不知道book元素下属性名和个数,可以使用for循环遍历book下属性
属性名:attributes.getQName(i);
属性值:attributes.getValue(i);
}
判断解析book是否结束
在endElement方法中使用
if(qName.equals("book")){
结束该本书的解析
}
⑤ 解析xml文件的节点名和节点间文本
解析文件的节点名,可以判断
if(!qName.equals("book")&&!qName.equals("bookstore")){
打印出解析节点值
}
新建Characters方法
public void characters(char[] ch, int start, int length){
String value = new String(ch, start, length);
if(!value.trim().equals("")){//去掉文本后的空格
value;//可以得到节点值
}
}
⑥ 使用xml解析将xml的内容和结构存入Java对象
新建book类,创建所有属性,并创建get和set方法
并在解析book值时,将得到的属性值set进book的方法中。
4、DOM4J解析
(1)DOM4J解析示例
① DOM4J 解析节点
解析books.xml文件
(1)创建SAXReader的对象reader
SAXReader reader = new SAXReader();
(2)通过reader对象的read方法加载book.xml文件,获取document对象
Document document = reader.reader(new File("src/res/book.xml"));
(3)通过document对象获取根节点bookstores
Element bookStore = document.getRootElement();
(4)通过element独享的elementIterator方法获取迭代器
Iterator it = bookStore.elementIterator();
(5)遍历迭代器,获取根节点中的信息(书籍)
while(it.hasNext()){
Element book = (Element)it.next();
获取book的属性名和属性值
List<Attribute>bookAttrs = book.attribute();
遍历每本书中的所有节点
for (Attribute attr : bookAttrs){
获取属性名
attr.getName();
获取属性值
attr.getValue();
}
}
② DOM4J 解析子节点信息
遍历book子节点依然可以使用elementIterator方法获取迭代器
Iterator itt = book.elementIterator();
while(itt.hasNext()){
Element bookChild = (Element)itt.next();
获取节点名
bookChild.getName();
获取节点值
bookChild.getStringValue();
}
5、JDOM 解析
(1)JDOM 解析步骤
① 导入jar包
② 准备工作
(1)创建一个SAXBuilder对象
SAXBuilder saxBuilder = new SAXBuilder;
(2)创建一个输入流,将xml文件加载到输入流
InputStream in = new FileInputStream("src/res/books.xml");
(3)通过saxBuilder的build方法,将输入流加载到saxBuilder
Document document = saxBuilder.build(in);
(4)通过document对象获取xml的根节点
Element rootElement = document.getRootElement();
(5)获取根节点下的子节点的List集合
List<Element> bookList = rootElement.getChildren();
③ 解析节点属性
(1)采用for循环遍历bookList中每个元素
for(Element book : bookList){
bookList.indexof(book);可以获取当前该本书处于bookList中的位置
}
(2)解析book的属性
List<Attribute> attrList = book.getAttributes();
遍历attrList(针对不清楚book节点下属性的名字及数量)
book.getAttributeName("");
book.getAttributeValue("属性名");
用以上两种方法可以获取已知的节点属性名和属性值
for(Attribute attr : attrList){
获取属性名
String attrName = attr.getName();
获取属性值
String attrValue = attr.getValue();
}
(3)解析子节点名和子节点值
List<Element> bookChilds = book.getChildren();
遍历bookChilds
for (Element child : bookChilds ){
child.getName();
child.getValue();
}
④ 解析时乱码的处理
(1)encoding编解码方式更改
(2)若(1)无法解决时
在创建输入流时可以改为使用InputStreamReader( ,"UTF-8");
通过使用字符流的方式
⑤ JDOM中存储Book对象
(1)创建book对象
Book bookEntity = new Book();
(2)判断id属性
if(attrName.equals("id")){
bookEntity.setId(attrValue)
}
(3)判断属性名
if(child.getName().equals("name")){
bookEntity.setName(child.getValue());
}
通过以上方法对每一个属性都进行判断
(4)创建一个ArrayList来存储对象
private static ArrayList<book> booksList = new ArrayList<book>();
booksList.add(bookEntity);
bookEntity = null;
⑥ JDOM中jar包的引用
若按之前的操作,有可能会发生由于工程的导入导出操作导致jar丢失,此时可以按一下操作解决。
在package下new一个folder,然后将放在桌面的jar包复制进刚刚new的folder中去,然后在package中继续build path,然后选中刚刚复制的jar 包。
6、几种解析方法比较
(1)解析方法分类
- 基础解析方式:DOM、SAX
- 扩展解析方式:JDOM、DOM4J
(2)DOM解析过程:
- 一次性将整个xml文件加载到内存中,形成DOM树
- 优点:形成了树结构,直观好理解,代码更容易编写解析过程中树结构保留在内存中,方便修改
- 缺点:当xml文件较大时,对内存消耗比较大,容易影响解析性能并造成内存溢出
(3)SAX解析过程:
- 逐条语句判断解析(基于时间的解析方式)
- 优点:采用事件驱动模式,对内存消耗比较小适用于只需要处理xml中数据时
- 缺点:不易编码,很难同时访问同一个xml中的多处不同数据
(4)JDOM解析过程:
- 仅使用具体类而不使用接口
- API大量使用了Collections类
(5)DOM4J解析过程:
- JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能
- DOM4J使用接口和抽象基本类方法,一个优秀的Java XML API具有性能优异、灵活性好、功能强大和极端易使用的特点,
- 是一个开放源代码的软件
四、XML的反射
1、反射介绍
- 获取对象类,并解析出其组成部分(方法,属性,构造方法)。
- Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。
- 使用反射,可以在运行时对类Class、构造方法Constructor、普通方法Method、字段Field进行操作。
2、Class 对象
(1)getConstructor()
:获取一个类的公共的构造方法
- 获取无参构造:
getConstructor(null);
- 获取有参构造:
getConstructor(数据类型.class);
调用到构造方法之后,想要使用反射创建对象,那么就必须使用newInstance()
方法,有参就需要传递参数,无参则不需要。
(2)getMethod()
:获取一个类的公共的成员方法
- 无参的方法:
getMethod(null);
想要调用方法,需要使用invoke(对象, null); 方法 - 有参的方法:
getMethod(方法名, 数据类型.class);
想要调用方法,需要使用invoke(对象, 参数列表); 方法
(3)getField()
:获取一个公共的成员属性
Field field = clazz.getField("成员属性名");
想要使用到该属性,使用field.get(对象)方法获取其数据,field.set()能够设置数据,如果是final成员属性,需要使用setAccessible(true);
暴力破解
(4)getDeclaredConstructor()
:获取一个类的私有的构造方法
(5)getDeclaredMethod()
:获取一个类的私有的成员方法
(6)getDeclaredField()
:获取一个私有的成员属性
(4)、(5)、(6)都需要使用setAccessible(true);
暴力破解
(7)使用反射创建字节码
方式1:Class cla = Class.forName(“完整类名”);完整类名是指:包名.类名
Class clazz = Class.forName("com.study.Person");//必须类全名
方式2:Class cla = 类名.class;
Class clazz = Person.class;
方式3:Class cla = new 类名().getClass();
//创建Peron对象
Person p = new Person();
//通过object继承来的方法(getClass)获取Person对应的字节码文件对象
Class clazz = p.getClass();
(8)反射示例
示例1:反射操作构造方法
① Person类
public class Person {
public String name;
private int age;
public Person() {
System.out.println("这是无参构造");
}
public Person(String name) {
System.out.println(name + "这是有参构造");
}
public Person(String name, int age) {
System.out.println(name + "说这是有参构造,今年" + age + "岁");
}
private Person(int age) {
System.out.println("私有构造方法" + age);
}
public void eat() {
System.out.println("吃饭");
}
public void eat(String name) {
System.out.println(name + "吃饭");
}
private void sleep() {
System.out.println("睡觉");
}
}
② main函数类
public class Demo {
@Test
public void refect1() throws Exception{ //调用无参构造
//1、使用反射,获取字节码对象
Class cla = Class.forName("javaeestudy.num1.Person");
//2、使用Class类中的getConstructor()方法,调用其类的公共无参构造方法
Constructor constructor = cla.getConstructor(null);
constructor.newInstance();
}
@Test
public void refect2() throws Exception{ //调用有参构造
//1、使用反射,获取字节码对象
Class cla = Class.forName("javaeestudy.num1.Person");
//2、使用Class类中的getConstructor()方法,调用其类的公共有参构造方法
Constructor constructor = cla.getConstructor(String.class);
constructor.newInstance("张三");
}
@Test
public void refect3() throws Exception{ //调用有参构造
//1、使用反射,获取字节码对象
Class cla = Class.forName("javaeestudy.num1.Person");
//2、使用Class类中的getConstructor()方法,调用其类的公共有参构造方法
Constructor constructor = cla.getConstructor(String.class, int.class);
constructor.newInstance("张三", 18);
}
@Test
public void refect4() throws Exception{ //调用私有构造方法
//1、使用反射,获取字节码对象
Class cla = Class.forName("javaeestudy.num1.Person");
//2、使用Class类中的getConstructor()方法,调用其类的私有构造方法
Constructor constructor = cla.getDeclaredConstructor(int.class);
//3、开启暴力破解
constructor.setAccessible(true);
constructor.newInstance(18);
}
}
示例2:反射对方法和属性的操作
public class Demo2 {
@Test
public void method1() throws Exception { //使用反射操作其类中的方法
Class cla = Class.forName("javaeestudy.num1.Person");
//参数(name, parameter),name表示方法名,parameter表示参数的数据类型
Method method = cla.getMethod("eat", null);
//invoke(obj, args)方法,使用对象调用方法,obj表示对象,args表示参数值
method.invoke(cla.newInstance(), null);
}
@Test
public void method2() throws Exception { //操作有参方法
Class cla = Class.forName("javaeestudy.num1.Person");
//参数(name, parameter),name表示方法名,parameter表示参数的数据类型
Method method = cla.getMethod("eat", String.class);
//invoke(obj, args)方法,使用对象调用方法,obj表示对象,args表示参数值
method.invoke(cla.newInstance(), "张三");
}
@Test
public void method3() throws Exception { //操作私有方法
Class cla = Class.forName("javaeestudy.num1.Person");
//参数(name, parameter),name表示方法名,parameter表示参数的数据类型
Method method = cla.getDeclaredMethod("sleep", String.class);
//开启暴力拆解
method.setAccessible(true);
//invoke(obj, args)方法,使用对象调用方法,obj表示对象,args表示参数值
method.invoke(cla.newInstance(), "张三");
}
@Test
public void method4() throws Exception { //操作公共属性
Class cla = Class.forName("javaeestudy.num1.Person");
Field field = cla.getField("name");
//获取字段的值
//obj参数,代表的是那个对象的字段
String obj = (String) field.get(cla.newInstance());
System.out.println(obj);
}
@Test
public void method5() throws Exception { //操作公共属性
Class cla = Class.forName("javaeestudy.num1.Person");
Field field = cla.getDeclaredField("age");
//开启暴力拆解
field.setAccessible(true);
//获取字段的值
//obj参数,代表的是那个对象的字段
int age = field.getInt(cla.newInstance());
System.out.println(age);
}
}
示例3:通过操作xml文件和反操作方法
① xml文件
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<package pname="javaeestudy.study">
<clazz cname="Person">
<method type="public">eat</method>
<method type="private">sleep</method>
</clazz>
</package>
② Person类
public class Person {
//公共方法
public void eat() {
System.out.println("吃饭");
}
//私有方法
private void sleep() {
System.out.println("睡觉");
}
}
③ main函数:操作类
public class Demo {
public static void main(String[] args) throws Exception {
new Demo2().method1();
}
//操作方法
public void method1() throws Exception {
Document document = getDocument();
//获取包名
NodeList packageList = document.getElementsByTagName("package");
Element packageNode = (Element)packageList.item(0);
String text = packageNode.getAttribute("pname");
//获取类名
NodeList clazzList = document.getElementsByTagName("clazz");
Element clazzNode = (Element)clazzList.item(0);
text = text + "." + clazzNode.getAttribute("cname");
//使用反射,获取字节码对象
Class cla = Class.forName(text);
//获取方法节点
NodeList methodList = document.getElementsByTagName("method");
for(int i = 0; i < methodList.getLength(); i++) {
//获取方法类型type
Element typeNode = (Element)methodList.item(i);
String typeText = typeNode.getAttribute("pname");
//获取方法名
Node methodNode = methodList.item(i);
String methodName = methodNode.getTextContent();
Method method = null;
if(typeText.equals("public")) {
//使用Class类中的getMethod方法,调用其类的公共无参构造方法
method = cla.getMethod(methodName, null);
}else {
//使用Class类中的getDeclaredMethod方法,调用其类的私有无参构造方法
method = cla.getDeclaredMethod(methodName, null);
//开启暴力拆解
method.setAccessible(true);
}
//invoke(obj, args)方法,使用对象调用方法,obj表示对象,args表示参数值
method.invoke(cla.newInstance(), null);
}
}
//获取document方法
public Document getDocument() throws Exception {
//获取工厂
DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
//根据工厂,获取解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//调用parse开始解析xml文件
return builder.parse(new File("src\\javaeestudy\\study\\person.xml"));
}
}