Xml

1.XML基础

  一:作用

    作为软件配置文件;作为小型的数据库

  二:语法

    标签:标签名不能以数字开头,中间不能有空格,区分大小写,有且只有一个根标签

    属性:可以有多个属性,属性值必须用引号(单双都可以但不可以单双混用)

       文档声明:<?xml version="1.0" encoding="utf-8">

          encoding="utf-8": 打开或解析xml文档时的编码

          注意:保存xml文档时的编码 和 解析xml文档时的编码要保持一致,才能避免中文乱码问题!

  三:XML 解析

    程序读取或者操作xml文档

    解析方式:DOM解析 vs SAX解析

    (一)DOM解析:   

       DOM解析原理:一次性把xml文档加载成Document树,通过Document对象得到节点对象,通过节点对象访问xml文档内容(标签,属性,文本,注释)。

       使用工具:Dom4j工具    

       使用语法:

          a.读取xml文档

           Document doc = new SAXReader().read("xml文件");

             节点:nodeIterator:所有节点;

             标签:element("名字")指定名称的第一个子标签

              elementIterator("名称");  指定名称的所有子标签对象

              elements();  所有子标签对象

           属性:

              attributeValue("名称")指定名称的属性值

              attribute("名称")指定名称的属性对象

              getName() 属性名称

              getValue() 属性值

              atributeIterator()   所有属性对象(Iterator)

              attributes() 所有属性对象(List)

           文本:

              getText()  得到当前标签的文本

              elementText("子标签名称") 得到子标签的文本

          b.写Xml文档

            XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)

              wirter.write(Document);

          c.修改Xml文档的API

            增加:DocumentHelper.createDocument() 增加文档

               addElement("名称") 增加标签

               addAttribute("名称",“值”) 增加属性

            修改:Attribute.setValue("值") 修改属性值

               Element.addAtribute("同名的属性名","值") 修改同名的属性值

               Element.setText("内容") 修改文本内容

            删除:Element.detach(); 删除标签

               Attribute.detach();  删除属性

例子:

/**
 *  课堂练习: 
 * 1.使用dom4j的api来生成以下的xml文件
<Students>
<Student id="1">
    <name>张三</name>
    <gender>男</gender>
    <grade>计算机1班</grade>
    <address>广州天河</address>
</Student>
<Student id="2">
    <name>李四</name>
    <gender>女</gender>
    <grade>计算机2班</grade>
    <address>广州越秀</address>
</Student>
</Students>

2.修改id为2的学生的姓名,改为“王丽”

3.删除id为2的学生
 * @author APPle
 *
 */
public class Demo2 {

    public static void main(String[] args) throws IOException, Exception {
        // TODO Auto-generated method stub
        //第一题
        /*Document doc=DocumentHelper.createDocument();
        Element root=doc.addElement("Students");
        Element e1=root.addElement("Student");
        Element e11=e1.addElement("name");
        Element e12=e1.addElement("gender");
        Element e13=e1.addElement("grade");
        Element e14=e1.addElement("address");
        e1.addAttribute("id", "1");
        e11.setText("张三");
        e12.setText("男");
        e13.setText("计算机1班");
        e14.setText("广州天河");
        
        Element e2=root.addElement("Student");
        Element e21=e2.addElement("name");
        Element e22=e2.addElement("gender");
        Element e23=e2.addElement("grade");
        Element e24=e2.addElement("address");
        e2.addAttribute("id", "2");
        e21.setText("李四");
        e22.setText("女");
        e23.setText("计算机2班");
        e24.setText("广州越秀");
        
        XMLWriter writer=new XMLWriter(new FileOutputStream(new File("e:/b.xml")));
        writer.write(doc);*/
        
        //第二题
        Document doc1=new SAXReader().read(new File("e/b.xml"));
        Element ele1=doc1.getRootElement();
        @SuppressWarnings("unchecked")
        Iterator<Element> it=ele1.elementIterator();
        while(it.hasNext()){
            Element e=it.next();
            if(e.attributeValue("id").equals("2")){
                e.element("name").setText("王丽");
            }
        }
        XMLWriter writer1=new XMLWriter(new FileOutputStream(new File("e:/bb.xml")));
        // 设置编码
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("utf-8");
        writer1.write(doc1);
        
    }

}
View Code

    (二)xPath技术

         a.出现的原因:当使用dom4j查询比较深层次结构的节点(标签属性文本)比较麻烦!就出现这个能快速定位到xml中的具体位置

         b.作用:快速获取所需节点对象

         c.使用:1.导入xPath支持的jar包:jaxen-1.1-beta-6.jar

             2.使用方法:List<Node> selectNodes("xpath表达式");查询多个节点对象

                   Node selectSingleNode("xpath表达式");查询一个节点对象

         d.语法:

            / 绝对路径 表示从xml的根位置开始或子元素(一个层次结构)

            // 相对路径 表示不分任何层次结构的选择元素。

            * 通配符 表示匹配所有元素

            [] 条件 表示选择什么条件下的元素

            @ 属性 表示选择属性节点

            and 关系 表示条件的与关系(等价于&&)

            text() 文本 表示选择文本内容

例子:

/**
     * 删除id=002的学生标签
     * @param doc 
     * @param id
     * @throws IOException 
     * @throws Exception 
     */
    public static void deleById() throws IOException, Exception{
        Document doc=new SAXReader().read(new File("./src/XML/contact.xml"));
        //1.查询id为2的学生标签
        //使用xpath技术
        Element ee=(Element)doc.selectSingleNode("//contact[@id='002']");
        //删除标签
        ee.detach();
        //写回去
        FileOutputStream fos=new FileOutputStream("./src/XML/contact.xml");
        @SuppressWarnings("static-access")
        OutputFormat format=new OutputFormat().createPrettyPrint();
        format.setEncoding("utf-8");
        XMLWriter writer=new XMLWriter(fos,format);
        writer.write(doc);
        writer.close();
    }
    /**
     * 表达式语法
     * 
     */
    public static void test() throws Exception{
        Document doc = new SAXReader().read(new File("./src/contact.xml"));
        String xpath = "";
        /**
         * 1.      /      绝对路径      表示从xml的根位置开始或子元素(一个层次结构)
         */
        xpath = "/contactList";
        xpath = "/contactList/contact";
        
        /**
         * 2. //     相对路径       表示不分任何层次结构的选择元素。
         */
        xpath = "//contact/name";
        xpath = "//name";
        
        /**
         * 3. *      通配符         表示匹配所有元素
         */
        xpath = "/contactList/*"; //根标签contactList下的所有子标签
        xpath = "/contactList//*";//根标签contactList下的所有标签(不分层次结构)
        /**
         * 4. []      条件           表示选择什么条件下的元素
         */
        //带有id属性的contact标签
        xpath = "//contact[@id]";
        //第二个的contact标签
        xpath = "//contact[2]";
        //选择最后一个contact标签
        xpath = "//contact[last()]";

        /**
         * 5. @     属性            表示选择属性节点
         */
        xpath = "//@id"; //选择id属性节点对象,返回的是Attribute对象
        xpath = "//contact[not(@id)]";//选择不包含id属性的contact标签节点
        xpath = "//contact[@id='002']";//选择id属性值为002的contact标签
        xpath = "//contact[@id='001' and @name='eric']";//选择id属性值为001,且name属性为eric的contact标签
        
        /**
         *6.  text()   表示选择文本内容
         */
        //选择name标签下的文本内容,返回Text对象
        xpath = "//name/text()";
        xpath = "//contact/name[text()='张三']";//选择姓名为张三的name标签
        
        @SuppressWarnings("unchecked")
        List<Node> list = doc.selectNodes(xpath);
        for (Node node : list) {
            System.out.println(node);
        }
    }
    /**
     * 模拟用户登录
     * @throws IOException 
     * @throws Exception 
     */
    public static void denglu() throws IOException, Exception{
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入用户名:");
        String name = reader.readLine();
        System.out.println("请输入密码:");
        String password = reader.readLine();
        
        //之后再Xml文档中查找是否有
        Document doc=new SAXReader().read(new File("./src/XML/user.xml"));
        Element user=(Element) doc.selectSingleNode("//user[@name='"+name+"' and @password='"+password+"']");
        if(user!=null){
            System.out.println("登录成功");
        }else{
            System.out.println("登录失败");
        }
    }
    /**
     * 读取Html文件
     * 练习:读取联系人的所有信息
     * 按照以下格式输出:
     *          编号:001 姓名:张三 性别:男 年龄:18 地址:xxxx 电话: xxxx
     *       编号:002 姓名:李四 性别:女 年龄:20 地址:xxxx 电话: xxxx
     *       ......
     */
    public static void readHtml() throws Exception{
        Document doc=new SAXReader().read(new File("./src/XML/persionList.html"));
        //读取所有tbody中的tr标签
        @SuppressWarnings("unchecked")
        List<Element> list=(List<Element>)doc.selectNodes("//tbody/tr");
        //2.遍历
                for (Element elem : list) {
                    //编号
                    //String id = ((Element)elem.elements().get(0)).getText();
                    String id = elem.selectSingleNode("td[1]").getText();
                    //姓名
                    String name = ((Element)elem.elements().get(1)).getText();
                    //性别
                    String gender = ((Element)elem.elements().get(2)).getText();
                    //年龄
                    String age = ((Element)elem.elements().get(3)).getText();
                    //地址
                    String address = ((Element)elem.elements().get(4)).getText();
                    //电话
                    String phone = ((Element)elem.elements().get(5)).getText();
                    
                    System.out.println("编号:"+id+"\t姓名:"+name+"\t性别:"+
                                        gender+"\t年龄:"+
                                        age+"\t地址:"+address+
                                        "\t电话:"+phone);
                }
    }
View Code

    (三)SAX解析

      a.出现原因:因为DOM解析会一次将xml文档加载到内存中去,然后内存中的构建Document树,这样对内存要求比较高,不适合读取大容量的xml文件,容易导致内存溢出

      b.解析原理:加载一点,读取一点,处理一点,对内存要求比较低

      c.解析工具:内置再jdk中的org.xml.sax.*(Sun公司提供)

      d.核心API:SAXParser类:用于读取和解析xml文件对象

           parse(File f, DefaultHandler dh)方法: 解析xml文件

              DefaultHandler: SAX事件处理程序。使用DefaultHandler的子类

      d.如何使用:

        1.创建SAXParser对象

          SAXParser parser=SAXParserFactory.newInstance().newSAXParser();

        2.调用parse方法

          parser.parse(new File("./src/contact.xml"), new MyDefaultHandler());}

           MyDefaultHandler()是DefaultHandler子类需要对这个重写方法达到操作xml文件的目的

        3.重写DefaultHandler子类

          void startDocument() : 在读到文档开始时调用

          void endDocument() :在读到文档结束时调用

          void startElement(String uri, String localName, String qName, Attributes attributes) :读到开始标签时调用

          void endElement(String uri, String localName, String qName) :读到结束标签时调用

          void characters(char[] ch, int start, int length) : 读到文本内容时调用

 例子:

主函数

public class SAX1 {

    public static void main(String[] args) throws Exception, SAXException {
        //创建SAXParser对象
        SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
        //调用parse方法
        MyDefaultHandler2 handler=new MyDefaultHandler2();
        parser.parse(new File("./src/XML/contact.xml"),handler );
        String content=handler.getContent();
        System.out.println(content);
    }
}
View Code

重写的DefaultHandler1子类

public class MyDefaultHandler2 extends DefaultHandler{
    //存储xml文档信息
    private StringBuffer sb=new StringBuffer();
    //获取xml信息
    public String getContent(){
        return sb.toString();
    }
    /**
     * 开始标签时调用
     * @param qName: 表示开始标签的标签名
     * @param attributes: 表示开始标签内包含的属性列表
     */
    @Override
    public void startElement (String uri, String localName,
            String qName, Attributes attributes)
                    throws SAXException
    {
        sb.append("<"+qName);
        if(attributes!=null){
            for(int i=0;i<attributes.getLength();i++){
                //获得属性名
                String attrName=attributes.getQName(i);
                //获得属性值
                String attrValue=attributes.getValue(i);
                sb.append(" "+attrName+"=\""+attrValue+"\"");
            }
        }
        sb.append(">")    ;

    }
    /**
     * 结束标签时调用
     * @param qName: 结束标签的标签名称
     */
    @Override
     public void endElement (String uri, String localName, String qName)
                throws SAXException
     {
        sb.append("</"+qName+">");
     }
    /**
     * 读到文本内容的时调用
     * @param ch: 表示当前读完的所有文本内容
     * @param start: 表示当前文本内容的开始位置
     * @param length: 表示当前文本内容的长度
     * char[](                                       张三              20)   100
     *                              98 2   
     */ 
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        //得到当前文本内容
        String content = new String(ch,start,length);
        sb.append(content);
    }
    /**
     * 结束文档时调用
     */
    @Override
    public void endDocument() throws SAXException {
    }
    
}
View Code

重写DefaultHandler1子类

public class MyDefaultHandler extends DefaultHandler{
    /**
     * 开始文档时调用
     */
    @Override
    public void startDocument()throws SAXException {
        System.out.println("MyDefaultHandler.startDocument()");
    }
    /**
     * 开始标签时调用
     * @param qName: 表示开始标签的标签名
     * @param attributes: 表示开始标签内包含的属性列表
     */
    @Override
    public void startElement (String uri, String localName,
            String qName, Attributes attributes)
                    throws SAXException
    {
        System.out.println("MyDefaultHandler.startElement()-->"+qName);
    }
    /**
     * 结束标签时调用
     * @param qName: 结束标签的标签名称
     */
    @Override
     public void endElement (String uri, String localName, String qName)
                throws SAXException
     {
        System.out.println("MyDefaultHandler.endElement()-->"+qName);
     }
    /**
     * 读到文本内容的时调用
     * @param ch: 表示当前读完的所有文本内容
     * @param start: 表示当前文本内容的开始位置
     * @param length: 表示当前文本内容的长度
     * char[](                                       张三              20)   100
     *                              98 2   
     */ 
    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        //得到当前文本内容
        String content = new String(ch,start,length);
        System.out.println("MyDefaultHandler.characters()-->"+content);
    }
    /**
     * 结束文档时调用
     */
    @Override
    public void endDocument() throws SAXException {
        System.out.println("MyDefaultHandler.endDocument()");
    }
    
}
View Code

 

    (四)DOM vs SAX解析

DOM解析

SAX解析

原理: 一次性加载xml文档,不适合大容量的文件读取

原理: 加载一点,读取一点,处理一点。适合大容量文件的读取

DOM解析可以任意进行增删改成

SAX解析只能读取

DOM解析任意读取任何位置的数据,甚至往回读

SAX解析只能从上往下,按顺序读取,不能往回读

DOM解析面向对象的编程方法(NodeElementAttribute,Java开发者编码比较简单。

SAX解析基于事件的编程方法。java开发编码相对复杂。

2.XML约束

  一:约束技术:  

    DTD约束:语法相对简单,功能也相对简单。学习成本也低。

    Schema约束:语法相对复杂,功能也相对强大。学习成本相对高!!!(名称空间)

  二:DTD约束:

      导入:内部导入;外部导入

        外部导入:本地文件系统;<!DOCTYPE note SYSTEM "note.dtd">

             公共的外部导入:<!DOCTYPE 根元素 PUBLIC "http:........">

      语法:

        约束标签:<!ELEMENT 元素名称 类别> 或 <!ELEMENT 元素名称 (元素内容)>

            类别:EMPTY:空标签;(#PCDATA)表示元素一定是普通字符(不能包含子标签);ANY:表示元素任意字符(可以包含子标签)

            元素内容:  

                顺序问题:<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)> 按顺序出现子标签

                次序问题:空:1次;+:至少1次;*:0~n次;?0~1次

        约束属性:<!ATTLIST 元素名称 属性名称 属性类型 默认值>

            默认类型:控制属性值的

 

                CDATA :表示普通字符串

 

                (en1|en2|..) 表示一定是任选其中的一个值

 

                ID:表示在一个xml文档中该属性值必须唯一。值不能以数字开头

            默认值:#REQUIRED 属性值是必需的

 

                #IMPLIED   属性不是必需的

 

                #FIXED value 属性不是必须的,但属性值是固定的

例子:

 

  <!ELEMENT note (from?,to+,heading*,body+)>
  <!ELEMENT to      EMPTY>
  <!ELEMENT from    (#PCDATA)>
  <!ELEMENT heading (#PCDATA)>
  <!ELEMENT body    (#PCDATA)>
  <!ATTLIST to id ID #REQUIRED>
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
  <from></from>
  <to id="a1"></to>
  <to id="a2"></to>
  <to id="a3"></to>
  <heading>Reminder</heading>
  <heading>Reminder</heading>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend</body>
  <body>Don't forget me this weekend</body>
  <body>Don't forget me this weekend</body>
</note>
View Code

  三:Schema约束

   (一)使用它的原因

      a.支持数据类型b.是DTD的替代c.是用xml来编写之后处理Schema变得更加方便d.可保护数据通信e.可扩展

 

  (二)名称空间:告诉xml文档的哪个元素被哪个schema文档约束 在一个xml文档中,不同的标签可以受到不同的schema文档的约束。

       1)一个名称空间受到schema文档约束的情况

       2)多个名称空间受到多个schema文档约束的情况

       3)默认名称空间的情况

       4)没有名称空间的情况

  (三)使用方法

      http://www.w3school.com.cn/schema/schema_howto.asp

  (四)例子

<?xml version="1.0" encoding="UTF-8"?>
<itcast:书架 xmlns:itcast="http://www.itcast.cn"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.itcast.cn book.xsd">
    <itcast:>
        <itcast:书名>JavaScript网页开发</itcast:书名>
        <itcast:作者>张孝祥</itcast:作者>
        <itcast:售价>28</itcast:售价>
    </itcast:书>

</itcast:书架>
View Code
<?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:string' />
                            <xs:element name='售价' type='xs:integer' />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>
View Code

  (五)注意:

    对Schema的编写我们可在eclipse中编写调到设计模式编写更方便

 

 

 

              

 

posted @ 2017-04-24 15:36  王吉平  阅读(312)  评论(0编辑  收藏  举报