XML学习

本文介绍XML的基本概念,包括DTD和Schema约束的使用方法,并详细解释了DOM、SAX及Pull三种解析方式的特点。此外,还提供了使用dom4j解析XML的具体示例,以及如何通过XML配置实现类的反射实例化。

为灵活实现不同路径执行不同的资源,需要使用XML进行配置。

XML 意为可扩展的标记语言,标签可以由用户自定义。通常进行配置文件,不是HTML的替代者而是补充。

XML文档声明必须为<?xml开头,以?>结束 ,0行0列开始,只有三个属性 versioin 版本  encoding 编码

为限定XML的内容,使用XML约束 常见 :DTD  Schema

一、DTD约束

通常不会自己写DTD文档,需要根据提供的DTD约束编写对应的XML文档。常见框架使用DTD约束的有Struts2、Hibernate等

例根据如下dtd约束编写XML文档

<?xml version="1.0" encoding="UTF-8"?>
<!--
	传智播客DTD教学实例文档。
	模拟servlet2.3规范,如果开发人员需要在xml使用当前DTD约束,必须包括DOCTYPE。
	格式如下:
	<!DOCTYPE web-app SYSTEM "web-app_2_3.dtd">
-->
<!ELEMENT web-app (servlet*,servlet-mapping* , welcome-file-list?) >
<!ELEMENT servlet (servlet-name,description?,(servlet-class|jsp-file))>
<!ELEMENT servlet-mapping (servlet-name,url-pattern+) >
<!ELEMENT servlet-name (#PCDATA)>
<!ELEMENT servlet-class (#PCDATA)>
<!ELEMENT url-pattern (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT jsp-file (#PCDATA)>

<!ELEMENT welcome-file-list (welcome-file+)>
<!ELEMENT welcome-file (#PCDATA)>

<!ATTLIST web-app version CDATA #IMPLIED>

二、Schema约束

常用框架使用的有Spring等,后缀为xsd,DTD的替代者,数据类型更完善,支持名称命名空间。

命名空间:处理元素和属性的名称冲突。

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
	传智播客Schema教学实例文档。
	模拟servlet2.5规范,如果开发人员需要在xml使用当前Schema约束,必须包括指定命名空间。
	格式如下:
	<web-app xmlns="http://www.example.org/web-app_2_5" 
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
			version="2.5">
-->
<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: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>


XML解析,获取XML的内容。IO可以做但繁琐。比较常见的解析有 DOM SAX PULL(理论解析方法)

DOM:要求解析器把整个XML文档装载到内存,解析成Document对象 

优点 元素与元素之间保留结构关系,可以进行增删改查操作。 缺点 当XML文档过大可能出现内存溢出

SAX:逐行扫描,边扫描边解析,速度更快,更有效。优点 处理快可以处理大文件 缺点 只能读 逐行后释放资源。

PULL 安卓内置的XML解析方式类似SAX。


解析器

使用dom4j 常用解析开发包,hibernate底层采用。必须导入jar包。必须使用核心类SaxReader加载xml文档获取Document,再获得文档根元素。

public class TestDom4j {
	@Test
	public void testReadWebXML() {
		try {
			// 1、获得解析器
			SAXReader saxReader = new SAXReader();
			// 2、获得document文档对象
			Document doc = saxReader.read("src/XML_Schema/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 i:childElements)
			{	
				//找到与字符串相同的子元素 获取其中的text 
				if("servlet".equals(i.getName())) {
					Element servletName = i.element("servlet-name");
					Element servletClass = i.element("servlet-class");
					System.out.println(servletName.getText());
					System.out.println(servletClass.getText());
				}
			}	
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
}


利用反射模拟servlet的运行

为模拟服务器端程序,且可以同时存在多个类似程序。提供一个Myservlet接口,接口中有三个方法。编写两个实现类1和2 

public class MyServletImpl implements MyServlet {
	@Override
	public void init() {
		System.out.println("1号111");
	}
	@Override
	public void service() {
		System.out.println("1号222");
	}
	@Override
	public void destory() {
		System.out.println("1号333");
	}
}
此时为程序的可扩展性,防止硬编码,通过反射加载字符串指定类,并创建实例。通过解析XML文档获取类全名和url,XML文档。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://www.example.org/web-app_2_5" 
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
			version="2.5">
			
			<servlet>
				<servlet-name>Servlet1</servlet-name>		
				<servlet-class>servlet.MyServletImpl</servlet-class>
			</servlet>
			<servlet-mapping>
				<servlet-name>Servlet1</servlet-name>
				<url-pattern>/myServlet1</url-pattern>
			</servlet-mapping>
			
			
			<servlet>
				<servlet-name>Servlet2</servlet-name>		
				<servlet-class>servlet.MyServletImpl2</servlet-class>
			</servlet>
			<servlet-mapping>
				<servlet-name>Servlet2</servlet-name>
				<url-pattern>/myServlet2</url-pattern>
			</servlet-mapping>			
</web-app>

在执行测试程序前 解析XML文件 将解析结果放在map 格式为路径=实现类。servlet标签中存着类全名,servlet-mapping存着url。解析方法和实现方法如下

public class Test2 {

	/*使用反射模拟servlet的运行
	 * XML配置文件中实现类的类全名和url 但分属于不同的标签中
	 */
	private HashMap<String,String> data= new HashMap<String,String>();	//存储url,类全名
	
	@Before
	public void getMethod(){	
		try {
			//从XML文件中解析类全名存入一个map中
			SAXReader saxReader = new SAXReader ();
			Document read = saxReader.read("src/XML_Schema/web.XML");
			Element rootElement = read.getRootElement();
			List<Element> elements = rootElement.elements();
			
			//servlet标签中存着类全名,servlet-mapping中存着url
			for(Element i:elements)
			{
				if("servlet".equals(i.getName()))
				{
					//先将名字,类全名添加进data
					data.put(i.element("servlet-name").getText(), i.element("servlet-class").getText());	
				}
				if("servlet-mapping".equals(i.getName()))
				{	
					//获取类全名
					String servletClass = data.get(i.element("servlet-name").getText());			
					data.remove(i.element("servlet-name").getText());//移除之前添加的名字,类全名
					data.put(i.element("url-pattern").getText(),servletClass);//添加url,类全名
				}
			}
			//System.out.println(data);	
		} catch (Exception e) {
			e.printStackTrace();
		}	
	}
	@Test
	public void testMethod(){
		try {
			String urll = "/myServlet1";
			String clazz = data.get(urll);
			Class<?> forName = Class.forName(clazz);
			MyServlet servlet = (MyServlet) forName.newInstance();
			servlet.init();
			servlet.service();
			servlet.destory();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}

}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值