标记语言概述


标记语言,是一种将文本(Text)以及文本相关的其他信息结合起来,展现出关于文档结构和数据处理细节的电脑文字编码。一部分是标记,一部分是标记中的内容,两部分构成标记语言   <标记>..内容..</>格式.

当今广泛使用的标记语言是超文本标记语言,可扩展标记语言标记语言广泛应用于网页和网络应用程序。

1. 超文本标记语言HTML(Hyper Text Markup Language)

    Html是标记语言的一种,是典型的标记语言。标记用来对内容进行定义和修饰,内容是数据的本质。普通的标记语言–>Html中用到的所有标记都是事先制定好的,自己不能增加标记定义,只能用已经定义好的标记。 (如 <a></a>表示超链接)

2. 可扩展的标记语言XML(eXtensible Markup Language)

    可扩展的标记语言–>可以自己定义标记并赋予意义。

     XML的作用:用于数据存储和数据描述

    使用场景        

    a、利用xml充当配置文件

    b、用于不同系统间的数据交换(XML可使用不同系统和平台)

    c、利用XML存储一些少量数据(大量数据需要使用数据库)

3. Xml和Html语言由同一种父语言SGML(Standard Generalized Markup Language,标准通用标记语言)发展出来的两种语言。

4. 解析器  解析器(比如:XML SPY与用于解析XML文件) ,浏览器 ,MyEclipse

5. W3C(World Wide Web Consortium)

  W3C: 开源的语言协会,万维网联盟(World Wide Web Consortium)

    HTML和XML都是W3C制定的语言规则

    官网:www.w3.org

    学习网站:http://www.w3school.com.cn/

XML语法规则


XML文件扩展名为.xml;XML文件由第一行指令和元素构成

指令

XML声明,负责指定xml文件的编码和xml版本。写在XML的第一行<?xml version=”1.0″ encoding=”UTF-8″?> 不要修改。version:语法的版本号  encoding:文字的编码,能写中文

元素(Element

元素由标记和其中的内容组成  <标记名称>内容</标记名称>

1. 根元素       最外层的元素叫根元素 ,一个XML文件有且只有一个根元素

2. 叶子元素    最里层的(没有子元素的)元素叫叶子元素

3. 空元素       没有内容的元素叫空元素,比如<a></a>,可以简写为:<a /> 。有标记,没内容

4. 普通元素    标记+内容+结束标记

5. 元素必须遵循的语法规则

   1)所有的标记都必须有结束  2)开始标记和结束标记必须成对出现  3)元素必须正确嵌套<a><b>c</b></a> (正确) <a><b>c</a></b> (错误)  4)标记的大小写敏感 Hello 和 hello不是同一个标记  5有且只能有一个根元素

标记

标记名字可以随意指定,可以用中文也可以用英文

1. 标记包括开始标记和结束标记  2. 开始标记和结束标记必须成对出现,所有的标记都必须有结束  3. 标记的大小写敏感

注释

格式:<!– 注释的内容–>  编译器将忽略注释  Html和XML注释方式相同

属性(定义在开始标记中的键值对)

1. 格式:属性=”属性值”

2. 要求:属性必须有值,属性值必须用引号引起来,单引号或双引号都可以,但必须一致

3. 属性是隶属于某个元素,<标记名称 属性名=“属性值”>内容</标记内容>,属性可以写多个,属性名不能重复

实体引用(转义字符)

如果元素内容遇到下面几种特殊字符,可以使用实体替代

小于号(<): less than –> &lt ;

大于号(>): great than –> &gt ;

And符号(&): &amp;

双引号(“): &quot;

单引号(‘): &apos;

注意这些转义字符都是以&开头,以;结尾的 。<,&字符必须用实体,其他几个建议使用

文本域

格式: < ! [ CDATA [ 文本内容 ] ] >  文本域中的实体引用都被忽略,所有内容被当成一整块文本数据对待

<![CDATA[
    一本好书,没<<笑傲江湖>>好看,比<<Thinking in java>>好看
]]> 

规则小结

1) 必须有唯一的根元素

2) xml标记大小写敏感

3) 标记必须配对出现,有开始有结束

4) 元素必须被正确嵌套

5) 属性必须有值,值必须用引号引括起来

6) 如果遵循所有的规则,称作格式良好的xml文件(well-formed)

使用XML文件描述数据的例子

1. 早期属性文件描述数据的方式

  url = jdbc:oracle:thin@192.168.0.26:1521:tarena

   dbUser = openlab

   dbPwd = open123

2. 现在使用xml表示方式

   <datasource id=”db_oracle”>

     <property name=”url”>jdbc:thin@192.168.0.26:1521:tarena</property>

     <property name=”dbUser”>openlab</property>

     <property name=”dbPwd”>open123</property>

    </datasource>

DTD(文档类型定义Document Type Difinition /Schema


DTD和Schema都是用于限定XML格式的技术。可以限制XML使用那些标记,标记出现顺序,标记嵌套关系,有哪些属性等。有效的xml文件 = 格式良好的xml文件 + 有DTD或Schema规则 + 遵循DTD或Schema的规则

DTD/Schema的由来

行业交换数据时要求xml文件格式相同,所以需要大家遵守规范的xml文件格式。

A学校的XML文件中

<计算机书籍>
  <书名 isbn="1234">XML的前世今生</书名>
  <价格>65</价格>
  <简介>一本好书</简介>
  <作者>李毅</作者>
</计算机书籍>

B学校的XML文件中

<Computer_book>
    <isbn>1234</isbn>
    <bookname author="李毅">XML的前世今生</bookname>
    <price>65</price>
    <brief>一本好书</brief>
</Computer_book>

这两个文件数据相同,但结构不同,无法交换数据

DTD技术

Document Type Definition文本类型定义,可以定义一个XML标记,出现顺序等规则。

1. 定义元素和标记

<!ELEMENT 标记名 (子标记名或#PCDATA)>

定义dept标记,该标记内部可以使用dname和loc子元素

<!ELEMENT dept (dname,loc)>

定义dname标记,该标记只能包含文本内容

<!ELEMENT dname (#PCDATA)>

定义dept标记,该标记内部只能用dname或loc之一

<!ELEMENT dept (dname | loc)>

定义一个loc空元素

<!ELEMENT loc EMPTY>

2. 元素出现次数的定义

    *允许出现0到多次. <!ELEMENT depts (dept*)>

    +允许出现1到多次.

    ?允许出现0次或1次

定义package元素,里面可以出现0到多次的interceptors和action,但action必须在interceptors之后

<!ELEMENT package (interceptors*,action*)>

3. 定义属性

<!ATTLIST 标记名 属性 CDATA 默认值>

4. DTD使用方法

在需要限定的XML中,利用下面指定引入。SYSTEM:个人或小范围应用,PUBLIC:某个组织或国际社团使用。浏览器显示的时候,DTD内容不显示

<!DOCTYPE 根元素名  SYSTEM|PUBLIC "dtd文件位置">

5.案例

dept.dtd文件内容    

<!ELEMENT DEPTS (DEPT)*>
<!ELEMENT DEPT (DNAME,LOC)>
<!ELEMENT DNAME (#PCDATA)>
<!ELEMENT LOC (#PCDATA)>
<!ATTLIST DEPT DEPTNO CDATA #REQUIRED>

dept.xml文件内容

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE DEPTS SYSTEM "depts.dtd">
<DEPTS>
  <DEPT DEPTNO="10">     <DNAME>ACCOUNTING</DNAME>     <LOC>NEW YORK</LOC>   </DEPT>   <DEPT DEPTNO="20">     <DNAME>RESEARCH</DNAME>     <LOC>DALLAS</LOC>   </DEPT>
  <DEPT DEPTNO="30">     <DNAME>SALES</DNAME>     <LOC>CHICAGO</LOC>   </DEPT> </DEPTS>

mybatis的xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xxx.xx">
     ...
</mapper>

Schema技术

Schema技术可以实现DTD的定义功能。一个xml只能引用一个DTD,如果引入多个DTD遇到相同标记时会产生混淆。而Schema在引入时需要指定命名空间名,可以通过命名空间名区分。

Java API解析XML文件


Java和xml有很多共同点(比如跨平台、不厂商无关),目前为止java对xml的解析较其他语言更完善

两种解析方式

1. DOM(Document Object Model 文档对象模型)

关键字:树(Document)

优点: 把xml文件在内存中构造树形结构,可以遍历和修改节点

缺点: 如果文件比较大,内存有压力,解析的时间会比较长

2. SAX(Simple API for Xml 基于XML的简单API)

关键字:流(Stream)

把xml文件作为输入流,触发标记开始,内容开始,标记结束等动作

优点: 解析可以立即开始,速度快,没有内存压力

缺点: 不能对节点做修改

JDOM / DOM4J

目前市场上常用的2种解析XML文件的API。dom4j-1.6.1.jar 结合了DOM和SAX两种解析方式的优点

dom4j工具使用步骤

a、引入dom4j.jar开发包

b、利用dom4j提供的API

    Document对象:文档树对象

    doc.getRootElement()获取树根节点元素

    elements(“标记名”):获取子节点元素(复数)

    element(“标记名”):获取子节点元素(单数)

    getText():获取节点的文本值

    attributeValue(“属性名”):获取属性值

    setText(val):修改节点文本值

    remove(子节点):删除子节点元素

    setAttributeValue(“属性名”,”属性值”):修改属性值

    addAttributeValue()添加属性值

案例

第一步:引入jar包,pom配置

<!-- dom4j -->
<dependency>  
    <groupId>dom4j</groupId>  
    <artifactId>dom4j</artifactId>  
    <version>1.6.1</version>  
</dependency> 

第二步:util工具类

标记语言XML-风君雪科技博客

package com.org.qin.common.xml;
public class Book {
    private String id;
    private String name;
    private String author;
    private String price;

    @Override
    public String toString() {
        return this.id + ":" + this.name + ":" + this.author + ":" + this.price;
    }
}
package com.org.qin.common.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
public class XmlUtil {
    /**
     * 生成xml文件
     * 
     * @param xmlFile
     * @param bookList
     * @throws Exception
     */
    public static void toXMLFlie(String file, List<Book> bookList) throws Exception {

        Document doc = DocumentHelper.createDocument(); // 创建一个空白的XML文档
        Element root = doc.addElement("book-list"); // 添加一个元素,返回值是刚刚添加的元素

        for(Book book : bookList){
            Element bookElement = root.addElement("book");
            bookElement.addElement("id").setText(book.getId());
            bookElement.addElement("name").setText(book.getName());
            bookElement.addElement("author").setText(book.getAuthor());
            bookElement.addElement("price").setText(book.getPrice());
        }

        /**
         * 这个XML文档存储在内存里, 把XML文档写到文件里,xmlFile
         * OutputFormat:输出格式
         * OutputFormat.createCompactFormat:默认的,紧凑格式,好
         * OutputFormat.createPrettyPrint:常写的格式,传入很多空格字符,不好
         */
        OutputFormat format = OutputFormat.createPrettyPrint();
        XMLWriter writer = new XMLWriter(new FileWriter(file), format);
        writer.write(doc);
        writer.close();
    }

    /**
     * 读取xml文件,生成list对象。注意:写这个程序的一定知道XML文档的结构
     * 
     * @param xmlFile
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public static List<Book> parseXmlToBookList(String xmlFile) throws Exception {

        SAXReader reader = new SAXReader(); // 用于读取XML文档SAXReader
        Document doc = reader.read(new File(xmlFile)); // Document 用于封装解析后的XML数据
        Element root = doc.getRootElement(); // 得到根元素,Element用于封装元素
        List<Element> bookElements = root.elements("book");// 返回根元素下名为book的所有节点

        List<Book> bookList = new ArrayList<Book>();
        for(Element ele : bookElements){
            Book book = new Book();
            book.setId(ele.element("id").getText());
            book.setName(ele.element("name").getText());
            book.setAuthor(ele.element("author").getText());
            book.setPrice(ele.element("price").getText());
            bookList.add(book);
        }
        return bookList;
    }

    /**
     * 修改xml文件内容
     * 
     * @param xmlFile
     */
    @SuppressWarnings("unchecked")
    public static void updateXmlText(String xmlFile) throws Exception {
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File(xmlFile));
        Element root = doc.getRootElement(); // 找到根元素books
        List<Element> bookElements = root.elements("book"); // 从books下找所有的book

        // 循环找出id=1002的book元素
        for(Element ele : bookElements){
            String id = ele.element("id").getText();
            // 如果是10001删除book节点
            if("10001".equals(id)){
                root.remove(ele);// 从books节点中将book移除
            }
            // 如果是10002修改price值
            else if("10002".equals(id)){
                // 定位book的price子元素
                Element price = ele.element("price");
                // 修改price文本值
                price.setText("60");
            }
        }

        // 将内存中文档树对象状态更新到xml文件中
        OutputStream os = new FileOutputStream(xmlFile);
        XMLWriter writer = new XMLWriter(os);
        writer.write(doc);// 将doc文档对象输出
        writer.flush();
        writer.close();
    }

    public static void main(String[] args) throws Exception {
        List<Book> bookList = new ArrayList<Book>();
        // for(int i = 0; i < 5; i++){
        // Book book = new Book();
        // book.setId("1000" + i);
        // book.setName("bookName" + i);
        // book.setAuthor("bookAuthor" + i);
        // book.setPrice("20.1" + i);
        // bookList.add(book);
        // }

        // 测试生成xml文件
        // XmlUtil.toXMLFlie("d:/books.xml", bookList);

        // 解析xml文件
        bookList = XmlUtil.parseXmlToBookList("d:/books.xml");
        System.out.println(bookList);

        // 更新xml文件
        XmlUtil.updateXmlText("d:/books.xml");
        bookList = XmlUtil.parseXmlToBookList("d:/books.xml");
        System.out.println(bookList);
    }
}

XPATH


XPATH:相当于XML的SQL语句,从XML中取出我们想要的数据。功能:可以快速定位文档树对象的节点

在dom4j.jar包基础上引入jaxen-1.1-beta-6.jar,然后利用selectNodes(“xpath表达式”);selectSingleNode(“xpath表达式”);

xpath表达式语法:

//节点名 : 定位任意位置的节点元素对象

/节点名 : 定位指定名字的根节点元素

/节点1/节点2 : 定位根节点1下面的节点2

//节点名[子节点名=’文本值’] :利用子元素内容做条件定位节点

//节点名[@属性名=’属性值’] :利用属性做条件定位节点

public static void main(String[] args) throws Exception {
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File("d:/books.xml"));
        List<Element> list = doc.selectNodes("/book-list/book/price");
        for(Element e : list){
            System.out.println(e.getText());
        }
        list = doc.selectNodes("/book-list/book[price<=200]/price");
        for(Element e : list){
            System.out.println(e.getText());
        }
}

“/book-list/book/price”:节点路径XPTH,找什么样的节点

Book[ 筛选条件],筛选条件可以有:first()  last()  postion()==>定哪些元素要哪些元素不要

eg:book[ potion()>1 and postion()<4]:第2,3个元素  Book[ price<200 and price>100]