通知 网站从因情语写改为晴雨,这个网站的模板也从calmlog_ex改为 whimurmur

XML学习记录1-复习SAX,DOM和JAXB

4999人浏览 / 0人评论 / | 作者:因情语写  | 分类: JAVA基础  | 标签: JAVA

作者:因情语写

链接:https://www.qingyu.blue/article/283

声明:请尊重原作者的劳动,如需转载请注明出处


    对xml文档的解析常见的有JDK中的sax,dom,jaxb,stax和JAVA类库JDOM和DOM4J,下面先说说前三个。

  Java中解析XML的工具很多,像JDOM,DOM4J等,但Java标准库提供的两种解析XML文档解析器是:DOM(Document Object Module)解析器 和 SAX(Simple API for XML)解析器。DOM解析器会读入整个XML文档并转换成树结构;SAX解析器会在读入XML文档时生成相应的事件;故也常叫基于文档对象模型的XML解析和基于事件驱动的XML解析;那它们有什么区别呢? 

   DOM解析器会读入整个文档,构建一个驻留在内存中的树型结构,我们就可以使用 DOM 接口来操作这个文档树,其优点是整个文档树在内存中,便于操作,支持删除、修改、重新排列等多种功能;缺点是需将整个文档读入内存中,在文档大时会消耗大量内存; 

   SAX解释器在XML文档读入时能够立即开始,而不是等待所有的数据加载完后处理,解析器通过发现元素开始、元素结束、文本开始、文档结束等来发送事件,通过种基于回调机制的方法来处理数据;其优点是解析速度快,不用事先调入整个文档,占用资源少;其缺点是必须实现事件处理程序,不能修改文档,不能随机访问。

  JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。

  1.  DOM(Document Object Model)

  1.解析器工厂类:DocumentBuilderFactory

  创建的方法:DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

  2.解析器:DocumentBuilder

  创建方法:通过解析器工厂类来获得 DocumentBuilder db = dbf.newDocumentBuilder();

  3.文档树模型Document

  创建方法:a.通过xml文档 Document doc = db.parse("bean.xml");  b.将需要解析的xml文档转化为输入流 InputStream is = new FileInputStream("bean.xml");

   Document doc = db.parse(is); 

  Document对象代表了一个XML文档的模型树,所有的其他Node都以一定的顺序包含在Document对象之内,排列成一个树状结构,以后对XML文档的所有操作都与解析器无关,

  直接在这个Document对象上进行操作即可;

   包含的方法:

  4.节点列表类NodeList

  NodeList代表了一个包含一个或者多个Node的列表,根据操作可以将其简化的看做为数组

  5.节点类Node

  Node对象是DOM中最基本的对象,代表了文档树中的抽象节点。但在实际使用中很少会直接使用Node对象,而是使用Node对象的子对象Element,Attr,Text等

  6.元素类Element

  是Node类最主要的子对象,在元素中可以包含属性,因而Element中有存取其属性的方法

  Node.getNamespaceURI() 返回和给定节点关联的名称空间字符串,如果该元素或属性没有关联的名称空间则返回 null。

  7.属性类Attr

  代表某个元素的属性,虽然Attr继承自Node接口,但因为Attr是包含在Element中的,但并不能将其看做是Element的子对象,因为Attr并不是DOM树的一部分

  实例:

  DomDemo.java

package dom;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class DomDemo {

    public static void main(String[] args) throws Exception {
        String url = System.getProperty("user.dir");
        File xmlFile = new File(url + "/src/dom/beans.xml");
        
        if(!xmlFile.exists())
        {
            System.out.println("file not exist, return.");
            return;
        }
        
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        // 支持命名空间
        dbf.setNamespaceAware(true);
        // 开启校验
        dbf.setValidating(true);
        // 忽略注释
        dbf.setIgnoringComments(true); 
        //如果使用xsd,一船需要设置schemaLanguage的schema版本.  
        dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
        
        try
        {
            DocumentBuilder db = dbf.newDocumentBuilder();
            // 校验出错处理
            db.setErrorHandler(new ErrorHandler() {
                
                @Override
                public void warning(SAXParseException exception) throws SAXException {
                    System.out.println("warning: " + exception.getMessage());
                    
                }
                
                @Override
                public void fatalError(SAXParseException exception) throws SAXException {
                    System.out.println("fatalError: " + exception.getMessage());
                }
                
                @Override
                public void error(SAXParseException exception) throws SAXException {
                    System.out.println("error: " + exception.getMessage());
                }
            });
            
            // dtd 或者 schema 文件验证xml
            // 校验xsd
            db.setEntityResolver(new EntityResolver() {
                
                @Override
                public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
                    String url = System.getProperty("user.dir");
                    InputSource inputSource = new InputSource(new FileInputStream(new File(url + "/bin/dom/spring-beans-3.2.xsd")));
                    inputSource.setSystemId(systemId);
                    inputSource.setPublicId(publicId);
                    return inputSource;
                }
            });
            
            Document document = db.parse(xmlFile);
            Element root = document.getDocumentElement();
            System.out.println("根元素: " + root.getNodeName());
            
       // 示例用法
            /*NodeList childNodes = root.getChildNodes();
            
            for(int i = 0; i <childNodes.getLength(); i++)
            {
                Node node = childNodes.item(i);
                if("web-app".equals(node.getNodeName()))
                {
                    System.out.println("\r\n找到一篇文章,所属分类: " + node.getAttributes()
                            .getNamedItem("category").getNodeValue() + ". ");
                    NodeList nodeDetail = node.getChildNodes();
                    for(int j = 0; j < nodeDetail.getLength(); j++)
                    {
                        Node detail = nodeDetail.item(j);
                        if("title".equals(detail.getNodeName()))
                        {
                            System.out.println("标题:" + detail.getTextContent());
                        }
                        else if("author".equals(detail.getNodeName()))
                        {
                            System.out.println("作者:" + detail.getTextContent());
                        }
                        else if("email".equals(detail.getNodeName()))
                        {
                            System.out.println("电子邮箱:" + detail.getTextContent());
                        }
                        else if("date".equals(detail.getNodeName()))
                        {
                            System.out.println("发表日期:" + detail.getTextContent());
                        }
                    }
                }
            }*/
            
        }
        catch(Exception exception)
        {
            exception.printStackTrace();
        }
        
    }
    
    /**
     * DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     * DocumentBuilder db = dbf.newDocumentBuilder();
     * Document document = db.parse(xmlFile);
     * Element root = document.getDocumentElement();
     * NodeList childNodes = root.getChildNodes();
     * Node node = childNodes.item(i);
     * node.getAttributes();
     * node.getAttributes().getNamedItem("category");
     * detail.getNodeName();
     * detail.getNodeValue();
     * detail.getTextContent();
     * 
     */
}

     beans.xml

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  

    <!-- 定义使用C3P0连接池的数据源 -->  
    <bean d="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">  
        <!-- 指定连接数据库的JDBC驱动 -->  
        <property name="driverClass">  
            <value>com.mysql.jdbc.Driver</value>  
        </property>  
        <!-- 连接数据库所用的URL -->  
        <property name="jdbcUrl">  
            <value>jdbc:mysql://localhost:3306/eportal?useUnicode=true&characterEncoding=utf-8</value>  
        </property>  
        <!-- 连接数据库的用户名 -->  
        <property name="user">  
            <value>root</value>  
        </property>  
        <!-- 连接数据库的密码 -->  
        <property name="password">  
            <value>root</value>  
        </property>  
        <!-- 设置数据库连接池的最大连接数 -->  
        <property name="maxPoolSize">  
            <value>20</value>  
        </property>  
        <!-- 设置数据库连接池的最小连接数 -->  
        <property name="minPoolSize">  
            <value>2</value>  
        </property>  
        <!-- 设置数据库连接池的初始化连接数 -->  
        <property name="initialPoolSize">  
            <value>2</value>  
        </property>  
        <!-- 设置数据库连接池的连接的最大空闲时间,单位为秒 -->  
        <property name="maxIdleTime">  
            <value>20</value>  
        </property>  
    </bean>  
    
    <!-- 定义Hibernate的SessionFactory -->  
    <bean id="sessionFactory"  
        class="org.springframework.orm.  
hibernate3.LocalSessionFactoryBean">  
        <!-- 依赖注入上面定义的数据源dataSource -->  
        <property name="dataSource" ref="dataSource" />  
        <!-- 注册Hibernate的ORM映射文件 -->  
        <property name="mappingResources">  
            <list>  
                <value>com/eportal/ORM/News.hbm.xml</value>  
                <value>com/eportal/ORM/Category.hbm.xml</value>  
                <value>com/eportal/ORM/Memberlevel.hbm.xml</value>  
                <value>com/eportal/ORM/Cart.hbm.xml</value>  
                <value>com/eportal/ORM/Traffic.hbm.xml</value>  
                <value>com/eportal/ORM/Newsrule.hbm.xml</value>  
                <value>com/eportal/ORM/Merchandise.hbm.xml</value>  
                <value>com/eportal/ORM/Admin.hbm.xml</value>  
                <value>com/eportal/ORM/Orders.hbm.xml</value>  
                <value>com/eportal/ORM/Cartselectedmer.hbm.xml</value>  
                <value>com/eportal/ORM/Newscolumns.hbm.xml</value>  
                <value>com/eportal/ORM/Member.hbm.xml</value>  
            </list>  
        </property>  
        <!-- 设置Hibernate的相关属性 -->  
        <property name="hibernateProperties">  
            <props>  
                <!-- 设置Hibernate的数据库方言 -->  
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>  
                <!-- 设置Hibernate是否在控制台输出SQL语句,开发调试阶段通常设为true -->  
                <prop key="show_sql">true</prop>  
                <!-- 设置Hibernate一个提交批次中的最大SQL语句数 -->  
                <prop key="hibernate.jdbc.batch_size">50</prop>  
                <prop key="show_sql">50</prop>  
            </props>  
        </property>  
    </bean>  
    <!--定义Hibernate的事务管理器HibernateTransactionManager -->  
    <bean id="transactionManager"  
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
        <!-- 依赖注入上面定义的sessionFactory -->  
        <property name="sessionFactory" ref="sessionFactory" />  
    </bean>  
    <!--定义Spring的事务拦截器TransactionInterceptor -->  
    <bean id="transactionInterceptor"  
        class="org.springframework.transaction.interceptor.TransactionInterceptor">  
        <!-- 依赖注入上面定义的事务管理器transactionManager -->  
        <property name="transactionManager" ref="transactionManager" />  
        <!-- 定义需要进行事务拦截的方法及所采用的事务控制类型 -->  
        <property name="transactionAttributes">  
            <props>  
                <!-- 以browse、list、load、get及is开头的所有方法采用只读型事务控制类型 -->  
                <prop key="browse*">PROPAGATION_REQUIRED,readOnly</prop>  
                <prop key="list*">PROPAGATION_REQUIRED,readOnly</prop>  
                <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>  
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>  
                <prop key="is*">PROPAGATION_REQUIRED,readOnly</prop>  
                <!-- 所有方法均进行事务控制,如果当前没有事务,则新建一个事务 -->  
                <prop key="*">PROPAGATION_REQUIRED</prop>  
            </props>  
        </property>  
    </bean>  
    <!-- 定义BeanNameAutoProxyCreatorf进行Spring的事务处理 -->  
    <bean  
        class="org.springframework.aop.framework.autoproxy.    
BeanNameAutoProxyCreator">  
        <!-- 针对指定的bean自动生成业务代理 -->  
        <property name="beanNames">  
            <list>  
                <value>adminService</value>  
                <value>columnsService</value>  
                <value>newsService</value>  
                <value>crawlService</value>  
                <value>memberLevelService</value>  
                <value>memberService</value>  
                <value>categoryService</value>  
                <value>merService</value>  
                <value>cartService</value>  
                <value>ordersService</value>  
                <value>trafficService</value>  
            </list>  
        </property>  
        <!-- 这个属性为true时,表示被代理的是目标类本身而不是目标类的接口 -->  
        <property name="proxyTargetClass">  
            <value>true</value>  
        </property>  
        <!-- 依赖注入上面定义的事务拦截器transactionInterceptor -->  
        <property name="interceptorNames">  
            <list>  
                <value>transactionInterceptor</value>  
            </list>  
        </property>  
    </bean>  
    <!-- 装配通用数据库访问类BaseDAOImpl -->  
    <bean id="dao" class="com.eportal.DAO.BaseDAOImpl">  
        <property name="sessionFactory" ref="sessionFactory" />  
    </bean>  
    <!-- 部署系统用户管理业务逻辑组件AdminServiceImpl -->  
    <bean id="adminService" class="com.eportal.service.AdminServiceImpl">  
        <property name="dao" ref="dao" />  
    </bean>  
    <!-- 部署新闻栏目管理业务逻辑组件ColumnsServiceImpl -->  
    <bean id="columnsService" class="com.eportal.service.ColumnsServiceImpl">  
        <property name="dao" ref="dao" />  
    </bean>  
      
    <!-- 部署订单管理业务逻辑组件OrderServiceImpl -->  
    <bean id="ordersService" class="com.eportal.service.OrderServiceImpl">  
        <property name="dao" ref="dao" />  
    </bean>  
    <!-- 部署流量统计业务逻辑组件TrafficServiceImpl -->  
    <bean id="trafficService" class="com.eportal.service.TrafficServiceImpl">  
        <property name="dao" ref="dao" />  
    </bean>  
    <!-- 部署Struts 2负责系统用户管理的控制器AdminAction -->  
    <bean id="adminAction" class="com.eportal.struts.action.  
AdminAction"  
        scope="prototype">  
        <property name="service" ref="adminService" />  
    </bean>  
    <!-- 部署Struts 2负责新闻栏目管理的控制器ColumnsAction -->  
    <bean id="columnsAction" class="com.eportal.struts.action.  
ColumnsAction"  
        scope="prototype">  
        <property name="service" ref="columnsService" />  
    </bean>  
    <!-- 部署Struts 2负责新闻管理的控制器NewsAction -->  
    <bean id="newsAction" class="com.eportal.struts.action.  
NewsAction"  
        scope="prototype">  
        <property name="service" ref="newsService" />  
        <property name="columnsService" ref="columnsService" />  
    </bean>  
    <!-- 部署Struts 2负责新闻采集规则管理的控制器CrawlAction -->  
    <bean id="crawlAction" class="com.eportal.struts.action.  
CrawlAction"  
        scope="prototype">  
        <property name="service" ref="crawlService" />  
        <property name="columnsService" ref="columnsService" />  
    </bean>  
      
</beans> 

    spring-beans-3.2.xsd(只显示一部分)

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- 注释掉了property -->
<xsd:schema xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.springframework.org/schema/beans">

    <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>

    <xsd:annotation>
        <xsd:documentation><![CDATA[
    Spring XML Beans Schema, version 3.2
    Authors: Juergen Hoeller, Rob Harrop, Mark Fisher, Chris Beams

    This defines a simple and consistent way of creating a namespace
    of JavaBeans objects, managed by a Spring BeanFactory, read by
    XmlBeanDefinitionReader (with DefaultBeanDefinitionDocumentReader).

    This document type is used by most Spring functionality, including
    web application contexts, which are based on bean factories.

    Each "bean" element in this document defines a JavaBean.
    Typically the bean class is specified, along with JavaBean properties
    and/or constructor arguments.

    A bean instance can be a "singleton" (shared instance) or a "prototype"
    (independent instance). Further scopes can be provided by extended
    bean factories, for example in a web environment.

    References among beans are supported, that is, setting a JavaBean property
    or a constructor argument to refer to another bean in the same factory
    (or an ancestor factory).

    As alternative to bean references, "inner bean definitions" can be used.
    Singleton flags of such inner bean definitions are effectively ignored:
    inner beans are typically anonymous prototypes.

    There is also support for lists, sets, maps, and java.util.Properties
    as bean property types or constructor argument types.
        ]]></xsd:documentation>
    </xsd:annotation>

    <!-- base types -->
    <xsd:complexType name="identifiedType" abstract="true">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
    The unique identifier for a bean. The scope of the identifier
    is the enclosing bean factory.
            ]]></xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="id" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[
    The unique identifier for a bean. A bean id may not be used more than once
    within the same <beans> element.
                ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
    </xsd:complexType>

    <!-- Top-level <beans> tag -->
    <xsd:element name="beans">
        <xsd:annotation>
            <xsd:documentation><![CDATA[
    Container for <bean> and other elements, typically the root element in the document.
    Allows the definition of default values for all nested bean definitions. May itself
    be nested for the purpose of defining a subset of beans with certain default values or
    to be registered only when certain profile(s) are active. Any such nested <beans> element
    must be declared as the last element in the document.
            ]]></xsd:documentation>
        </xsd:annotation>
  。。。。。。
  。。。。。。
  。。。。。。
  。。。。。。
</xsd:schema>

    包含了对xml文件的验证和错误处理。验证使用EntityResolver,错误处理使用ErrorHandler,和基本使用示例

  下面说一下DOM方式生成XML:抄了一段别人的代码:

package util;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class FileUtil {

    public void createXMLByDOM(File dest) {
        // 创建DocumentBuilderFactory
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        try {

            // 创建DocumentBuilder
            DocumentBuilder builder = factory.newDocumentBuilder();

            // 创建Document
            Document document = builder.newDocument();

            // 设置XML声明中standalone为yes,即没有dtd和schema作为该XML的说明文档,且不显示该属性
            // document.setXmlStandalone(true);

            // 创建根节点
            Element bookstore = document.createElement("bookstore");

            // 创建子节点,并设置属性
            Element book = document.createElement("book");
            book.setAttribute("id", "1");

            // 为book添加子节点
            Element name = document.createElement("name");
            name.setTextContent("安徒生童话");
            book.appendChild(name);
            Element author = document.createElement("author");
            author.setTextContent("安徒生");
            book.appendChild(author);
            Element price = document.createElement("price");
            price.setTextContent("49");
            book.appendChild(price);

            // 为根节点添加子节点
            bookstore.appendChild(book);

            // 将根节点添加到Document下
            document.appendChild(bookstore);

            /*
             * 下面开始实现: 生成XML文件
             */

            // 创建TransformerFactory对象
            TransformerFactory tff = TransformerFactory.newInstance();

            // 创建Transformer对象
            Transformer tf = tff.newTransformer();

            // 设置输出数据时换行
            tf.setOutputProperty(OutputKeys.INDENT, "yes");

            // 使用Transformer的transform()方法将DOM树转换成XML
            tf.transform(new DOMSource(document), new StreamResult(dest));

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TransformerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

    详见下面的文章:Java——DOM方式生成XML

  2. SAX (Simple API for XML)

  SAX是基于事件的方法,它很类似于标签库的处理机制,在文档开始、结束,标签开始、结束以及错误发生等等地方调用相应的接口实现方法,不是全部文 档都读入内存。 SAX具有优异的性能和利用更少的存储空间特点。SAX 的设计只考虑了功能的强大性,却没有考虑程序员使用起来是否方便。

  必须扩展ContentHandler(或者DefaultHandler )。

  实例:

package sax;

import java.io.File;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class SaxDemo {
    public static void main(String[] args) throws Exception {
        String url = System.getProperty("user.dir");
        File xmlFile = new File(url + "/src/sax/article.xml");
        if(!xmlFile.exists())
        {
            System.out.println("file not found, return");
            return;
        }
        
        SAXParserFactory spf = SAXParserFactory.newInstance();
        // Specifies that the parser produced by this code will provide support for XML namespaces
        spf.setNamespaceAware(true);
        spf.setValidating(true);
        // http://blog.csdn.net/scmrpu/article/details/50423701
        spf.setFeature("http://xml.org/sax/features/validation", true);
        
        try
        {
            SAXParser sp = spf.newSAXParser();
            sp.parse(xmlFile, new MySaxHandler());
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    
    /**
     * SAXParserFactory spf = SAXParserFactory.newInstance();
     * SAXParser sp = spf.newSAXParser();
     * sp.parse(xmlFile, new MySaxHandler());
     * MySaxHandler
     * startElement
     * endElement
     * endDocument
     * startDocument
     * characters
     */
}

    article.xml

<?xml version="1.0" encoding="UTF-8"?>
<a:articles xmlns:a="www.example.namespace/article">
<a:article category="java">
    <a:title>Java基本语法</a:title>
    <a:author>janet</a:author>
    <a:email>janetvsfei@yahoo.com.cn</a:email>
    <a:date>20080801</a:date>
</a:article>
<a:article category="xml">
    <a:title>XML概述</a:title>
    <a:author>janet</a:author>
    <a:email>janetvsfei@yahoo.com.cn</a:email>
    <a:date>20080801</a:date>
</a:article>
</a:articles>

    MySaxHandler.java

package sax;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MySaxHandler extends DefaultHandler {
    
    private String content;
    @Override
    public void startDocument() throws SAXException 
    {
    }
    
    @Override
    public void endDocument() throws SAXException 
    {
    }
    
    @Override
    /*
     *spf.setNamespaceAware(true): then uri and localName are not null; otherwise
     *they are null.
     */
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException 
    {
        if("a:article".equals(qName))
        {
            System.out.println("\r\n找到一篇文章,所属分类: " + attributes.getValue("category") + ". ");
        }
    }
    
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException 
    {
        if("a:title".equals(qName))
        {
            System.out.println("标题:" + content);
        }
        else if("a:author".equals(qName))
        {
            System.out.println("作者:" + content);
        }
        else if("a:email".equals(qName))
        {
            System.out.println("电子邮箱:" + content);
        }
        else if("a:date".equals(qName))
        {
            System.out.println("发表日期:" + content);
        }
    }
    
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException 
    {
        content = new String(ch, start, length);
    }
}

    下面是SAX生成XML,抄了别人一段代码:

package util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import domain.Book;

public class XMLUtil {

    private List<Book> bookList;

    //生成XML文件
    public void createXMLBySAX(List<Book> books, File dest) {
        // 创建SAXTransformerFactory对象
        SAXTransformerFactory factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
        try {
            // 通过SAXTransformerFactory对象创建TransformerHandler对象
            TransformerHandler handler = factory.newTransformerHandler();
            // 通过Handler创建Transformer对象
            Transformer transformer = handler.getTransformer();
            // 设置Transformer的属性
            transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            // 创建Result对象,并将目的XML文件与其关联
            Result result = new StreamResult(dest);
            // 将handler与result关联起来
            handler.setResult(result);

            try {
                // 开启文档
                handler.startDocument();
                // 新建节点
                handler.startElement("", "", "bookstore", null);
                AttributesImpl atts = new AttributesImpl();
                for (Book book : books) {
                    atts.clear();
                    atts.addAttribute("", "", "id", "", String.valueOf(book.getId()));
                    handler.startElement("", "", "book", atts);
                    handler.startElement("", "", "name", null);
                    handler.characters(book.getName().toCharArray(), 0, book.getName().length());
                    handler.endElement("", "", "name");
                    handler.startElement("", "", "author", null);
                    handler.characters(book.getAuthor().toCharArray(), 0, book.getAuthor().length());
                    handler.endElement("", "", "author");
                    handler.startElement("", "", "price", null);
                    handler.characters(Float.toString(book.getPrice()).toCharArray(), 0,
                            Float.toString(book.getPrice()).length());
                    handler.endElement("", "", "price");
                    handler.endElement("", "", "book");
                }
                // 关闭节点
                handler.endElement("", "", "bookstore");
                // 关闭文档
                handler.endDocument();
            } catch (SAXException e) {
                e.printStackTrace();
            }

        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        }
    }

    //解析XML文件
    public List<Book> parseXMLBySAX(File file) {
        SAXParser parser = getParser();
        MyHandler handler = new MyHandler();
        try {
            parser.parse(file, handler);
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        bookList = handler.getBookList();

        return bookList;
    }

    public SAXParser getParser() {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = null;
        try {
            parser = factory.newSAXParser();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        }
        return parser;
    }

    public List<Book> getBookList() {
        return bookList;
    }

    public void setBookList(List<Book> bookList) {
        this.bookList = bookList;
    }

}

    详见下面的文章:Java——SAX方式生成XML

  3. JAXB(Java Architecture for XML Binding)

  JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术。该过程中,JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。

  实例:

  基本的java bean的处理

package jaxb;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class JAXBDemo {
    public static void main(String[] args) {
        String url = System.getProperty("user.dir");
        File xmlFile = new File(url + "/src/jaxb/article.xml");
        if(xmlFile.exists())
        {
            xmlFile.delete();
        }
        
        JAXBContext jaxbContext;
        BufferedWriter bw = null;
        
        try
        {
            jaxbContext = JAXBContext.newInstance(Article.class);
            // marshal
            Marshaller m = jaxbContext.createMarshaller();
            m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");// 设置编码
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);// 格式化输出
            
            Article article = new Article();
            article.setAuthor("Janet");
            article.setDate("20080801");
            article.setEmail("janetvsfei@yhoo.com.cn");
            article.setTitle("XML");
            
            StringWriter sw = new StringWriter();
            xmlFile.createNewFile();
            
            // 生成xml
            m.marshal(article, sw);
            
            bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(xmlFile)));
            bw.write(sw.toString().replace(" standalone=\"yes\"", ""));// 去掉standalone属性
            if(null != bw)
            {
                bw.close();
            }
            
            // unmarshal
            Unmarshaller u = jaxbContext.createUnmarshaller();
            
            // 从xml生成java对象
            Article article2 = (Article) u.unmarshal(xmlFile);
            System.out.println(article2);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    
    /**
     * JAXBContext jaxbContext = JAXBContext.newInstance(Article.class);
     * Marshaller m = jaxbContext.createMarshaller();
     * m.marshal(article, sw);
     * 
     * Unmarshaller u = jaxbContext.createUnmarshaller();
     * Article article2 = (Article) u.unmarshal(xmlFile);
     */
}

    article.xml

<?xml version="1.0" encoding="UTF-8"?>
<article>
    <author>Janet</author>
    <date>20080801</date>
    <email>janetvsfei@yahoo.com.cn</email>
    <title>XML</title>
</article>

    列表的处理

package jaxb;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;

// root name
@XmlRootElement(name="articles")
public class ArticleData {
    // named root's first level children list name
    private List<Article> article = new ArrayList<Article>();
    
    public List<Article> getArticle() {
        return article;
    }
    public void setArticle(List<Article> article) {
        this.article = article;
    }
    public static void main(String[] args) {
        String url = System.getProperty("user.dir");
        File xmlFile = new File(url + "/src/jaxb/article2.xml");
        JAXBContext jaxbContext;
        try
        {
            jaxbContext = JAXBContext.newInstance(ArticleData.class);
            Unmarshaller u = jaxbContext.createUnmarshaller();
            ArticleData articleData = (ArticleData) u.unmarshal(xmlFile);
            
            System.out.println(articleData.getArticle().get(0));
            System.out.println(articleData.getArticle().get(1));
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

}

    article2.xml

<?xml version="1.0" encoding="UTF-8"?>
<articles>
<article category="java">
    <title>Java基本语法</title>
    <author>janet</author>
    <email>janetvsfei@yahoo.com.cn</email>
    <date>20080801</date>
</article>
<article category="xml">
    <title>XML概述</title>
    <author>janet</author>
    <email>janetvsfei@yahoo.com.cn</email>
    <date>20080801</date>
</article>
</articles>

    Article.java

package jaxb;

import javax.xml.bind.annotation.XmlRootElement;
// 使用注解
@XmlRootElement
public class Article {
    private String title;
    private String author;
    private String email;
    private String date;
    
    @Override
    public String toString() {
        return "Article [title=" + title + ", author=" + author + ", email=" + email + ", date=" + date + "]";
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getDate() {
        return date;
    }
    public void setDate(String date) {
        this.date = date;
    }
}

   详细内容可以看下面的文章:JAXB应用实例

  除了抄别人的代码,剩下的都是自己学习过程的代码,对dom,说了解析xml,设置错误处理器和校验,还说了生成xml(抄别人的代码);对sax,说了生成(抄别人的代码)与解析xml;对JAXB,说了生成与解析XML,还说了字段为列表的情况,其它内容可以看我提供的文章,有关于jaxb更高级一些的内容,如适配器,工具类,更多注解,数据修改,对集合与对象字段的处理,自己学习的很浅显,看别人的文章才能看出问题,只当是做个大致的了解,作为入门的参考吧。


自己写的文章声明标题示例:


点赞(0) 打赏

全部评论

还没有评论!