java之XML


XML常用应用:

xml除了保存有关系的数据之外,他还经常用作配置文件,来描述进程模块之间的关系

在一个软件系统中,为提高系统的灵活性,他所启动的模块通常由其配置文件决定

XML文件分为以下几个部分:

1、文档声明:使用Xml文件时要先声明文件的版本,编码,standalone属性(说明文件是否独立)

2、元素:xml文件中的标签

3、属性:标签中的属性

4、注释:<!--    -->

5、CDATA区:将一段代码不被解析引擎解析

特殊字符:

特殊字符      替代符号

&                    &amp

 <                     &lt

>                       &gt

"                        &quot

'                       &apos

6、处理指令(processing instruction):他简称PI,处理指令用来指挥解析引擎如何解析xml文档内容

例如:在xml文档中可以使用xml-stylesheet指令,通知xml解析引擎,应用css文件显示xml文档的内容

<? xml-stylesheet  type="text/css" href="1.css"?>

注:处理指令必须以<? 作为开头,以?>作为结尾xml声明语句就是最常见的一种处理指令

XML约束概述:

常用约束技术:

XML  DTD和XML Schema

xml中的DTD技术:

元素定义:

例如:

<!ELEMENT a (b)>

a和b之间一定要有空格空开否则编译出错

在DTD文件中每一部分之间一定要有空格将其分开否则会报错

用到的语句是PCDATA代表的是字符格式

+代表1-n次

*代表0-n次

?代表0-1次

对于b中的内容如果是逗号分开的要按照顺序进行排序

属性定义:

对于属性常用到的格式为

CDATA字符数据

ID:id编号他一般是有字母开头组成的字符串

EUMNETION:<!ATTLIST 元素名    属性名  (en1|en2)  "可以带上个默认值">例如: <!ATTLIST book bookTest (check|cash) "cash">

对属性的的要求限定

REQUIRED:必须写

IMPLIED:可以不写

FIXED:设定默认值

直接在数据类型后面声明值

实体定义:

有两种方式

一种是引用实体:

<!ENTITY  copyright  "I am studying">

然后在<book>&copright;</book>

注:这个地方一定要加上分号,否则编译不通过

另一种是参数实体:

<!ENTITY  %  name  "<!ATTLIST name time CDATA #FIXED 'aaa'>">

在这里面%分号左右都要有空格否则编译失败

对于调用只能放在声明体外面否则编译失败

例如只能这样写:

	<!ENTITY  %  names   "<!ATTLIST name time CDATA #FIXED 'aaa'>">
	%names;

此时的%后面紧跟着名字不能用空格并且还要写分号

XML解析技术的概括

XML解析技术有两种一种是dom解析一种是sax解析,他们的区别是:

1、dom解析的有点是对文档crud比较方便,缺点是消耗内存比较大,是w3c组织推荐的解析xml的一种方式

2、sax解析的优点是占用内存少解析速度快,缺点是适合做文档的读取不适合做文档的crud,不是官方标准,但他是xml社区事实上的标准,几乎所有的xml解析器都支持他

jvm默认内存是64M

调整jvm内存大小就是将-Xmx 80m将内存改成80兆

xml解析开发包:

jaxp(sun公司开发的) ,jdom,dom4j

JAXP:

jaxp开发包是j2se的一部分,它由javax.xml.org.w3c.dom和org.xml.sax包及其子包组成

在javax.xml.parsers包中,定义了几个工厂类,程序员调用这些工厂类,可以得到xml文档的dom或sax的解析器,从而实现对xml文档的解析

使用jaxp进行dom解析:

javax.xml.parsers包中DocumentBuilderFactory用于创建DOM模式的解析器对象,DocumentBilderFactory是一个抽象工厂类,他不能直接实例化,但该类提供了newInstanc方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对对象并返回

DOM方式解析XML文件的编程步骤:

获取document对象:

private void getDocument()throws Exception
	{
		DocumentBuilderFactory builderFactory=DocumentBuilderFactory.newInstance();
		DocumentBuilder builder=builderFactory.newDocumentBuilder();
		document=builder.parse("src\\book.xml");
	}

保存处理后的document对象:

private void setSave() throws Exception
	{
		TransformerFactory formerFactory=TransformerFactory.newInstance();
		Transformer former=formerFactory.newTransformer();
		former.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src\\book.xml")));
	}

遍历所有节点:

	public void bianLiNode(Node node)
	{
		if(node instanceof Element)//判断获得的节点是否是标签,因为在程序处理的时候程序还会将text标签也当做是节点处理
		sop(node.getNodeName());//打印获的标签的名字
		NodeList childList=node.getChildNodes();//获取标签下的子标签
		for(int i=0;childList!=null&&i<childList.getLength();i++)//要先判断子标签是否为空否则会发生空指针异常
		{
			bianLiNode(childList.item(i));//通过遍历的方法将标签遍历出来
		}	
	}

查找某一个节点:

Element element=(Element) document.getElementsByTagName("book").item(0);

删除节点:

		Element element=(Element) document.getElementsByTagName("time").item(0);
		element.getParentNode().removeChild(element);

更新节点:

	Element element=(Element) document.getElementsByTagName("book").item(1);
		element.setAttribute("bookId", "345");

添加节点:

		Element element=document.createElement("time");
		element.setTextContent("tianjia");
		
		Element book=(Element) document.getElementsByTagName("book").item(0);
		book.appendChild(element);
对于上面的几种操作凡是xml文件发生变化的都要对修改后的文件进行保存
通过自己写成程序得知:

当修改标签属性的时候用setNodeValue设置标签中的内容用setTestContent方法

做项目总结:

在做项目时要先分析项目的框架,一边情况项目中和用户直接交互的程序放在UI包中,和数据直接交互的程序方法dao包中,对dao起辅助功能的工具包放在util包中,在程序中用到的对象类方法domain或者bean或者entity包中

SAX解析:

使用dom解析xml文档时需要读取整个文档,在内存中构架代表整个dom树的document对象,从而在对xml文档进行操作,此种情况下,如果xml文档特别大,就会消耗计算机大量内存,并且容易导致内存溢出

sax解析允许读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会对文档进行操作

sax采用事件处理的方式解析xml文件,利用sax解析xml'文档涉及两个部分:解析器和事件处理器

解析器可以使用jaxp的api创建,创建出sax解析器后,就可以指定解析器去解析某个xml文档

解析器采用sax方式在解析某个xml文档时,他只要解析到xml文档的一个组成部分,就会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器

事件处理器有程序员辨编写,程序员通过事件处理器中的方法的参数,就可以很轻松的得到sax解析器解析的数据,从而可以决定如何对数据进行处理

对xml文档的信息进行遍历:

1、创建解析工厂

SAXParserFactory parserFactory=SAXParserFactory.newInstance();

2、获取解析器

SAXParser parser=parserFactory.newSAXParser();

3、获取读取器

XMLReader reader=parser.getXMLReader();

4、设置处理器

         reader.setContentHandler(new DefaultHandler(){//此处理器是实现将所有书的节点存到list集合中
			private boolean flag=false;
			private String nodeName;
			private Book book=null;
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				if("book".equals(qName))
				{
					flag=true;
					book=new Book();
					list.add(book);//因为list存放的是book对象的地址,所以可以对下面的对象直接复制
				}
				nodeName=qName;//获取当前标签的名称
			}
			
			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
					String content=new String(ch,start,length);
					if(flag&&nodeName!=null)
					{
						if("name".equals(nodeName))
						{
	//						System.out.println("\t"+nodeName+":\t"+content);
							book.setName(content);
						}
						if("author".equals(nodeName))
						{
	//						System.out.println("\t"+nodeName+":\t"+content);
							book.setAuthor(content);
						}
						if("price".equals(nodeName))
						{
	//						System.out.println("\t"+nodeName+":\t"+content);
							book.setPrice(content);
						}
					}
					
			}
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				nodeName=null;
				if("book".equals(qName))//当标签的结束标签的名字是book的时候要将flag设为false这表明一本书的信息已经录入完
				{
					flag=false;
				}
			}
 

5、读取xml文档

reader.parse("src/book.xml");

DOM4J解析xml文档:

dom4j是一种简单、灵活的开放源代码的库。Dom4j是由早期开发的jdom的人分离出来而独立开发的,于jdom不同的是,Dom4j使用接口和抽象基类,虽然Dom4j的Api相对要复杂点,但是它提供了比Dom更好的灵活性

Dom4j是一个非常优秀的java xml api,具有性能优异、功能强大和极易使用的特点。现在很多软件采用Dom4j,例如hibernate,包括sun公司自己的jaxm也用了dom4j

Dom4j编码问题:

对于它的默认编码是UTF-8所以不管什么编码的数据一旦读入将会被变成UTF-8的编码,如果想更改默认值如下:

OutputFormat   format=OutputFormat.createPrettyPrint();

format.setEncoding("gb2313");

Dom4j的增删改查:

在dom4j中获得Document对象(注:这个地方的document对象和jaxp中的不是一个注意导入的包)

	private Document parser() throws Exception
	{
		SAXReader reader=new SAXReader();//获取读取器
		Document document=(Document) reader.read("src/student.xml");//读取xml文档
		return document;
	}
将修改后的document保存到xml文档中

private void write(Document document)throws Exception//此种方法不会更改格式,相对应的地方添加上,不会更改以前文档中的格式
	{
		XMLWriter writer=new XMLWriter(new FileWriter("src/student.xml"));
		writer.write(document);
		writer.close();
	}
	private void prettyPrint(Document document)throws Exception//这种方式将保存xml并格式化
	{
		//OutputFormat format=OutputFormat.createPrettyPrint();//这种是漂亮的格式化
                OutputFormat format=OutputFormat.createCompactFormat();//这种方式将会去掉标签中的空格实现压缩的功能
                 XMLWriter writer=new XMLWriter(new FileWriter("src/student.xml"),format);
		writer.write(document);
		writer.close();	
	}
遍历标签:

private void getChild(Element element)throws Exception
	{
		for(Iterator<Element> it=element.elementIterator();it.hasNext();)
		{
			Element child=it.next();
	
				System.out.print(child.getName()+":");
				System.out.println(child.getText());
				Iterator<Element> itChild=child.elementIterator();
				if(itChild.hasNext())
					getChild(child);
		}
	}
增加标签:

public void add() throws Exception
	{
		Document document=parser();
		Element exam=document.getRootElement();
		Element student=exam.addElement("student");
		student.addElement("number").addText("101105111");
		student.addElement("name").addText("zxm");
		student.addElement("price").addText("100.00");
		//write(document);
		prettyPrint(document);
	}
查找:

	public void getNode1()throws Exception
	{
		Document document=parser();
		List<Element> list=document.selectNodes("//exam/student");
		for(Iterator<Element> it=list.iterator();it.hasNext();)
		{
			getChild(it.next());
		}
	}
删除:

public void delete() throws Exception
	{
		Document document=parser();
		Element exam=document.getRootElement();
		Element element=(Element) exam.selectSingleNode("//student[@name='zjd1']");
		getChild(element);
		exam.remove(element);
		prettyPrint(document);
	}

修改:

public void update()throws Exception
	{
		Document document=parser();
		Element exam=document.getRootElement();
		Element element=(Element) exam.selectSingleNode("//student[@name='zjd1']");
		Element name=(Element) element.selectSingleNode("name");
		name.setAttributeValue("name", "zxm");
		prettyPrint(document);	
	}

XML Schema

xml Schema 也是一种用于定义和描述xml文档结构与内容的模式语言,它的出现是为了克服DTD的局限性
xml Schema VS DTD
    xml Schema符合xml语法结构

    DOM,SAX等xml API很容易解析出xml Schema文档中的内容

    xml Schema对名称空间(是Schema独有的)支持的非常好

    xml Schema比xml  DTD支持更多的数据类型,并支持用户自定义新的数据类型

    xml Schema定义约束的能力非常强大,可以对xml实例文档作出细致的语义限制

    xml Schema不能像DTD一样定义实体,比DTD更复杂但xml Schema现在已是w3c组织的标准,他正逐步取代DTD

Schema约束快速入门
   xml Schema文件自身是一个xml文件,但他的扩展名通常为.xsd

   一个xml Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档

   和xml文件一样,一个xml Schema文件也必须有一个根节点,但这个根节点的名称是Schema

   编写一个xml Schema约束文档后,通常需要把这个文件中声明的元素绑定到一个URI地址上,在xml Schema技术中有一个专业术语来描述这个过程,
   即把xml Schema文档声明的元素绑定到一个名称空间上,以后xml文件就可以通过这个URI(即名称空间)来告诉解析引擎,xml文档中编写的元素来自哪里被谁约束

如下shema文档分析:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"//定义一个元素和数据类型的命名空间,并将命名空间赋值到xs上,其中xmlns一定不能写成其他字母
targetNamespace="http://www.w3school.com.cn"//定义一个自定义元素的的命名空间
xmlns="http://www.w3school.com.cn"//设置默认命名空间
elementFormDefault="qualified">//规定自定义元素必须是自定义元素命名空间的元素
<xs:element name="note">//定义一个node标签
    <xs:complexType>//将node标签设置为复合类型,用于放多个标签
      <xs:sequence>//node标签中放入的子标签
		<xs:element name="to" type="xs:string"/>//创建一个名为to的标签且他存入到的数据类型是string类型,(注:这个地方的string一定要小写,
                                                        //他的所有数据类型都是小写开头的
		<xs:element name="from" type="xs:string"/>
		<xs:element name="heading" type="xs:string"/>
		<xs:element name="body" type="xs:decimal"/>
      </xs:sequence>
    </xs:complexType>
</xs:element>

</xs:schema>
引用上面的shema文档的xml文件:

<?xml version="1.0" encoding="UTF-8" ?>
<note 
 xmlns="http://www.w3school.com.cn"//设置默认的命名空间
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"//个人理解就是将定义元素和数据类型的命名空间导入
 xsi:schemaLocation="http://www.w3school.com.cn F:/java/xmlpractice/src/note.xsd">//这个有两个参数,第一个是提供的命名空间,第二个值是供命名
                                                                                  //空间使用的文档地址
	<to>George</to>
	<from>John</from>
	<heading>Reminder</heading>
	<body>Don't forget the meeting!</body>
	<sadasd></sadasd>
</note>
上面的代码没有实现限定,至今不知为什么,我是从api文档上拷贝下来的,不知怎么回事但是大体也理解了一下


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值