第三天:dom4j_xpath_schema

来源:互联网 发布:足球大师小贝捏脸数据 编辑:程序博客网 时间:2024/05/29 18:57

u  jaxp dom 编程回顾

jaxp dom 编程的流程

1.       得到DocumentBuilderFactory

DocumentBuilderFactorydbf= DocumentBuilderFactory.newInstance();

2.       通过工厂得到dom解析器DocumentBuilder

DocumentBuilder db=dbf.newDocumentBuilder();

3.       通过解析器得到你要解析的 xml对应的Document

Documentdocment=db.parse(new File(“src/xxx.xml”));

4.       如何对xml文件进行读的的操作

4.1. 读取xml文件的某个标签的内容

*得到xml标签对应的节点对象

Element element=(Element)docment.getElementsByTagName(‘标签的名字’ ).item(第几个) ;

*读取

String con=element.getTextContent() ;

4.2. 读取xml文件的标签的属性值

*得到xml标签对应的节点对象

Element element=(Element)document.getElementsByTagName(‘标签名字’ ).item(第几个) ;

*得到标签属性的值

Stiring val=element.getAttribute(‘属性名称’) ;

5.       使用jaxp dom技术对xml文件进行添加操作

5.1添加标签(标签体,也可能是子标签)

       *通过document来创建Element

       Element element=document.createElement(‘标签名’) ;

       如果有子标签

       Element element2=document.createElement(‘子标签’) ;

       elements.setTextContent(‘’)

       element.appendChild(element2) ;

       *给标签赋值

       element.setTextContent(‘值’) ;

       *添加到它的父标签对应的节点对象

       parent.appendChild(element) ;

       *更新xml

       (1)得到TransformerFactory

       TransformerFactory tff= TransformerFactory.newInstance() ;

       (2)得打转换器Transformer

       Transformer tf=tff.newTransformer() ;

       (3)转换把document -> 文件

       tf.transform(newDOMSource(document),new StreamResult(new File(“src/abc.xml”)));

5.2给xml文件的某个标签添加属性

       *得到这个标签对应的节点对象

Element element=(Element)document.getElementsByTagName(‘标签名字’ ).item(第几个) ;

*添加属性

element.setAttribute(‘属性名’,’属性值’) ;

*更新xml

       (1)得到TransformerFactory

       TransformerFactory tff= TransformerFactory.newInstance() ;

       (2)得打转换器Transformer

       Transformer tf=tff.newTransformer() ;

       (3)转换把document -> 文件

6.对xml文件进行删除的操作

6.1删除某个标签

       *得到标签对应的节点对象

Element element=(Element)document.getElementsByTagName(‘标签名字’ ).item(第几个) ;

*删除标签

element.getParentNode().removeChild(element) ;

//更新文档

6.2删除标签的某个属性

       *得到标签对应的节点对象

Element element=(Element)document.getElementsByTagName(‘标签名字’ ).item(第几个) ;

       *删除该标签的某个属性

       element.removeAttribue(‘属性名’)

       *更新文档

7.对xml文件更新操作

7.1对xml文件的标签内容更新

       *得到标签对应的节点对象

Element element=(Element)document.getElementsByTagName(‘标签名字’ ).item(第几个) ;

*更新属性

element.setAttribute(‘属性名’,’值’) ;

*更新内容

element.setTextContent(’新值’)

//更新文档

 

在使用 DOM解析 XML文档时,需要读取整个XML文档,在内存中构架代表整个DOM树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果XML文档特别大,就会消耗计算机的大量内存,严重情况下可能还会导致内存溢出。

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

通过继承DefaultHandler ,来开发一个sax解析器

 

 

Saxsax原理图.png

u 原理如果仅仅需要读取XML而不用CRUD,则可以直接用SAX,能力较弱,也只能读取一下,XML

u  

ax是一种推式的机制,你创建一个sax 解析器,解析器在发现xml文档中的内容时就告诉你(把事件推给你). 如何处理这些内容,由程序员自己决定。事件监听机制

在基于sax 的程序中,有五个最常用sax事件

startDocument() ----> 告诉你解析器发现了文档的开始,告诉你解析器开始扫描文档.

endDocument() ---> 告诉你解析器发现了文档尾

startElement()------>  告诉你解析器发现了一个起始标签,该事件告诉你元素的名称,该元素所有的属性名和值.

character() -----> 告诉你解析器发现了一些文本,将得到一个字符数组, 该数组的偏移量和一个长度变量,有这三个变量你可以得到解析器所发现的文本.

endElement()-----> 告诉你解析器发现了一个结束标签,该事件告诉你元素的名称

先由解析器,解析一个XML元素,然后根据它是什么样的元素,触发相应的事件。

u  sax具体案例

1.      编写一个xml测试文件

<?xmlversion="1.0"encoding="utf-8"?>

<班级>

    <学生>

       <名字>周星驰</名字>

       <年龄>23</年龄>

       <介绍>学习刻苦</介绍>

    </学生>

    <学生>

       <名字>林青霞</名字>

        <年龄>32</年龄>

       <介绍>是一个好学生</介绍>

    </学生>

</班级>

2.  开发sax解析程序(如果仅仅需要读取XML而不用CRUD,则可以直接用SAX

packagecn.itcast.sax;

importjava.io.File;

importjava.io.IOException;

import javax.xml.parsers.ParserConfigurationException;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

importorg.xml.sax.helpers.DefaultHandler;

publicclass Demo1 {

    /**sax去解析myClass.xml

     *@paramargs

     *@throwsSAXException

     *@throwsParserConfigurationException

     *@throwsException

     */

    publicstaticvoid main(String[] args)throwsParserConfigurationException, SAXException, Exception {

       //TODO Auto-generated method stub

       //得到SAXParserFactory

       SAXParserFactory  spf=SAXParserFactory.newInstance();

       //sax解析器

       SAXParserparser=spf.newSAXParser();

       //指定解析哪个xml文件,并把事件交给事件处理器

       parser.parse(new File("src/myClass.xml"),new MyHandler2());

    }

}

//需求,要求开发一个新的事件处理器,只显示学生名字和年龄

classMyHandler2extends DefaultHandler{

    privatebooleanisName=false;

    privatebooleanisAge=false;

    @Override

    publicvoid characters(char[] ch, int start,int length)

           throws SAXException {

       if(isName||isAge){

       //得到内容

       String con=new String(ch,start,length);

       System.out.println(con);

       }

       isName=false;

       isAge=false;

    }

    @Override

    publicvoid endDocument()throws SAXException {

       //TODO Auto-generated method stub

       super.endDocument();

    }

    @Override

    publicvoid endElement(String uri, String localName, Stringname)

           throws SAXException {

       //TODO Auto-generated method stub

       super.endElement(uri, localName, name);

    }

    @Override

    publicvoid startDocument()throws SAXException {

       //TODO Auto-generated method stub

       super.startDocument();

    }

    @Override

    publicvoid startElement(String uri, String localName, Stringname,

           Attributes attributes)throws SAXException {

       //TODO Auto-generated method stub

       if(name.equals("名字")){

           isName=true;

       }elseif(name.equals("年龄")){

           isAge=true;

       }

    }

}

//遍历整个myClass.xml

classMyHandler1extends DefaultHandler{

    //发现文档开始

    @Override

    publicvoid startDocument()throws SAXException {

       System.out.println("文档开始..");

       //TODO Auto-generated method stub

       super.startDocument();

    }

    //发现元素

    @Override

    publicvoid startElement(String uri, String localName, Stringname,

           Attributes attributes)throws SAXException {

       //TODO Auto-generated method stub

       System.out.println(name);

    }

    //发现文本 char[] ch表示你的xml文档.start表示发现的文本在xml中的开始位置,length :长度

    @Override

    publicvoid characters(char[] ch, int start,int length)

           throws SAXException {

       //TODO Auto-generated method stub

       String con=new String(ch,start,length);

       if(!con.trim().equals("")){

           System.out.println(con+" start: "+start+len="+length);

       }

    }

    //发现元素结束

    @Override

    publicvoid endElement(String uri, String localName, Stringname)

           throws SAXException {

       //TODO Auto-generated method stub

       super.endElement(uri, localName, name);

    }

    //发现文档结束

    @Override

    publicvoid endDocument()throws SAXException {

       //TODO Auto-generated method stub

       System.out.println("文档结束");

       super.endDocument();

    }

}

u  dom4j技术

1.      为什么有dom4j出现

为了解决DOM耗内存和SAX功能单一的问题,由jdom演化而来的DOM4J是一个两者的完美结合,它不属于任何一个的,也不是sun公司的,所以要导包。

dom4j 解决dom把整个文件加载到内存的问题,同时也可以对xml文件进行增加,删除,修改操作.

2.      在进行dom4j开发一定要导入dom4j-1.6.1.jar

3.      案例

写xml文件

<?xmlversion="1.0"encoding="utf-8"?>

<班级>

  <学生性别="">

    <名字>周星驰</名字> 

    <年龄>23</年龄> 

    <介绍>学习刻苦</介绍>

  </学生> 

  <学生性别="">

    <名字>林青霞</名字> 

    <年龄>32</年龄> 

    <介绍>是一个好学生</介绍>

  </学生> 

</班级>

 

 遍历xml文档.

//1遍历整个xml文件

    publicstaticvoid list(Element e){

      

       System.out.println(e.getName()+e.getText().trim());

       //遍历

       Iterator it=e.elementIterator();

      

       while(it.hasNext()){

           Element element=(Element) it.next();

           list(element);

       }

      

    }

//读取某个xml标签

//1.读取xml的某个标签内容(比如,读取第一个学生的名字)

    publicstaticvoid read(Document doc){

      

       Element stu=doc.getRootElement().element("名字");//->xpath

       Element name=stu.element("名字");

       System.out.println(stu.getText());

      

    }

//读取标签属性

//2.读取xml标签的某个属性的值(比如,读取第二个学生的性别)

    publicstaticvoid readAttriube(Document doc){

       //得到第二个学生

       Element student=(Element)doc.getRootElement().elements("学生").get(0);

       //取名字

       String val=student.attributeValue("性别");

       System.out.println(val);

    }

//添加标签

在使用dom4j进行添加的时候,会出现乱码.

把硬盘上的文件存到内存上以UTF-8的形式存储,然后在内存它就以UTF-8的编码形式存在,

当我们通过流或者其它方式再次写到硬盘上时间,又用了其它编码形式,它是把用内存中UTF-8的编码,然后根据码表转换成GB2312等其它编码,这就是它乱码的根本原因,所以我们可以用流在写出的时间,指定编码方式。

 

//3.添加xml标签(加入一个学生)

    publicstaticvoid add(Document doc)throwsIOException{

      

       //1.创建一个元素

       Element e=DocumentHelper.createElement("学生");

       //e.setText("贾宝玉");

       //在学生标签下,加入名字

       Element name=DocumentHelper.createElement("名字");

       name.setText("小龙女");

       e.add(name);

       //2.挂到根元素下

       doc.getRootElement().add(e);

      

       //3.更新文档.

      

       OutputFormat output=OutputFormat.createPrettyPrint();

       output.setEncoding("utf-8");

       //分析

      

       //XMLWriter writer=new XMLWriter(newFileWriter("src/myClass.xml"),output);

       //一种解决乱码的方法

       /*XMLWriter writer=new XMLWriter(

              new OutputStreamWriter(newFileOutputStream(new File("src/myClass.xml")),"utf-8"),

              output);*/

       //第二种方法解决乱码

       XMLWriter writer=new XMLWriter(new FileOutputStream(new File("src/myClass.xml")),output);

       writer.write(doc);

       writer.close();

      

    }

//添加属性的操作

//4.添加属性

    publicstaticvoid addAttribute(Document doc)throwsException, FileNotFoundException{

       Element e=doc.getRootElement().element("学生").element("名字");

       //e.setAttributeValue("小名", "星星");

       Attribute att=DocumentHelper.createAttribute(e,"小名2","星星2");

       e.add(att);      

       //更新文档.

       DocumentTools.updateDocument(doc);

    }

//删除xml某个标签

//删除xml文件的一般标签

    publicstaticvoid del(Documentdoc)throws Exception{

       //得到标签对应的节点对象

       Element e=(Element)doc.getRootElement().elements("学生").get(1);

       //通过父节点去删除

       e.getParent().remove(e);

       //更新

       DocumentTools.updateDocument(doc);

    }

//删除某个标签的属性

//删除一个属性

    publicstaticvoid delAttribute(Document doc)throwsException{

       //得到标签对应的节点对象

       Elementname=doc.getRootElement().element("学生").element("名字");

       //得到属性节点对象

      name.remove(name.attribute("小名2"));

       //更新

      DocumentTools.updateDocument(doc);

    }

//修改标签的内容

//更新xml标签内容(把所有学生的年龄*2)

    publicstaticvoid update(Document doc)throwsException{

       List<Element>list=doc.getRootElement().elements("学生");

       for(Element e: list){

           Element age=e.element("年龄");

           String result=Integer.parseInt(age.getText())*2+"";

           age.setText(result);

       }

       DocumentTools.updateDocument(doc);

    }

//修改标签的属性

//更新xml标签的属性(把所有学生生的小名改成小舟)

    publicstaticvoid updateAttribute(Document doc)throws Exception{

       List<Element>list=doc.getRootElement().elements("学生");

       for(Element e: list){

           //如果属性值存在,则更新它,如果不存在则添加.

           e.element("名字").addAttribute("小名e","小舟");

       }

       DocumentTools.updateDocument(doc);

    }

 

xpath-为什么需要?

我们前面的dom4j中一个案例得到学生的名字要一层一层的得到,非常麻烦

解决方案-xpath

要导入jar包:

dom4j重要方法 selectSingleNode

selectNodes 该方法可以在document和元素使用.

自学文档。Xpath在作用时间,看文档。

Dom4j+Xpath十分强大

 

 

 

 

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

XML Schema VS DTD

•    XML Schema符合XML语法结构。

•    DOMSAXXML API很容易解析出XML Schema文档中的内容。

•    XML Schema名称空间支持得非常好。

•    XML SchemaXML DTD支持更多的数据类型,并支持用户自定义新的数据类型。

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

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

 

快速入门:

XML Schema 文件自身就是一个XML文件,但它的扩展名通常为.xsd

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

XML文件一样,一个XML Schema文档也必须有一个根结点,但这个根结点的名称为Schema

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

 

schema的原理图

:

xsd文件

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.itcast.cn" elementFormDefault="qualified">

       <xs:element name="班级">

              <xs:complexType>

                     <xs:sequence maxOccurs="unbounded">

                           <xs:element name="学生">

                                  <xs:complexType>

                                         <xs:sequence>

                                                <xs:element name="名字" type="xs:string"/>

                                                <xs:element name="年龄" type="xs:integer"/>

                                                <xs:element name="介绍" type="xs:string"/>

                                                <xs:element name="生日" type="xs:date" maxOccurs="1"/>

                                         </xs:sequence>

                                         <xs:attribute name="sex">

                                                <xs:simpleType>

                                                       <xs:restriction base="xs:string">

                                                              <xs:enumeration value="man"/>

                                                              <xs:enumeration value="woman"/>

                                                       </xs:restriction>

                                                </xs:simpleType>

                                         </xs:attribute>

                                   </xs:complexType>

                           </xs:element>

                     </xs:sequence>

              </xs:complexType>

       </xs:element>

</xs:schema>

该文件对应的xml文件

<?xml version="1.0" encoding="UTF-8"?>

<班级 xmlns="http://www.itcast.cn"

                     :xsi="http://www.w3.org/2001/XMLSchema-instance"

                     :schemaLocation="http://www.itcast.cnmyClass.xsd">

       <学生 sex="woman">

              <名字>周星驰</名字>

              <年龄>12</年龄>

              <介绍>学习很刻苦</介绍>

              <生日>1980-12-11</生日>

       </学生>

</班级>

 

还有一组:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.itcast2.cn" elementFormDefault="qualified">

       <xs:element name="shiporder">

              <xs:complexType>

                     <xs:sequence>

                           <xs:element name="orderperson" type="xs:string"/>

                           <xs:element name="shipto">

                                  <xs:complexType>

                                         <xs:sequence>

                                                 <xs:element name="name" type="xs:string"/>

                                                <xs:element name="address" type="xs:string"/>

                                                <xs:element name="city" type="xs:string"/>

                                                <xs:element name="country" type="xs:string"/>

                                         </xs:sequence>

                                  </xs:complexType>

                           </xs:element>

                           <xs:element name="item" maxOccurs="unbounded">

                                  <xs:complexType>

                                         <xs:sequence>

                                                <xs:element name="title" type="xs:string"/>

                                                <xs:element name="note" type="xs:string" minOccurs="0"/>

                                                <xs:element name="quantity" type="xs:positiveInteger"/>

                                                <xs:element name="price" type="xs:decimal"/>

                                         </xs:sequence>

                                  </xs:complexType>

                           </xs:element>

                     </xs:sequence>

                     <xs:attribute name="orderid" type="xs:string" use="required"/>

              </xs:complexType>

       </xs:element>

</xs:schema>

 

对应的xml文件:

<?xml version="1.0" encoding="UTF-8"?>

<shiporderxmlns="http://www.itcast2.cn"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.itcast2.cn:\shiporder.xsd"orderid="">

       <orderperson>aaa</orderperson>

       <shipto>

              <name>北京</name>

              <address>海淀</address>

              <city>不知道</city>

              <country>中国</country>

       </shipto>

       <item>

              <title>汽车</title>

              <quantity>3</quantity>

              <price>1234.5</price>

       </item>

</shiporder>

 

 

 

 

 

 

 

原创粉丝点击