打算考研,一直没空出时间来继续学习,今天晚上因为计划出了点问题,空出来不少时间,把这一节补上。
1、XML简介
XML全称为Extensible Markup Language,意思是可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。
使用的规则比较简单,不再赘述,下面这个网址挺好的emm
http://www.w3school.com.cn/xml/index.asp
2、XML约束
1.DTD约束
DTD为英文Document Type Definition,中文意思为“文档类型定义”。DTD肩负着两重任务:一方面它帮助你编写合法的代码,另一方面它让浏览器正确地显示器代码。
一个DTD应该放在每一个文档的第一行(包括空白).这样正确地放置,你的DTD才能告诉浏览器的用的是什么标记语言。在通常情况下,如果你编写的是正确代码,并拥有一个合适的DTD,浏览器将会根据W3C的标准显示你的代码。
良好的xml文档:符合xml的语法规则。
有效的xml文档:符合xml语法规则的同时还需要符合DTD文档类型定义。
有效(Valid)的XML文档:
首先,XML文档是个格式正规的(Well-formed)XML文档;
其次,需要满足DTD的要求,这样的XML文档称为有效的(Valid)XML文档。
利用DTD可以对xml文档的各个节点进行约束定义,使开发遵循一套“标准”。
DTD可以约束xml文档出现的元素,元素名称,元素的先后顺序,属性等。
DTD文档有三种应用形式:
1.内部DTD文档,仅对当前xml有效
<!DOCTYPE 根元素[定义内容]>
2.外部DTD文档,文档在本地系统上
<!DOCTYPE 根元素 SYSTEM "DTD文件路径">
3.内外部DTD文档结合,文档在网络上,一般都有框架提供
<!DOCTYPE 根元素 SYSTEM "DTD文件路径" [定义内容]>
下面给出一个编写的范例
<!DOCTYPE poem [
<!ELEMENT poem (author, title, content)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT content (#PCDATA)>
<!--为元素poem定义了三个子元素author title content,
这三个元素必须要出现并且必须按照这个顺序
少元素不行,多元素也不行
#PCDATA(Parsed Character Data) ,可解析的字符数据,即字符串。
-->
<!--指明author,title,content里面的内容是字符串类型-->
<!ATTLIST poem poet CDATA #IMPLIED>
<!--给poem(元素)添加poet(属性),属性必须是(文本值),且(可选)-->
<!--属性类型有:ID、CDATA(文本类型)、枚举({e1|e2|e3...}多选一)-->
<!--约束有:#REQUIRED 必须的、#IMPLIED 可选的-->
]>
本部分内容参考https://blog.csdn.net/yeoman92/article/details/53055749
2.SCHEMA约束
schema是新的xml文档约束,比dtd要强大的多,其本身也是xml文档,但其扩展名为xsd,且支持命名空间。常见使用schema的框架有spring等。
直接给一个示范吧:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/web-app_2_5"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.example.org/web-app_2_5"
elementFormDefault="qualified">
<!--如xsd、tns等就是对上面定义的命名空间的使用,可以把网址复制下来去看看具体的文件编写-->
<xsd:element name="web-app">
<xsd:complexType>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="servlet">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="servlet-name"></xsd:element>
<xsd:element name="servlet-class"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="servlet-mapping">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="servlet-name"></xsd:element>
<xsd:element name="url-pattern" maxOccurs="unbounded"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="welcome-file-list">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="welcome-file" maxOccurs="unbounded"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:attribute name="version" type="double" use="optional"></xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>
命名空间用来处理元素和属性重名的问题,与java中包的使用类似。
3、XML解析
常用的解析器有DOM、SAX以及安卓内置的PULL。这里主要介绍用DOM解析XML文件,使用到了dom4j这个解析开发包。
xml dom将整个xml文档加载至内存,生成一个dom树,并获得一个document对象,通过document对象就可以对dom进行操作。
dom中核心概念就是节点,在xml文档中的元素、属性、文本等在dom中都是节点!
dom4j常用的API有:
SaxReader对象:read() 加载执行xml文档
Document对象:getRootElement() 获得根元素
Element对象:elements() 获得指定名称的所有子元素,也可以不指定名称
element() 获得指定名称的第一个子元素,也可以不指定名称
getName() 获得当前元素的元素名
attributeValue() 获得指定属性名的属性值
elementText() 获得指定名称子元素的文本值
getText() 获得当前元素的文本内容
下面给出一段示例代码:
public class TestDom4j {
@Test
public void testReadWebXML() {
try {
// 1.获取解析器
SAXReader saxReader = new SAXReader();
// 2.获得document文档对象
Document doc = saxReader.read("src/web.xml");
// 3.获取根元素
Element rootElement = doc.getRootElement();
// System.out.println(rootElement.getName());//获取根元素的名称
// System.out.println(rootElement.attributeValue("version"));//获取根元素中的属性值
// 4.获取根元素下的子元素
List<Element> childElements = rootElement.elements();
// 5.遍历子元素
for (Element element : childElements) {
//6.判断元素名称为servlet的元素
if ("servlet".equals(element.getName())) {
//7.获取servlet-name元素
Element servletName = element.element("servlet-name");
//8.获取servlet-class元素
Element servletClass = element.element("servlet-class");
System.out.println(servletName.getText());
System.out.println(servletClass.getText());
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
4、反射(PS:本节重点重点重重点)
应用程序已经运行,无法在其中进行new对象的建立,就无法使用对象。这时可以根据配置文件的类全名去找对应的字节码文件,并加载进内存,并创建该类对象实例。这就需要使用反射技术完成,通过反射动态获取指定类以及类中的内容(成员),并运行其内容。
要利用反射,首先要获取到对应的类,这里有三种方法:
1.通过对象具备的getClass方法(源于Object类的方法)。有点不方便,需要用到该类,并创建该类的对象,再调用getClass方法完成。
Person p = new Person();//创建Peron对象
Class clazz = p.getClass();//通过object继承来的方法(getClass)获取Person对应的字节码文件对象
2.每一个类型都具备一个class静态属性,通过该属性即可获取该类的字节码文件对象。比第一种简单了一些,仅用一个静态属性就搞定了。但是,还是有一点不方便,还必须要使用到该类。
Class clazz = Person.class;
3.使用Class.forName(),相对方便的多,不需要直接使用具体的类,只要知道该类的名字即可。而名字完成可以作为参数进行传递 ,这样就可以提高扩展性。所以为了动态获取一个类,第三种方式最为常用。
Class clazz = Class.forName("com.bean.Person");//必须类全名
这里有个来自IT黑马的实例,但是代码有点长我就不复制粘贴了,大家下载之后直接拖到src目录下就可以测试运行了。通过运行实例我们可以清晰的理解反射是如何执行的,即调用class字节码文件动态的更新内容,这在实际生产环境下十分有用。
同样最后不忘打一下广告,欢迎关注:落饼枫林!回复 反射 获取代码!