XML解析

XML文件解析

1、XML文件要求

  • 1、标签

    1. xml标签名称区分大小写,中间不能有空格,不能以数字开头
    2. xml标签一定要正确匹配
    3. 一个xml文件中只能有一个标签
  • 2、属性

    1. 属性值必须以引号包含,不能省略,可以是单引号也可以是双引号
    2. 一个标签可以有多个属性,但不能出现重复的属性名
  • 3、注释

    <!-- xml注释 -->

  • 4、xml中特殊字符,转义字符
  • 5、CDATA块

    作用: 可以让一些需要进行包含特殊字符的内容统一进行原样输出

  • 6、处理指令

    作用: 告诉xml解析如果解析xml文档
    案例:<?xml-stylesheet type="text/css" href="1.css"?> 告诉xml解析该xml文档引用了哪个css文件
    需要提前xml内容可以使用xml-stylesheet指令指令

2、XML解析

  • 1、解析方式
    1. DOM解析
    2. SAX解析
  • 2、XML解析工具

    • DOM解析:
      1. JAXP(官方工具)
      2. JDOM工具(非官方)
      3. Dom4J(非官方)
    • SAX解析
      • Sax解析工具(oracle-sun公司官方)
  • 3、DOM 解析

    DOM解析原理:xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一棵Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到xml文档的内容。

    使用步骤:

    1. 导入dom4j的核心包。dom4j-1.6.1.jar
    2. 编写Dom4j读取xml文件代码

    节点信息:节点名称、节点类型 封装到 Node(父类)

    • 标签节点封装为ELement对象(Node子类),含有子节点
    • 属性节点封装为Attribute对象(Node子类)
    • 文本对象封装为Text对象(Node子类)

      节点:
          Iterator  Element.nodeIterator();  //获取当前标签节点下的所有子节点
      
      标签:
            Element  Document.getRootElement();  //获取xml文档的根标签        
           Element   ELement.element("标签名") //指定名称的第一个子标签
            Iterator<Element> Element.elementIterator("标签名");// 指定名称的所有子标签
              List<Element>    Element.elements(); //获取所有子标签
      
      属性:
          String   Element.attributeValue("属性名") //获取指定名称的属性值
           Attribute    Element.attribute("属性名");//获取指定名称的属性对象    
                  Attribute.getName()  //获取属性名称
                  Attibute.getValue()  //获取属性值
              List<Attribute>  Element.attributes();  //获取所有属性对象
              Iterator<Attribute>     Element.attibuteIterator(); //获取所有属性对象
      
      文本:
                  Element.getText();  //获取当前标签的文本
                  Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容 
      

示例代码XML文件读取

得到节点信息

@Test
public void test1() {
    try {
        // 1、读取xml文档
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File("./src/contact.xml"));

        // 2. nodeIterator:得到当前节点下所有的子节点对象(不包括孙节点)
        Iterator<Node> it = doc.nodeIterator();
        while(it.hasNext()){
            Node node = it.next();
            String name = node.getName();
            System.out.println(name);

            // 继续取出下边的子节点
            // 只有标签节点才有子节点
            // 判断当前节点是否是标签节点
            if(node instanceof Element){
                Element elem = (Element)node;
                Iterator<Node> it2 = elem.nodeIterator();
                while(it2.hasNext()){
                    Node n = it2.next();
                    String nName = n.getName();
                    System.out.println(nName);
                }
            }
        }

    } catch (DocumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

得到所有的标签

@Test
public void test2(){
    try {
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File("./src/contact.xml"));
        Element rootElement = doc.getRootElement();
        System.out.println(rootElement.getName());
        Iterator<Node> it = rootElement.nodeIterator();
        while(it.hasNext()){
            Node node = it.next();
            if(node instanceof Element){
                Element el = (Element)node;
                getChild(el);
            }
        }

    } catch (DocumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
// 获取节点下的所有子节点
public void getChild(Element elem){
    System.out.println(elem.getName());
    Iterator<Node> it = elem.nodeIterator();
    while(it.hasNext()){
        Node n = it.next();
        if(n instanceof Element){
            Element el = (Element)n;
            getChild(el);
        }
    }
}

获取 标签 属性

@Test
public void test3(){
    try {
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new File("./src/contact.xml"));

        // 1. 获取根标签
        Element rootElement = doc.getRootElement();

        // 2. 获取指定名称标签(遇到的第一个)
        Element element = rootElement.element("contact");
        System.out.println(element.getName());
        // 3.获取所有的指定名称的子标签
        Iterator<Node> it = rootElement.elementIterator("contact");
        while(it.hasNext()){
            Node n = it.next();
            System.out.println(n.getName());
        }
        // 4、获取所有的子标签(不包括孙标签)
        List<Node> list = element.elements();
        for(Node n:list){
            System.out.println(n.getName());
        }

        // 5、获取属性
        String attributeValue = element.attributeValue("id");
        System.out.println(attributeValue);
        // 获取指定名称的属性对象
        Attribute attribute = element.attribute("id");
        System.out.println(attribute.getName()+" : "+attribute.getValue());
        // 获取节点的所有属性对象
        List<Attribute> listAttri = element.attributes();
        for(Attribute attr:listAttri){
            System.out.println(attr.getName()+" : "+attr.getValue());
        }

    } catch (DocumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

XML文件写出

  • 写出内容到xml文档

    XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
    wirter.write(Document);
    
  • 修改xml文档的API

    • 增加:

      DocumentHelper.createDocument()  增加文档
      addElement("名称")  增加标签
      addAttribute("名称",“值”)  增加属性
      
    • 修改:

      Attribute.setValue("值")  修改属性值
      Element.addAtribute("同名的属性名","值")  修改同名的属性值
      Element.setText("内容")  修改文本内容
      
    • 删除

      Element.detach();  删除标签  
      Attribute.detach();  删除属性
      

XML文件修改

import java.io.FileOutputStream;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.junit.Test;

/**
 * 创建一个xml文件,并加入标签
 * @author wsk
 *
 */
public class Demo2 {

    @Test
    public void test1() throws Exception{
        // 1、创建文档
        Document doc = DocumentHelper.createDocument();

        // 增加标签
        Element rootElem = doc.addElement("contactList");
        Element conElem = rootElem.addElement("contact");
        // 添加属性
        conElem.addAttribute("name", "abc");
        // 修改属性
        Attribute nameAttr = conElem.attribute("name");
        nameAttr.setValue("123");
        // 添加文本
        conElem.addText("张安");
        conElem.clearContent();// 清除文本内容
        conElem.addText("李四");
        // 删除:两种删除方式1.直接删除对象。2.调用父节点,用父节点删除子节点。
        nameAttr.detach();
        nameAttr.getParent().remove(nameAttr);

        // 2、写出
        FileOutputStream out = new FileOutputStream("./src/contact.xml");
//      OutputFormat format = OutputFormat.createCompactFormat();//紧凑格式
        OutputFormat format = OutputFormat.createPrettyPrint();//有换行格式
        format.setEncoding("utf-8");
        XMLWriter writer = new XMLWriter(out,format);
        writer.write(doc);
        writer.close();
    }
}

3、XPath技术

问题:当使用dom4j查询比较深的层次结构的节点(标签,属性,文本),比较麻烦

  • XPath作用:主要是用于快速获取所需的节点对象。

在dom4j中如何使用xPath技术

  1. 导入xPath支持jar包 。 jaxen-1.1-beta-6.jar
  2. 使用xpath方法
    List<Node> selectNodes("xpath表达式"); 查询多个节点对象

    Node selectSingleNode("xpath表达式"); 查询一个节点对象

XPath 语法

/ 绝对路径: 表示从xml的根位置开始或子元素(一个层次结构)
// 相对路径 : 表示不分任何层次结构的选择元素。
* 通配符 : 表示匹配所有元素
[] 条件 : 表示选择什么条件下的元素
@ 属性 : 表示选择属性节点
and 关系 : 表示条件的与关系(等价于&&)
text() 文本 : 表示选择文本内容

示例

String xPath = "//@id"; // 选择id属性对象
xPath = "//contact[not(@id)]";  //选择没有id属性的contact对象
xPath = "//contact[@id='001' and @name='eric']";    // 选择id=‘001’ name='eric'的节点
xPath = "//name/text()";    // 选择name节点的文本
Element stu = (Element)doc.selectSingleNode("//student[@id='2']");
List<Node> list = doc.selectNodes("//contact");

4、SAX解析

DOM解析时,一次性把xml全部读入到内存中,然后在内存中构建Document树,不适合大文件的读取
SAX解析原理:加载一点读取一点,对内存要求较低

SAX解析工具

SAX解析工具,sun公司提供内置在jdk中。org.xml.sax.*

核心类:SAXParser类:用于读取和解析xml文件对象

  1. 创建SAXParser对象
    SAXParser parser=SAXParserFactory.newInstanc().newSAXParser();
  2. 调用parse方法
    parser.parse(new File(“./src/contact.xml”), new MyDefaultHandler());
    一个类继承class 类名(extends DefaultHandler) 在调用是创建传进去
DefaultHandler类的API:
    void startDocument()  :  在读到文档开始时调用
    void endDocument()  :在读到文档结束时调用
    void startElement(String uri, String localName, String qName, Attributes attributes)  :读到开始标签时调用                
    void endElement(String uri, String localName, String qName)   :读到结束标签时调用
    void characters(char[] ch, int start, int length)  : 读到文本内容时调用

SAX解析
原理: 加载一点,读取一点,处理一点。适合大容量文件的读取
SAX解析只能读取
SAX解析只能从上往下,按顺序读取,不能往回读
SAX解析基于事件的编程方法。java开发编码相对复杂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值