可扩展标记语言,一般用作配置文件(如struts、spring、hibernate),也可以用来传输数据。由xml声明,文档类型声明和若干标记组成。
文档类型
文档类型规定了xml文件的数据结构,若不符合要求,即使该xml文件是规范的,也是无效的。
DTD
dtd是较为常用的文档类型文件,它规定了xml文件的数据结构。
格式
先看一个例子
<!ELEMENT 学生名单 (学生*)>
<!ELEMENT 学生 (姓名,学号)>
<!ELEMENT 姓名 (#PCDATA)>
<!ELEMENT 学号 (#PCDATA)>
<!ATTLIST 学生
专业 CDATA #REQUIRED
>
1.标记
<!ELEMENT 标记名称 (子标记列表)>
对于子标记列表的格式
#PCDATA:除特殊字符外所有字符
EMPTY:空标记
ANY:无任何约束
2.属性
<!ATTLIST 标记名称
属性名 属性类型 默认值情况
属性名 属性类型 默认值情况
...
>
属性类型:
CDATA:除特殊字符外的所有字符
Eumerated:枚举
NMTOKEN:由字母、数字、下划线、“.”、“-”组成的字符串,不能包含空格
NMTOKENS:含空格的NMTOKEN
ID:不能重复且只能有一个的MTOKEN,同时默认值情况只能是“#REQUIRED”或“#IMPLIED”
IDREF:只能是ID类型的值
IDREFS:多个IDREF
默认值情况:
#REQUIRED:必须有该属性,无默认值
#IMPLIED:可以没有该属性,无默认值
#FIXED“字符串”:可以没有该属性,若有则属性值固定
字符串:必须由该属性,且有默认值
XML Schema
XML Schema的功能比dtd更强大,不仅能够约束文件的标记和属性结构,还能约束文本的具体内容。XML Schema模式的文件扩展名为“.xsd”,使用XML语法来编写。
格式
XML Schema模式的跟标记必须是schema,使用的名称空间必须是:http://www.w3.org/2001/XMLSchema,名称空间的前缀是xsd。
对于没有子标记的标记,使用“简单类型”来约束,格式如下:
<xsd:element name="标记名称" type="简单数据类型"/>
相对的,有子标记的标记,使用“复杂类型”来约束,格式如下:
<xsd:element name="标记名称">
<xsd:complexType>
<xsd:squence>//squence表示子标记需要按照顺序排列,all则不约束
<xsd:element ref="子标记名称"/>
<xsd:element ref="子标记名称"/>
...
</xsd:squence>
</xsd:complexType>
</xsd:element>
ref中引用的子标记必须是全局元素,若不想引用或没有该全局元素,对子标记约束的元素也可以是一个复杂类型元素,格式如下:
<xsd:element name="子标记名称">
<xsd:complexType>
...
</xsd:complexType>
</xsd:element>
下面例子展示了复杂类型的使用方式
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="产品">
<xsd:complexType>
<xsd:squence>
<xsd:element ref="电视机"/>
<xsd:element name="洗衣机">
<xsd:complexType>
<xsd:element ref="价钱"/>
<xsd:element name="重量" type="int"/>
</xsd:complexType>
</xsd:element>
</xsd:squence>
</xsd:complexType>
</xsd:element>
<xsd:element name="电视机">
<xsd:complexType>
<xsd:squence>
<xsd:element ref="价钱"/>
<xsd:element ref="重量"/>
</xsd:squence>
</xsd:complexType>
</xsd:element>
<xsd:element name="价钱" type="xsd:int"/>
<xsd:element name="重量" type="xsd:float"/>
</xsd:schema>
对于标记,还可以进行数量限制,例如:
<xsd:element ref="学生" minOccurs="0" maxOccurs="unbounded">
unbounded表示不限制
属性必须定义在复杂类型中,此时若用到无子标记的标记,可以用复杂类型代替:
<xsd:element name="姓名">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:simpleContent>
</xsd:complexType>
</xsd:element>
上面的代码和<xsd:element name="姓名" type="xsd:string"/>
效果相同
属性的格式
<xsd:attribute name="属性名称" type="基本数据类型" use="条件"/>
其中use可取值required、optional、fixed、default
解析器
目前XML的解析器分为两种,DOM解析器和SAX解析器
DOM解析器
DOM解析器基于DOM规范,在内存中创建和XML数据结构相对应的树形结构数据,不仅可以方便程序分析XML文件中的数据,而且程序也可以使用内存中的树形结构数据修改XML文件中的数据或创建新的XML文件。DOM解析器的缺点是占用较多的内存,如果仅仅需要XML文件中的少量特殊数据,使用DOM解析器就会事倍功半。
DOM解析器的方法和dom类似。
基于JAXP的DOM解析器使用
import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
public class JAXPTest {
public static void main(String[] args) {
try {
//读取XML
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder domPaser = factory.newDocumentBuilder();
Document document = domPaser.parse(new File("WebContent/x1.xml"));
Element root = document.getDocumentElement();
String rootName = root.getNodeName();
System.out.println("XML文件根节点的名字:"+rootName);
NodeList nodelist = root.getChildNodes();
//显示
output(nodelist);
//修改XML,添加新的节点
Node text = document.createTextNode("赵六");
Node nodeName = document.createElement("姓名");
Node nodeStu = document.createElement("学生");
Element element = (Element) nodeStu;
element.setAttribute("专业", "嵌入式");
nodeName.appendChild(text);
element.appendChild(nodeName);
root.appendChild(element);
//使用DOM建立XML文件
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
DOMSource domSource = new DOMSource(document);
FileOutputStream out = new FileOutputStream(new File("WebContent/x2.xml"));
StreamResult xmlResult = new StreamResult(out);
transformer.transform(domSource, xmlResult);
} catch (Exception e) {
e.printStackTrace();
}
}
//递归输出节点内容的方法
private static void output(NodeList nodelist) {
int size = nodelist.getLength();
for(int i=0;i<size;i++){
Node node = nodelist.item(i);
if(node.getNodeType() == Node.TEXT_NODE){
Text textNode = (Text)node;
String content = textNode.getWholeText();
System.out.println(content);
}
if(node.getNodeType() == Node.ELEMENT_NODE){
Element elementNode = (Element)node;
String name = elementNode.getNodeName();
System.out.println(name+":");
NodeList nodes = elementNode.getChildNodes();
output(nodes);
}
}
}
}
修改document的常用方法如下:
Node节点:
Node appendChild(Node newChild):添加子节点
Node removeChild(Node newChild):删除子节点
Node replaceChild(Node newChild):替换子节点
Element节点:
Attr removeAttributeNode(Attr oldAttr):删除Element节点的属性
void setAttribute(String name,String value):为Element节点添加属性
Text节点:
Text replaceWholeText(String content):替换文本内容
void appendData(String arg):添加文本
void insertData(int offset,String arg):在指定位置插入文本
void deleteData(int offset,int count):删除指定位置开始的count个字符
void replaceData(int offset,int count):替换指定位置开始的count个字符
SAX解析器
SAX解析器基于事件处理机制,相对DOM解析器,SAX解析器占用的内存较少,效率高。但是SAX解析器只能读取数据,且对于获取特殊数据需要先处理诸多不必要的事件。
import java.io.*;
import javax.xml.parsers.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SAXTest {
public static void main(String[] args) {
try {
File file = new File("WebContent/x1.xml");
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
EventHandler handler = new EventHandler();
saxParser.parse(file, handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class EventHandler extends DefaultHandler{
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.println("<"+qName+">");
}
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.println("</"+qName+">");
}
public void characters(char[] ch, int start, int length) throws SAXException {
String text = new String(ch,start,length);
System.out.println(text);
}
}
XPATH语言
XPATH语言的核心是给出从XML文件中查找标记的语法规则,使程序能方便快捷的从XML文件中检索特殊数据。
XPATH路径表达式通过若干个“定位步”确定特殊标记的位置,中间由“/”隔开。
如:child::studentList/child::student/child::name
定位步格式
轴::节点测试[谓词]
轴
轴用来定位节点的位置
轴名 | 缩写 | 描述 |
child::节点测试 | 节点测试 | 当前节点的子节点 |
descendant::节点测试 | /节点测试 | 当前节点的子孙节点 |
parent::节点测试 | .. | 当前节点的父节点 |
ancestor::节点测试 | 无 | 当前节点的始祖节点 |
following::节点测试 | 无 | 当前节点的弟节点/td> |
preceding::节点测试 | 无 | 当前节点的兄节点 |
self::节点测试 | . | 当前节点 |
attribute::属性名 | @属性名 | 当前节点所关联的Attritube节点 |
namesapce::节点测试 | 无 | 当前节点所关联的Namespace节点 |
节点测试
节点测试决定节点的类型
标记名:寻找指定名字的Element类型节点
text():寻找Text类型节点
node():寻找Node类型节点
*:寻找任意名字的Element类型节点
processing-instruction:寻找Processing-Instruction类型节点
comment:寻找Comment类型节点
谓词
谓词决定节点的条件
[contains(@属性名,’特定字符串’)]:属性含有特定字符串
谓词可以嵌套使用,如:
/学生名单/学生[descendant::专业[contains(child::text(),'计算机')]]