XML ( Extensible Markup Language ( 可拓展标记语言 ))
是SGML(标准通用标记语言)即允许用户对自己的标记语言进行定义的源语言,
是Internet环境中跨平台的,依赖于内容技术,是处理结构化文档信息的有力工具。
是一种简单的数据存储语言,它使用一系列简单的标记描述数据。
是W3C组织发布的(包括HTML, CSS)
简称:在XML语音中,它允许用户自定义标签,一个标签用于描述一段数据; 一个标签可以分为开始标签和结束标签,在开始和结束标签之间,又可以使用其他标签描述其他数据, 以此来实现数据关系的描述。
XML技术除了用于保存有关的数据之外,它还经常用作软件配置文件,以描述程序模块之间的关系。
在一个软件系统中,为了提高系统的灵活性,它所启动的模块通常由其配置文件决定。
例如:一个软件在启动时,它需要启动A,B两个模块,在这两个模块启动时,又分别需要启动A1,A2和B1,B2的支持,为了准确描述这种关系,XML最为合适。
历史:刚开始W3C推出XML是为了取代HTML,中间还使用Xhtml过度,但是因为学习成本较高,没有实现取代,后面才作为其他作用。
标记语言:由一些格式代码(codes) 或控制标记 (tags)组成。标记决定信息的显示格式或数据的意义,但这些标记不能单独存在,只用于修饰它所包括的信息。
详细语法:
一个Xml文件分为以下几个内容
①文档声明(没有声明的文档称为格式不良好文档,所以必须要有,且要求放到第一句)
最简单的声明语法:
<?xml version="1.0"?>
用encoding属性说明文档的字符编码:
<?xml version ="1.0" encoding ="UTF-8"?>
用standalone属性说明文档是否独立:(是否依赖于其他文档)
<?xml version="1.0" encoding="GB2312" standalone="yes" ?>
②元素(element)
1,XML文件中出现的标签,一个标签分为开始标签和结束标签,一个
标签有两种书写形式:包含标签体<a>abcd</a>, 不含标签体<a/>
2,一个标签中可以嵌套若干子标签,但所有标签必须合理的嵌套,绝不允许相互嵌套;
例如 A中有B,在A结束标签前,B标签必须已经在A内部结束;
3,格式良好的XML文档必须有且仅有一个根标签,其他表示都是这个根标签的子孙标签。
对于XML中出现的所有空格和换行,XML解析程序都会当作标签内容进行处理。
例如:下面两段内容的医院是不一样的。
第一段:<国家>China</国家>
第二段:<国家>
China
</国家>
由于在XML中,空格和换行都作为原始内容被处理,所以,在编写XML文件时,
使用换行和缩进等方式让原文件中的内容清晰可读的”良好“书写习惯可能被迫改变。
4,一个XML元素可以包含字母,数字,以及其他一下可见字符,但必须遵守下面的一些规范:
区分大小写;
不能以数字或”_“ (下划线)开头;
不能以xml(或XML,Xml等)开头;
不能包含空格。
名称中间不能包含冒号(:)
③属性
一个标签可以有多个属性,每个属性都有它自己的名称和取值,例如:
<input name="text">
属性值一定要用双引号(”)或单引号(')引起来
定义属性必须准信与标签相同的命名规范
在XML技术中,标签属性所代表的信息,也可以被改成用子元素的形式来描述(属性封装或子元素封装)
例如:
<input>
<name>text</name>
</input>
④注释
格式: <!--注释-->
XMl声明之前不能有注释,注释不能嵌套
⑤CDATA区,特殊字符
在编写XML文件时,有些内容可能不想让解析引擎执行解析执行,而是当中元素内容处理。
这种情况可以吧这些内容放到CDATA区里,对于CDATA区域内的内容,
XML解析程序不会处理,而是执行原封不动的输出。例如:
语法:<![CDATA[内容]]>
<![CDATA[
<itcast>
<br/>
</itcast>
]]>
特殊字符
& &
> >
< <
" "
' &apos
⑥处理指令(processing instruction)
简称PI( processing instruction ) 。处理指令用来之后解析引擎如何解析XML文档内容。
例如在XML文档中可以使用xml-stylesheet指令,通知XML解析引擎,应用css文件显示xml文档内容。
<?xml-stylesheet type="text/css" href="1.css"?>
处理指令必须以“<?”作为开头,以“?>”作为结尾
XML声明语句就是最常见的意志处理指令。
XMl约束概述:
在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束。
常用的约束技术:XML DTD ; XML Schame
DTD(Document Type Dedinition),全称为文档类型定义。
例如:
文件清单:book.xml
<?xml version="1.0"?>
<!DOCTYPE 书架 SYSTEM"book.dtd">
<书架>
<书>
<书名>java</书名>
<作者>Bob</作者>
<价格>10.00元</价格>
</书>
</书架>
文件清单:book.dtd
<!ELEMENT 书架(书+)> +代表可以放一本或多本
<!ELEMENT 书(书名,作者,售价)> 指明仅能放书名,作者和售价
<!ELEMENT 书名(#PCDATA)> parse character data 可解析的字符数据,即字符串
<!ELEMENT 作者(#PCDATA)>
<!ELEMENT 售价(#PCDATA)>
DTD文件应用使用UTF-8或Unicode
与html区别:
①xml允许自定义标签名,html不支持
②xml是存储数据,html是显示数据
XML的结构解析:1,节点,2,元素,3,属性和属性值
DOM解析XML文件
“文档对象模型”方式,解析完XML将生产一个树状结构的对象。
实例:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf . newDocumentBuilder ();
Document doc = builder . parse ( xmlPath ) ;
得到doc后获取节点集合
NodeList list = doc . getElementsByTagName ( "message" );
获取每一个节点内的信息;
Node node = list . item( 0 );
String msg = note . getFirstChild() . getNodeValue();
基本DOM对象
①Domcument
代表整个XML文档,所有其他的Node,都以一定顺序包含在Document对象内,排列成一个树形结构
createAttribute ( String )
用给定的属性名创建一个Attr对象,并可在其后使用setAttributeNode方法来放置在某一个Element对象上面。
createElement ( String )
用给定的标签名创建一个Element 对象,代码XML 文档中的一个标签,然后就可以在这个Element对象上添加属性或者进行其他的操作。
crateTextNode ( String )
用给定的字符串创建一个Text对象, Text对象代码了标签或者属性中所包含的纯文本字符串。如果在一个标签内没有其他的标签,那么标签内的文本所代码的Text对象是这个Element对象的唯一子对象。
getElementByTagName ( String )
返回一个NodeList对象,包含所有给定标签名字的标签。
getDocumentElement ()
返回一个代表这个DOM树的根节点的Element对象,即文档根元素对象
②Node
代表文档中的一个抽象的节点,实际很少会真正用到Node对象,而是用Element , Attr, Text 等Node对象的子类对象操作文档。Node对象为这些对象提供一个抽象的,公共的根。
appendChild ( org.w3c.dom.Node )
为这个节点添加一个子节点,并放在所有子节点的最后,如果子节点已存在,则先把它删除再填加进去
insertBefore ( org.w3c.dom.Node new , org.w3c.dom.Node ref )
在给定的一个子对象前面再插入一个子对象。
getFirstChild ()
如果节点存在子节点,返回第一个子节点,(getLastChild()返回最后一个子节点)
getNodeName()
hasChildNodes()
hasArrtributes()
判断这个节点是否存在属性
getOwnerDocument()
返回节点所处的Document对象
③NodeList
包含一个或多个Node的列表,可简单视为一个Node数组
item( int ) 返回指定位置的Node对象
④Element
代表XML文档中的标签元素,继承Node,也是Node最主要的子对象
在标签中科院包含属性,因而Element对象中有存取其属性的方法,
getElementsByTagName ( String )
返回一个NodeList对象,包含了标签中旗下的子孙节点中具有给定签名字的标签。
getTagName()
getAttribute ( String ) 返回标签中给定的属性名称的属性值
getAttributeNode ( String ) 返回一个代码给定属性名称的Attr对象
⑤Attr
代表某标签中的属性,继承与Node,Attr实际包含在Element中,所以不能被视为Element的子对象
在DOM中Attr并不是DOM树的一部分,所以Node中的getparentNode(),getpreviousSibling()和getnextSibling() 返回都是null
SAX解析XML文件(Simple API for XML)
与DOM比较而言sax是一种轻量型的方法,
DOM是文档驱动的,在处理DOM时候,需要读取整个XML文档,然后在内存中创建DOM树,生成DOM树上的每个Node对象,当文档大起来时候是相当费劲的。
SAX是事件驱动的,不需读入整个文档,读文档的过程就是解析的过程,
它解析速度快,占内存少,这种解析器比较适合android等移动设备。
优点:流的方式处理,遇到标签时不会记录下当前所遇到的标签(在startElement()中,知道的仅是当前标签的名字和属性,至于标签的嵌套结构,上层标签名,是否有子元素与其他结构相关的信息,都是不知道的)。
在XMLReader , SAXParser 接收XML文档,在读入XML文档的过程中就进行解析,解析前需要向XMLReader/SAXParser注册一个ContentHandler监听,一般使用DefaultHander的子类处理XML文件
void startDocument()
在遇到文档开头时候调用,一般做预处理工作
void startElement ( String namespaseURI , String localName, String qName, Attributes atts )
读到开始标签时触发,namespaceURI是命名空间,localName是不带命名空间的标签名,qName是带命名空间的标签名,通过stts得到所有的属性名和相应的值
void characters( Char[] ch,int start,int lenght )
用于处理节点中读到的内容,第一个参数是文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用 new String ( ch , start , lenght )就可以获取内容
endEliment
和上面的startElement()方法对应,遇到结束标签的时候,调用这个方法。
endDocument
和上面的sartDocument()方法相对应,当问到结束时,调用这个方法,可以在其中做一些善后的工作。
实例:
解析如下XML文件:
①MyHandler继承DefaultHander
②重写 startDocument(){}
startElement(){}
characters(){}
endElement(){}
详:
private HashMap<String,String> map=null;//存储单个解析的完整对象
private List<HashMap<String,String>>list=null;//存储所有的解析对象
private String currentTag=null;//正在解析的元素的标签
private String currentValue=null;//解析当前元素的值
private String nodeName=null;//解析当前的节点名称
public My Handler( String nodeName ){
this.nodeName=nodeName;
}
public List<HashMap<String,String>>getList(){ return list; }
重写 startDocument(){
//当读到第一个开始标签的时候触发
list=new ArrayList<HashMap<String,String>>();
}
重写 startElelent(){
//当遇到文档开头的时候,调用这个方法
if(qName.equse(nodeName){
map=new HashMap<String,String>();
}
if(attributes != null && map!=null){
for(int i = 0; i<attributes ; i++){
map.put(attributes.getQName(i),attributes.getValue(i));
}
}
curentTag=qName;
}
重写 characters(){
//处理XML文件读到的内容
if(curentTag!=null&&map!=null){
curentValue=new String(ch,start,leng);//声明字符串装置节点对应的值
if(currentValue!=null&¤tValue.trim().equals("")
&&!curentValue.trim().equals("\n")){
map.put(currentTag,currentValue);
}
}
currentTag=null;//把当前节点的对应的值和标签设置为空
currentValue=null;
}
重写endElement(){
//遇到结束标记的时候,会调用这个方法//准备解析下一个节点
if(qName.equalse(nodeName)){
list.add(map);
map=null;
}
}
使用pull来解析XML文件
pull解析器是一个开源的java项目,可用于android 也可用于其他的JavaEE项目中,
Pull已经默认集成到android类库中,
它类似于SAX方式,程序以“拉取”的方式对xml进行解析。
pull运行方式与SAX解析相似,提供了一个用户解析XML的接口:Xmlpullparser,
提供了和SAX类似的事件:
开始和结束的元素事件,使用parser,nest() 进入下一个元素并触发事件,和SAX不同的是,Pull解析器参数的事件是一个数字(使用其中的常量来比较),而非方法,因此可以swich 对感兴趣的事件进行处理,当元素开始解析时,调用parser.nextText()方法可以获取下一个Next类型节点的值。
使用pull解析器,可以根据需要只读取XML的部分内容,需要的数据被读取到的时候不再往下读。
文档声明 0 START_DOCUMENT;
文档结束 1 END_DOCUMENT;
开始标签 2 START_TAG
结束标签 3 END_TAG
读取文本 4 TEXT
三种解析方式的比较:
DUM
解析方式 将一个xml文件先按树的方式进行存储然后根据相应的方法解析加载整个XML文件
随机读取解析 支持
可生成xml文件 不可以
SAX
解析方式 从XML文件头开始解析,无需全部加载 , 以触发事件,调用相应的方法解析
随机读取解析 不支持
可生成xml文件 不可以
PULL
解析方式 以触发事件,执行相应的事件常量来进行解析,从XML文件头开始解析
随机读取解析 不支持
可生成xml文件 可以
对应实例的类
SaxService{
public SaxService(){
}
public static List<List<HashMap<String,String>>>readXML(
InputStream inputStream, String nodeName){
List<HashMap<String,String>>list =null;
try{
//创建一个解析XML的工厂对象
SAXParserFactory spf =SAXParserFactory.newInstans();
SAXParser sparser = spf.newSAParser();
MyHandler hander =new MyHandler(nodeName);
parser.parse(inputStream,handler);
inputStream.close();
return handler.getList();
}catch(){}
return null;
}
}
对应的网络上下载的XML文件
public class HttpUtils{
public HttpUtilsP(){}
public static InputStream getXML(String path){
InputStream inputStream =null;
try{
URL ur =new URL( path );
if(url!=null){
HttpURLConnection connection = (HttpURLConnection)
.openConnection();
connection.setConnectionTimeOut(3000);
connection.setDoInput(true);
connection.setRequesMethod("GET");
int code =connection.getResposeCode();
if(code==200){
inputStream = connection.getInputStream();
}
}
}
return null;
}
}
测试类
void main(){
String paht ="http://..."
InputStream is =HttpUtils.getXML(path);
try{
list<HashMap<String,String>> list = SaxService.readXML(is,"person");
for( HashMap<String,String>map : list ){
syso(map.toString());
}
}catch(){}
}