初学XML

可扩展标记语言,一般用作配置文件(如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(),'计算机')]]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值