XML解析

1 篇文章 0 订阅

一、了解XML

  • XML 指可扩展标记语言(EXtensible Markup Language)
  • XML 是一种标记语言,很类似 HTML
  • XML 的设计宗旨是传输数据,而非显示数据
  • XML 标签没有被预定义。您需要自行定义标签。
  • XML 被设计为具有自我描述性
XML 与 HTML 的主要差异
  • XML 被设计为传输和存储数据,其焦点是数据的内容。
  • HTML 被设计用来显示数据,其焦点是数据的外观。
  • HTML 旨在显示信息,而 XML 旨在传输信息。

二、常用的解析XML的技术

  • A:DOM(Document Object Model):

    在内存中构建一颗倒挂的树,通过对内存中的节点进行操作从而解析XML缺点:由于需要根据XML文档构造倒挂的树,所以当XML文档比较大时,非常耗内存。有造成内存溢出的危险。不适合移动设备的开发.

  • B:SAX(Simple API For Xml):

    基于事件驱动的方式解析XML(推模式PUSH)

  • C:JDOM:

    对DOM模型的简化,专门针对Java语言解析XML而设计的

  • D:DOM4J:
    融入了XPath语法等,是目前解析XML功能最强大的一门技术

  • E:PULL:
    基于事件驱动的方式解析XML.(拉模式(PULL))

三、使用DOM技术解析Xml

DOM技术是JDK自带的技术,使用时不需要导入第三方jar包

1.实例化DOM解析器工厂对象

DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();

2.根据DOM解析器工厂对象得到DOM解析器对象

DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();

3.指定要解析的Xml文件在哪里并发放文档对象

Document document= documentBuilder.parse(inputStream);

4.根据文档对象得到根节点对象

Element root= document.getDocumentElement();

5.根据标签名获取指定节点的集合存储到NodeList对象中

NodeList book_nodeList= root.getElementsByTagName("标签名");
int len=book_nodeList.getLength();//获取集合中节点的个数
for(int i=0;i<len;i++){
    Node book_node=book_nodeList.item(i);
    //为了使用Element特有的方法:String getAttribute(String name)根据属性名获取属性值的功能
    Element book_element=(Element) book_node;
    String isbn=book_element.getAttribute("isbn");
    //getTextContent():获取当前节点的文本内容
    String name=book_element.getElementsByTagName("name").item(0).getTextContent();
    String author=book_element.getElementsByTagName("author").item(0).getTextContent();
    String price=book_element.getElementsByTagName("price").item(0).getTextContent();
    String publish=book_element.getElementsByTagName("publish").item(0).getTextContent();
    Book book=new Book(isbn,name,author,Double.parseDouble(price),publish);
    books.add(book);
}

xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book isbn="001">
        <name>Java</name>
        <author>孙鑫</author>
        <price>56.7</price>
        <publish>人民出版社</publish>
    </book>
    <book isbn="002">
        <name>Android</name>
        <author>安迪鲁宾</author>
        <price>76.7</price>
        <publish>邮电出版社</publish>
    </book>
    <book isbn="003">
        <name>iOS</name>
        <author>乔布斯</author>
        <price>56.7</price>
        <publish>清华出版社</publish>
    </book>
</books>

将给定的Xml文件做相关修改后生成新的Xml文件

public class DOMGenerateXmlDemo02 {
    public static void main(String[] args) {
        DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
        1.实例化转换工厂对象
        TransformerFactory transformerFactory=TransformerFactory.newInstance();
        DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
        InputStream inputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("books.xml");
        Document doc=documentBuilder.parse(inputStream);
        Element element_root=doc.getDocumentElement();
        2.通过转化工厂对象得到转换器对象
        Transformer transformer= transformerFactory.newTransformer();
        3.设置输出属性,文档进行缩进
        transformer.setOutputProperty("indent","yes");
        4.实例化DOMSource对象
        DOMSource domSource=new DOMSource();
        domSource.setNode(doc);
        Element element_book=doc.createElement("book");
        element_book.setAttribute("isbn","400");
        Element element_name=doc.createElement("name");
        element_name.setTextContent("小丽");
        element_book.appendChild(element_name);
        element_root.appendChild(element_book);
        //实例化流结果对象
        StreamResult streamResult=new StreamResult();
        //指定流结果对象关联的输出流对象
        streamResult.setOutputStream(new FileOutputStream("hsj.xml"));
        //将内存中的树结构生成指定的文件
        transformer.transform(domSource, streamResult);
    }
}

根据数据源中的数据生产Xml文档

public class DOMGenerateXmlDemo03 { 
    public static void main(String[] args) {
        List<Book> books=new ArrayList<Book>();
        books.add(new Book("100", "Java", "孙鑫", 45.6, "人民出版社"));
        books.add(new Book("200", "Android", "安迪鲁宾", 55.6, "邮电出版社"));
        books.add(new Book("300", "iOS", "乔布斯", 65.6, "清华出版社"));
        //1.得到DOM解析器工厂对象
        DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
        //2.得到DOM解析器对象
        DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
        //3.使用解析器对象得到文档对象
        Document document=documentBuilder.newDocument();
        //4.根据文档对象创建元素对象
        Element element_root=document.createElement("books");
        //5.将根节点对象挂载到文档对象上
        document.appendChild(element_root);
        //构建Xml文件
        for(Book book:books){
            //创建子节点book
            Element element_book=document.createElement("book");
            element_book.setAttribute("isbn", book.getIsbn());
            //将book节点挂载到books节点上
            element_root.appendChild(element_book);
            //创建子节点name
            Element element_name=document.createElement("name");
            element_name.setTextContent(book.getName());
            //将name节点挂载到book节点上
            element_book.appendChild(element_name);
            //创建子节点author
            Element element_author=document.createElement("author");
            element_author.setTextContent(book.getAuthor());
            //将author节点挂载到book节点上
            element_book.appendChild(element_author);
            //创建子节点price
            Element element_price=document.createElement("price");
            element_price.setTextContent(String.valueOf(book.getPrice()));
            //将price节点挂载到book节点上
            element_book.appendChild(element_price);
            //创建子节点publish
            Element element_publish=document.createElement("publish");
            element_publish.setTextContent(book.getPublish());
            //将publish节点挂载到book节点上
            element_book.appendChild(element_publish);
        }
         
        //将内存中构建的倒挂的树生成本地的Xml文件
        
        //1.得到转换器工厂对象
        TransformerFactory transformerFactory=TransformerFactory.newInstance();
        //2.根据转换器工厂对象得到转换器对象
        Transformer transformer=transformerFactory.newTransformer();
        //3.设置输出属性,文档进行缩进
        transformer.setOutputProperty("indent","yes");
        //4.准备DOMSouce对象
        DOMSource domSource=new DOMSource(document);
        //5.准备Result对象
        /*StringWriter stringWriter=new StringWriter();
        StreamResult streamResult=new StreamResult(stringWriter);*/
        File destFile=new File("hsj.xml");
        StreamResult streamResult=new StreamResult(destFile);
        //6.执行转换操作生成xml字符串
        transformer.transform(domSource, streamResult);
        //System.out.println(stringWriter);
        System.out.println("Xml文件生成成功!");
    }
 
}

四、SAX解析

1.得到SAX解析器工厂对象

SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();

2.通过SAX解析器工厂对象得到SAX解析器对象

SAXParser saxParser= saxParserFactory.newSAXParser();

3.通过解析器对象得到Xml的阅读器对象

XMLReader xmlReader= saxParser.getXMLReader();

4.通过Xml的阅读器对象开启命名空间特性功能

xmlReader.setFeature("http://xml.org/sax/features/namespaces", true);

5.指定要解析的Xml文件在哪里并且指定解析器(解析给定的Xml)对象

InputStream inputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("books.xml");
saxParser.parse(inputStream, new MyHandler());

5.在解析器中解析Xml即可
自定义SAX处理器是可以继承DefaultHandler类或者实现ContentHandler接口

要想解析Xml文件一般都会重写如下方法:

  • startDocument():在开始解析Xml文档前自动调用的方法,做初始化工作,只调用一次
  • startElement():遇到Xml的开始标签时自动调用的方法,看遇到多少个开始标签就调用多少次
  • characters():遇到文本元素(汉字,空白(空格,tab,回车等))时自动调用的方法,看xml文档中有多少文本元素
  • endElement():遇到Xml的结束标签时自动调用的方法,看遇到多少个结束标签就调用多少次
  • endDocument():在解析完毕Xml文档后自动调用的方法,做资源释放工作,只调用一次
private final static class MyHandler extends DefaultHandler{
     声明存放Book对象的集合
    private List<Book> books;
     声明书对象,用来存储解析出来的数据 
    private Book book;
     记录当前解析对象的父节点对象
    private String parent;
     收到开始解析Xml文档的通知时自动调用的方法,只调用一次
    @Override
    public void startDocument() throws SAXException {
        this.books=new ArrayList<Book>();
    }
    /**
     * 收到遇到开始标签的通知时自动调用的方法
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        //记录当前节点的标签名
        this.parent=qName;
        if("book".equals(qName)){
            //根据属性名得到属性值
            String isbn=attributes.getValue("isbn");
            book=new Book();
            book.setIsbn(isbn);
        }
    }
    /**
     * 收到遇到元素字符数据时自动调用的方法
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String data=new String(ch,start,length);
        if("name".equals(this.parent)){
            this.book.setName(data);
            }else if("author".equals(this.parent)){
            this.book.setAuthor(data);
            }else if("price".equals(this.parent)){
            this.book.setPrice(Double.parseDouble(data));
            }else if("publish".equals(this.parent)){
            this.book.setPublish(data);
        }
    }
    /**
     * 收到遇到元素结束标签时自动调用的方法
     */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        //遇到结束标签将之前的开始标签内容置空
        this.parent=null;
        if("book".equals(qName)){
            this.books.add(book);
        }
    }
    /**
     * 收到文档结束完毕的通知后自动调用的方法,只调用一次.
     */
    @Override
    public void endDocument() throws SAXException {
        System.out.println("books="+books);
    } 
}

五、Pull解析

1.得到Pull解析器工厂对象

XmlPullParserFactory xmlPullParserFactory=XmlPullParserFactory.newInstance();

2.过Pull解析器工厂对象得到Pull解析器对象

XmlPullParser xmlPullParser= xmlPullParserFactory.newPullParser();

3.指定要解析的Xml文件在哪里同时指定编码表

InputStream inputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("books.xml");
xmlPullParser.setInput(inputStream, "utf-8");

4.得到事件对象值

int eventType=xmlPullParser.getEventType();

5.只要没有解析到Xml的结尾则继续继续

while(eventType!=XmlPullParser.END_DOCUMENT){
    switch (eventType) {
        //XmlPullParser.START_DOCUMENT=0
        case XmlPullParser.START_DOCUMENT://开始解析Xml文档时返回的事件值
        break;
        
        //XmlPullParser.START_TAG=2
        case XmlPullParser.START_TAG://遇到开始标签时返回的事件值
            String startTag=xmlPullParser.getName();//得到当前解析节点的标签名
        break;
        
        //XmlPullParser.TEXT=4
        case XmlPullParser.TEXT://遇到字符数据时返回的事件值
            String text=xmlPullParser.getText();//得到当前的文本内容
        break;
        
        //XmlPullParser.END_TAG=3
        
        case XmlPullParser.END_TAG://遇到结束标签时返回的事件值
            String endTag=xmlPullParser.getName();//得到当前解析节点的标签名
        break;
    }
    String startTag=xmlPullParser.getName();//得到当前解析节点的标签名
    String isbn=xmlPullParser.getAttributeValue(null, "isbn");//根据属性名获取属性值
    String publish=xmlPullParser.nextText();//得到当前节点的文本内容
 	//将事件流继续向下推动
    eventType=xmlPullParser.next();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值