xml——简述、约束、解析

一、   Xml简介

1  概述.

a)      Xml是可扩展性的标记语言,设计被用来格式化存储,传递数据,而不是像HTML一样显示数据。

b)     Xml的标签没有预定义的,都需要自己定义

c)      Xml必须有且只有一个根标签,且标签必须要正确的嵌套,必须闭合,标签是大小写敏感的。

d)     Xml中的元素必须有关闭标签,但是Xml的声明没有关闭标签因为声明不属于xml本身的组成部分

2.   Xml元素

a)      概述:xml元素是从开始标签到结束标签的部分,一个元素内可以包括其他元素,属性,文本。

b)     命名规则:不能以数字、标点符号、xml、XML、Xml等开始;不能包含空格;可以包含字母,数字,其他字符;尽量避免“-”减号,“:”冒号,”.”句号。

c)      CDATA:CDATA中的文本不会被解析器解析,语法:<![CDATA[不希望被解析的文本内容]]>

3.  Xml属性

a)      属性必须用引号包围,尽量避免使用属性(属性不能包含多个值,属性不能包含数据结构,属性不容易扩展),而用元素代替。当仅仅需要数据作为标识符,而不是数据的一部分时,建议使用属性。

二、   DTD约束

1. 概述:用来定义合法的xml文档构建模型

2.  DTD的引用

a)      Xml源文件内部dtd的引用:<!DOCTYPE  root-element[ elements-declarations]>

b)     外部DTD文件的引用:<! DOCTYPE root-element SYSTEM “file-name”>

3.  DTD元素

a)      元素的声明:<! ELEMENT  emlemtName(element-content)>

b)     元素约束:

约束

关键字

格式

结果/解释

空元素

EMPTY

<! ELEMENT br EMPTY>

<br/>

带任何内容的元素

ANY

<! ELEMNET note ANY>

该元素可以包含任何元素数据

子元素

(child1,child2)

<! ELEMNET note (child1,child2,,,)>

该元素必须包含这些子元素,且子元素由逗号分隔开的顺序进行声明

至少出现一次

+

<! ELEMNET note (child1+)>

Child1子元素必须至少在note元素中出现一次

出现0次或多次

*

<! ELEMNET note (child1*)>

Child1子元素可以在note中出现0次或多次

0次或一次

<! ELEMNET note (child1?)>

Child1子元素可以在note中出现0次或一次

|

<! ELEMNET note (child1|child2)>

Note中出现一次child1或child2

 

4.    DTD属性约束

            i. 属性声明语法:<!ATTLIST element-name attribute-name attribute-typeattribute-value>

           ii.  属性类型:

xml——简述、约束、解析xml——简述、约束、解析

         iii.  属性值约束:

xml——简述、约束、解析xml——简述、约束、解析

5.      DTD实体

a)   实体概述:用于定义引用普通文本或特殊字符串的快捷方式的变量

b)  实体的定义:<!ENTITY entity-name "entity-value">

c)   外部实体声明:<!ENTITY entity-name SYSTEM "URI/URL">

d)  实体的引用:&实体名;

三、   Xml schema

1.  概述:由xml文件编写的描述了xml的文档的结构,是dtd的替代。<xsd:schema>是每个xml schema的根节点

2.  元素

a)  简易元素

              i.  概述:仅包含文本的元素,不会包含其他元素或属性

             ii. 定义:<xs:element name=”xxx” type=”yyy” [default=”aaa”  fixed=”bbb”]> 定义简易元素的名称,类型,默认值,固定值

            iii. 常用元素类型:xs:string 、xs:decimal、xs:integer、xs:boolean、xs:date、xs:time

b)  复合元素

                 i. 概述:包含其他元素或属性或文本,<xs:complexType>

                ii. 复合元素之间的扩展与引用:<xs:extension base="personinfo">,扩展引用personinfo这个元素

               iii. 常用标签

标签

解释

<xs:sequence>

该标签下的子元素必须按顺序出现

<xs:all>

子元素可以按任意顺序出现,且有且仅出现一次

<xs:simpleContent>

仅包含文本或属性的复合元素,必须在该标签下定义扩展或限定

<xs:choice>

选择指示器:出现其中任意一个子元素

<xs:any/>

可以使用未被规定的元素扩展xml文档

<xs:anyAttribute/>

可以使未被规定的属性来扩展xml元素

<xs:element name="navn" substitutionGroup="name"/>

声明navn元素可替换name元素

 

3.  属性

a)  概述:属性本身是简易类型

b) 定义:<xs:attribute name="xxx" type="yyy"  [default=”aaa”  fixed=”bbb” use=”required”] /> 定义属性名称,类型,默认值,固定值,是否必须

4.  限定(restriction)

a)  概述:为元素或属性定义可接受的值

b) 语法:

<xs:restriction base=”对哪种数据类型做限定”>

  <xs:限定类型 value=”限定值”/>

</xs:restriction>

c)  限定类型

xml——简述、约束、解析

xml——简述、约束、解析

四、   Xml解析

1.  DOM解析(documentobject modal)

a) 概述:官方提供的平台无关的解析方式,操作读取xml之前需要加载分析整个xml文档将其转换为对象模型的集合(dom树),所以是比较耗内存的对机器性能要求比较高。但它提供随机访问的方式,使得开发更灵活

b) 实现

public class DOMTest {

    public static void main(String[] args) {

        //创建一个DocumentBuilderFactory的对象

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        //创建一个DocumentBuilder的对象

        try {

            //创建DocumentBuilder对象

            DocumentBuilder db = dbf.newDocumentBuilder();

            //通过DocumentBuilder对象的parser方法加载books.xml文件到当前项目下

            Document document = db.parse("books.xml");

            //获取所有book节点的集合

            NodeList bookList = document.getElementsByTagName("book");

            //通过nodelistgetLength()方法可以获取bookList的长度

            System.out.println("一共有" + bookList.getLength() + "本书");

            //遍历每一个book节点

            for (int i = 0; i < bookList.getLength(); i++) {

                System.out.println("=================下面开始遍历第" + (i + 1) + "本书的内容=================");

                //通过 item(i)方法获取一个book节点,nodelist的索引值从0开始

                Node book = bookList.item(i);

                //获取book节点的所有属性集合

                NamedNodeMap attrs = book.getAttributes();

                System.out.println("第 " + (i + 1) + "本书共有" + attrs.getLength() + "个属性");

                //遍历book的属性

                for (int j = 0; j < attrs.getLength(); j++) {

                    //通过item(index)方法获取book节点的某一个属性

                    Node attr = attrs.item(j);

                    //获取属性名

                    System.out.print("属性名:" + attr.getNodeName());

                    //获取属性值

                    System.out.println("--属性值" + attr.getNodeValue());

                }

                //解析book节点的子节点

                NodeList childNodes = book.getChildNodes();

                //遍历childNodes获取每个节点的节点名和节点值

                System.out.println("第" + (i+1) + "本书共有" + childNodes.getLength() + "个子节点");

                for (int k = 0; k < childNodes.getLength(); k++) {

                    //区分出text类型的node以及element类型的node

                    if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {

                        //获取了element类型节点的节点名

                        System.out.print("第" + (k + 1) + "个节点的节点名:" + childNodes.item(k).getNodeName());

                        //获取了element类型节点的节点值

                        System.out.println("--节点值是:" + childNodes.item(k).getFirstChild().getNodeValue());

                        //System.out.println("--节点值是:" + childNodes.item(k).getTextContent());

                    }

                }

                System.out.println("======================结束遍历第" + (i + 1) + "本书的内容=================");

            }

        } catch (ParserConfigurationException e) {

            e.printStackTrace();

        } catch (SAXException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }       

    }

}

 

2. JDOM解析

a)  概述:扩展方法,只适用于java平台,简化了与xml的交互,所以比dom方式快些。使用具体类而不是接口

b) 实现:

public class JDOMTest {

    private static ArrayList<Book> booksList = new ArrayList<Book>();

    public static void main(String[] args) {

        // 1.创建一个SAXBuilder的对象

        SAXBuilder saxBuilder = new SAXBuilder();

        InputStream in;

        try {

            // 2.创建一个输入流,将xml文件加载到输入流中

            in = new FileInputStream("src/res/books.xml");

            InputStreamReader isr = new InputStreamReader(in, "UTF-8");

            // 3.通过saxBuilderbuild方法,将输入流加载到saxBuilder

            Document document = saxBuilder.build(isr);

            // 4.通过document对象获取xml文件的根节点

            Element rootElement = document.getRootElement();

            // 5.获取根节点下的子节点的List集合

            List<Element> bookList = rootElement.getChildren();

            // 继续进行解析

            for (Element book : bookList) {

                Book bookEntity = new Book();

                System.out.println("======开始解析第" + (bookList.indexOf(book) + 1)  + "书======");

                // 解析book的属性集合

                List<Attribute> attrList = book.getAttributes();

                // //知道节点下属性名称时,获取节点值

                // book.getAttributeValue("id");

                // 遍历attrList(针对不清楚book节点下属性的名字及数量)

                for (Attribute attr : attrList) {

                    // 获取属性名

                    String attrName = attr.getName();

                    // 获取属性值

                    String attrValue = attr.getValue();

                    System.out.println("属性名:" + attrName + "----属性值:"+ attrValue);

                    if (attrName.equals("id")) {

                        bookEntity.setId(attrValue);

                    }

                }

                // 对book节点的子节点的节点名以及节点值的遍历

                List<Element> bookChilds = book.getChildren();

                for (Element child : bookChilds) {

                    System.out.println("节点名:" + child.getName() + "----节点值:"+ child.getValue());

                    if (child.getName().equals("name")) {

                        bookEntity.setName(child.getValue());

                    }

                    else if (child.getName().equals("author")) {

                        bookEntity.setAuthor(child.getValue());

                    }

                    else if (child.getName().equals("year")) {

                        bookEntity.setYear(child.getValue());

                    }

                    else if (child.getName().equals("price")) {

                        bookEntity.setPrice(child.getValue());

                    }

                    else if (child.getName().equals("language")) {

                        bookEntity.setLanguage(child.getValue());

                    }

                }

                System.out.println("======结束解析第" + (bookList.indexOf(book) + 1)

                        + "书======");

                booksList.add(bookEntity);

                bookEntity = null;

                System.out.println(booksList.size());

                System.out.println(booksList.get(0).getId());

                System.out.println(booksList.get(0).getName());

               

            }

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (JDOMException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

}


3. SAX解析(simpleAPIs for xml)

a) 概述:官方提供的平台无关的解析方式,sax解析方式有时不必解析整个文档,采用事件驱动模型,所以内存消耗相对dom较少,顺序的访问模式,所以很难同时访问xml中的多处不同数据

b)  实现:

public class SAXTest{

        public static void main(String[] args) {

            //获得sax解析器工厂

            SAXParserFactory factory = SAXParserFactory.newInstance();

            try {

                //通过sax解析器工厂获取sax

                SAXParser parser = factory.newSAXParser();

                //创建sax解析器的处理器,指定对xml文档的处理,该处理器继承DefaultHandler,实现自己的处理

                SAXParserHandler handler = new SAXParserHandler();

                //解析xml文件

                parser.parse("books.xml", handler);

                System.out.println("~!~!~!共有" + handler.getBookList().size() + "本书");

                for (Book book : handler.getBookList()) {

                    System.out.println(book.getId());

                    System.out.println(book.getName());

                    System.out.println(book.getAuthor());

                    System.out.println(book.getYear());

                    System.out.println(book.getPrice());

                    System.out.println(book.getLanguage());

                    System.out.println("----finish----");

                }

            } catch (ParserConfigurationException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            } catch (SAXException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            } catch (IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }

}

packagecom.xml.test;

import
org.xml.sax.Attributes;
import
org.xml.sax.SAXException;
import
org.xml.sax.helpers.DefaultHandler;

import
java.util.ArrayList;

/**
 * @author xujieni
 * @create 2017- 11 - 21 - 18:15
 */
public class SAXParserHandlerextendsDefaultHandler{
    String
value =null;
   
Book book=null;
    private
ArrayList<Book> bookList=newArrayList<Book>();
    public
ArrayList<Book> getBookList() {
       
return bookList;
   
}

   
int bookIndex=0;
   
/**
     *
用来标识解析开始
     */
   
@Override
   
public void startDocument()throwsSAXException {
       
// TODO Auto-generated method stub
       
super.startDocument();
       
System.out.println("SAX解析开始");
   
}

   
/**
     *
用来标识解析结束
     */
   
@Override
   
public void endDocument()throwsSAXException {
       
// TODO Auto-generated method stub
       
super.endDocument();
       
System.out.println("SAX解析结束");
   
}

   
/**
     *
解析xml元素
     */
   
@Override
   
public void startElement(String uri,String localName,String qName,
                            
Attributes attributes)throwsSAXException {
       
//调用DefaultHandler类的startElement方法
       
super.startElement(uri,localName,qName,attributes);
        if
(qName.equals("book")) {
           
bookIndex++;
           
//创建一个book对象
           
book =newBook();
           
//开始解析book元素的属性
           
System.out.println("======================开始遍历某一本书的内容=================");
           
//不知道book元素下属性的名称以及个数,如何获取属性名以及属性值
           
int num = attributes.getLength();
            for
(inti =0;i < num;i++){
                System.
out.print("book元素的第"+ (i + 1) + "个属性名是:"
                       
+ attributes.getQName(i));
               
System.out.println("---属性值是:"+ attributes.getValue(i));
                if
(attributes.getQName(i).equals("id")) {
                   
book.setId(attributes.getValue(i));
               
}
            }
        }
       
else if (!qName.equals("name") && !qName.equals("bookstore")) {
            System.
out.print("节点名是:"+ qName + "---");
       
}
    }

   
@Override
   
public void endElement(String uri,String localName,String qName)
            
throws SAXException {
       
//调用DefaultHandler类的endElement方法
       
super.endElement(uri,localName,qName);
       
//判断是否针对一本书已经遍历结束
       
if (qName.equals("book")) {
           
bookList.add(book);
           
book =null;
           
System.out.println("======================结束遍历某一本书的内容=================");
       
}
       
else if (qName.equals("name")) {
           
book.setName(value);
       
}
       
else if (qName.equals("author")) {
           
book.setAuthor(value);
       
}
       
else if (qName.equals("year")) {
           
book.setYear(value);
       
}
       
else if (qName.equals("price")) {
           
book.setPrice(Double.parseDouble(value));
       
}
       
else if (qName.equals("language")) {
           
book.setLanguage(value);
       
}
    }

   
@Override
   
public void characters(char[] ch, intstart, int length)
           
throws SAXException {
       
// TODO Auto-generated method stub
       
super.characters(ch,start,length);
       
value =newString(ch,start,length);
        if
(!value.trim().equals("")) {
            System.
out.println("节点值是:"+value);
       
}
    }
}

自行脑补book


4.  DOM4J解析         

a) 概述:性能最好,常用方式

b) 实现

File f = new File("data_10k.xml");  

SAXReader reader = new SAXReader();  

Document doc = reader.read(f);  

  Element root = doc.getRootElement();