java-XML

XML不再多说,XML 约束也不用说了,这里讲讲java如何对XML操作。

java中使用XML,目前常用的就是Jaxp(sun)和dom4j了,这里先讲讲java自带的Jaxp包

JAXP 开发包是J2SE的一部分,它由javax.xml、org.w3c.dom 、org.xml.sax 包及其子包组成

Jaxp的xml解析器有两种,一种是DOM解析器,一种是SAX解析器,两种各自应用在不同的场景上。

在DOM解析时,会把xml中各个节点视为对象,然后根据父子关系相互嵌套。优点时容易操纵,缺点也很明显,必须全部通读xml并加载进内存。

DOM解析的流程:

1,DocumentBuilderFactory是抽象类,newInstance()方法会根据本地平台安装的xml解析器自动创建相应的工厂实力

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

2,DocumentBuilder的newDocumentBuilder()方法会得到本地xml解析器相应的DocumentBuilder实力

DocumentBuilder documentB = dbf.newDocumentBuilder();

3,解析xml,根据DocumentBuilder的parse方法。

Document document = documentB.parse(new File(path));
//看文档可以知道,parse可以从解析File、InputSource(经过包装的InputStream)、InputStream和URI字符串

4,Document代表了整个XML文档,首先获取根节点,Element就是标签,它们都属于Node,也就是说,都实现了Node接口

Element root=document.getDocumentElement();

5,下面就是增删改查了

增加结点

//增加一个结点,注意,增加节点是对document操作,Document实现了这个方法
Element newStudent=document.createElement("student");
             
//增加一个属性,属性也算是结点,一切都是Node
Attr cid=document.createAttribute("idcard");
//给属性设置值
cid.setValue("1121");
             
//将属性添加进这个标签
newStudent.setAttributeNode(cid);
             
//最后,将这个结点添加进根节点,注意,是对根节点添加,不是Document
root.appendChild(newStudent);


提取某节点信息(查)

//首先根据第3步,已经获得根结点,也就是Element root
 
 
//获取所有标签名为sutdent的节点集合
NodeList students=root.getElementsByTagName("student");
 
//至于获取标签属性以及text内容,自行看手册
 
//要注意的是,换行和制表符'\n\t'这些,也会被当做text内容解析
//至于xml的编码问题,都是自动的,不用手动设置了。

更改结点内容(很多都是Node接口的方法,自行查看手册即可)

//设置标签内容
Node.setTextContent(String text)
 
//设置属性内容
Attr.setValue(String value)

删除结点

Node.removeChild(Node node)


6,操作完xml,保存结果

javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式后进行输出,例如把xml文件应用样式表后转成一个html文档。
利用这个对象,当然也可以把Document对象又重新写入到一个XML文件中。
//1、获得Transformer工厂
TransformerFactory tff=TransformerFactory.newInstance();
 
//2、对于DOM对象,使用树来表示,肯定是个多叉树了,,,
//这个类,就是将树,变为结果树
Transformer tf = tff.newTransformer();
 
//3、把document(DOM)转换为xml source
Source sc=new DOMSource(document);
 
//4、创建一个DOM目标,这里是个流
Result rs=new StreamResult(new File(path_URI));
 
//5、将 XML Source 转换为 Result,这样就写入数据流了
tf.transform(sc, rs);

DOM解析就到这里,如果以网络流读取一个大的xml文件的话,这样肯定是不行的,不可能一直等到它全部读完载入内存再操作吧。。。。。光读取的话,就用SAX了。

SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:
•解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。
•解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。

事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理

我们常用的就是ContentHandler了。

下面是sax示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//定义工厂api,用以配置和获取sax解析器
        SAXParserFactory spf = SAXParserFactory.newInstance();
         
        //得到解析器对象
        SAXParser sp = spf.newSAXParser();
         
        //得到一个xmlreader读取器
        XMLReader xmlReader = sp.getXMLReader();
 
        //注册一个内容事件处理器 ContentHandler,一般情况下,使用ContentHandler接口的已知
        //子类DefaultHandler就行了
         
        xmlReader.setContentHandler(new DefaultHandler(){
            //为了方便,以内部类重写需要使用到的方法
             
            //开始读取标签
            public void startElement(String uri, //命名空间
                    String localName, //标签名
                    String qName, //限定名称
                    Attributes attributes //属性
                    ){
                 
                ///////////////////////////
                //获取标签的个数
                attr.getLength();
                //其它的看手册               
            }
             
            //开始读取文档
            public void startDocument(){
                 
            }
             
            //读取到标签尾
            public void endElement( String namespaceURI,
                      String localName,
                      String qName ) {
 
           }
             
            //读取标签体,注意的是,sax是分段读取的,每次最大读取是2kb
            public void characters(char[] ch,
                    int start,
                    int length
                   ){
                //读取大数据的时候注意sax是分段读取的,每次最大读取是2kb
                 
                 
            }
            
 
             
        });
         
         
        //开始读取xml数据
        xmlReader.parse("book.xml");


到这里,我们发现SAX虽然比DOM效率高,但是它是顺序读取的,无法回头,且只能从头到尾。

现在就可以使用Dom4j了,它是第三方包

Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。
使用Dom4j开发,需下载dom4j相应的jar文件。

lDOM4j中,获得Document对象的方式有三种:
//1.读取XML文件,获得document对象            
          SAXReader reader = new SAXReader();
         Document   document = reader.read(new File("input.xml"));
 
//2.解析XML形式的文本,得到document对象.
          String text = "<members></members>";            Document document = DocumentHelper.parseText(text);//3.主动创建document对象.
          Document document = DocumentHelper.createDocument();             //创建根节点
          Element root = document.addElement("members");

dom4j 中结点对象的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  //1.获取文档的根节点.
    Element root = document.getRootElement();
     
  //2.取得某个节点的子节点.
    Element element=node.element(“书名");
     
  //3.取得节点的文字
    String text=node.getText();
  //4.取得某节点下所有名为“member”的子节点,并进行遍历.
    List nodes = rootElm.elements("member");
    for (Iterator it = nodes.iterator(); it.hasNext();) {
        Element elm = (Element) it.next();
        // do something
    }
     
  //5.对某节点下的所有子节点进行遍历.
    for(Iterator it=root.elementIterator();it.hasNext();){
        Element element = (Element) it.next();
       // do something
    }
     
  //6.在某节点下添加子节点.
    Element ageElm = newMemberElm.addElement("age");
     
  //7.设置节点文字.
    element.setText("29");
     
  //8.删除某节点.
    //childElm是待删除的节点,parentElm是其父节点
    parentElm.remove(childElm);
  //9.添加一个CDATA节点.
    Element contentElm = infoElm.addElement("content");
    contentElm.addCDATA(diary.getContent());

对节点对象属性的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  //1.取得某节点下的某属性
    Element root=document.getRootElement();
    //属性名name
    Attribute attribute=root.attribute("size");
 
  //2.取得属性的文字
   String text=attribute.getText();
 
  //3.删除某属性
    Attribute attribute=root.attribute("size");
    root.remove(attribute);
     
  //4.遍历某节点的所有属性
    Element root=document.getRootElement(); 
    for(Iterator it=root.attributeIterator();it.hasNext();){
        Attribute attribute = (Attribute) it.next();
        String text=attribute.getText();
        System.out.println(text);
    }
  //5.设置某节点的属性和文字.
    newMemberElm.addAttribute("name", "sitinspring");
 
  //6.设置属性的文字
    Attribute attribute=root.attribute("name");
    attribute.setText("sitinspring");

在指定位置中插入元素:

1.得到插入位置的节点列表(list)
2.调用list.add(index,elemnent),由index决定element的插入位置。
3.list中存储的是引用,对list进行了更改,既对document进行了更改
//Element元素可以通过DocumentHelper对象得到。示例代码:
 
Element aaa = DocumentHelper.createElement("aaa");
aaa.setText("aaa");
 
List list = root.element("书").elements();
list.add(1, aaa);

写入XML文档

//1.文档中全为英文,不设置编码,直接写入的形式.
  XMLWriter writer = new XMLWriter(new  FileWriter("output.xml"));
  writer.write(document);
  writer.close();
 
//2.文档中含有中文,设置编码格式写入的形式. OutputFormat format = OutputFormat.createPrettyPrint(); // 指定XML编码                  
  format.setEncoding("GBK");
  XMLWriter writer = new XMLWriter(newFileWriter("output.xml"),format);
  writer.write(document);
  writer.close();

XML与字符串的转换

//1.将字符串转化为XML
  String text = "<members> <member>sitinspring</member></members>";
  Document document = DocumentHelper.parseText(text);
 
//2.将文档或节点的XML转化为字符串.
  SAXReader reader = new SAXReader();
  Document   document = reader.read(new File("input.xml"));
  Element root=document.getRootElement();    
  String docXmlText=document.asXML();
  String rootXmlText=root.asXML();
  Element memberElm=root.element("member");
  String memberXmlText=memberElm.asXML();

在Dom4j中使用xpath查询路径

xpath路径表达式就像正则表达式一样,可以免去自己写遍历对比代码了。

//dom4j的包中的document..........
List<Node> list = document.selectNodes("//xpath");

上面的所有代码基本上算是模板代码了,用的时候多看手册,拷贝粘贴就ok了

posted on   黑暗伯爵  阅读(868)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述

导航

< 2011年6月 >
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 1 2
3 4 5 6 7 8 9

统计

点击右上角即可分享
微信分享提示