Chinaunix首页 | 论坛 | 博客
  • 博客访问: 533487
  • 博文数量: 135
  • 博客积分: 3568
  • 博客等级: 中校
  • 技术积分: 1942
  • 用 户 组: 普通用户
  • 注册时间: 2006-10-19 17:52
文章分类

全部博文(135)

文章存档

2012年(29)

2011年(41)

2010年(26)

2009年(12)

2008年(9)

2007年(12)

2006年(6)

分类: Java

2010-12-07 20:27:36

文件:JaXBTest.rar
大小:16KB
下载:下载





package me.test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import com.ibm.icu.util.Calendar;

/**
 * 使用JAXB(JSR 222)解析、生成XML文件(大数据量)。
 *
 * 这里使用先编写XSD,再生成JavaBean的方式(类似于WebService中的Contract First-契约优先,或Up-Down方式)
 * 其实也可以先写JavaBean,再由Javabean生成XSD。
 *
 * Step 1. 使用Eclipse图形编写需要的XSD。
 * Step 2. 使用 JDK 6 自带的 xjc 命令自动生成javaBean代码。
 * (如果使用既有的XSD文件,且命名空间不符合要求,可以参考使用 external bindings files (*.xjb))
 * (如果使用JDK 1.5 单独下载 JAXB的RI即可,JAXB不支持JDK 1.4。)
 * Step 3. 使用生成的JavaBean解析、生成XML。
 *
 * 参考:
 * JSR 222
 *
 * JAXB RI(Reference Implementation, 参考实现)
 * https://jaxb.dev.java.net/
 * JAXB RI 中的 例子
 * JAXB2_20090708.jar!samples/partial-unmarshalling/*
 * XJC 命令介绍
 *
 * Customizing JAXB Bindings
 *
 *
 * @author btpka3@163.com
 */

public class JAXBTest {

    // XML -> JavaBean (unmarshaller)
    public static void unmarshall() throws Exception {
        JAXBContext context = JAXBContext.newInstance("me.test"); //package名称

        Unmarshaller unmarshaller = context.createUnmarshaller();

        // 创建并设定一个 Unmarshaller.Listener
        ExamUnmarshallListener unmarshallListener = new ExamUnmarshallListener();
        unmarshaller.setListener(unmarshallListener);

        // create a new XML parser
        SAXParserFactory factory = SAXParserFactory.newInstance();
        factory.setNamespaceAware(true);
        XMLReader reader = factory.newSAXParser().getXMLReader();

        // 流式解析XML,主要使用了该方法。
        // 缺点就是造成了业务逻辑代码片段被分割成一个一个的片段,而无法连续。
        // FIXME : 如何使用 StAX + JAXB? 且同时做到代码尽可能的简单?
        reader.setContentHandler(unmarshaller.getUnmarshallerHandler());

        try {
            reader.parse(new InputSource(
                    JAXBTest.class.getResourceAsStream("exam.xml")));
        } catch (Exception e) {
            // 如果觉得将业务异常变成RuntimeExcepiton不合适的话,
            // 就应该在 ExamUnmarshallListener 中设定结果正确标志,
            // 如果正确,就取得正确结果,否则取得异常信息。
            System.out.println("捕获了异常 :" + e.getMessage());
            e.printStackTrace();
        }
    }

    // JavaBean -> XML (marshall)
    public static void marshall() throws JAXBException, XMLStreamException,
            FileNotFoundException, UnsupportedEncodingException {

        // Step 1. 创建JAXB上下文

        JAXBContext context = JAXBContext.newInstance(ExamType.class);

        // Step 2. 创建Marshaller
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "GBK");
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
        //marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "");

        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

        // Step 3. 使用StAX写入开始标签和基本信息。
        XmlSchema xmlSchema = PersonType.class.getPackage().getAnnotation(
                XmlSchema.class);
        String ns = xmlSchema.namespace();
        System.out.println(xmlSchema.namespace());
        ObjectFactory fac = new ObjectFactory();

        XMLOutputFactory output = XMLOutputFactory.newInstance();
        output.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
        File file = new File("C:/aa.txt");
        OutputStream out = new FileOutputStream(file);
        XMLStreamWriter writer = output.createXMLStreamWriter(out, "UTF-8");

        writer.writeStartDocument();
        writer.setDefaultNamespace(ns);
        writer.writeStartElement(ns, "exam");

        // Step 4. 使用JaXB写入循环的大量记录
        for (int i = 0; i < 3; i++) {

            // Step 4.1. 准备需要的JavaBean(比如查询数据库)
            PersonType p = new PersonType();
            p.setId("04111010" + (i + 1));
            p.setName("Name" + (i + 1));
            p.setSex("男");
            Calendar c = Calendar.getInstance();
            c.set(1985, 7, i + 1, 0, 0, 0);
            p.setBirthday(fromDate(c.getTime()));

            for (int j = 0; j < 3; j++) {
                ScoreType score = new ScoreType();
                score.setSubject("s" + (j + 1));
                score.setValue(85 + j);
                p.getScore().add(score);
            }

            JAXBElement<PersonType> personElement = fac.createPerson(p);

            // 计算当前记录转换成XML后的长度(注意:会)
            StringWriter w = new StringWriter();
            marshaller.marshal(personElement, w);
            int curRecLength = w.getBuffer().length();
            System.out.println("当前记录的长度为(含xmlns):" + curRecLength);
            System.out.println(w);

            // Step 4. 转换并输出
            marshaller.marshal(personElement, writer);

            writer.flush();
            System.out.println("XML 文件当前记录长度 (仅根元素含xmlns)= " + file.length());

        }
        // 写入结束标签
        writer.writeEndElement();
        writer.writeEndDocument();
        writer.flush();
    }
    public static void main(String[] args) {
        try {
            unmarshall();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            marshall();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static String personToString(PersonType p) {
        StringBuilder buf = new StringBuilder();
        buf.append("\n----------------person");
        buf.append("\n id = " + p.getId());
        buf.append("\n name = " + p.getName());
        buf.append("\n sex = " + p.getSex());
        buf.append("\n birthday = " + p.getBirthday());
        for (ScoreType s : p.getScore()) {
            buf.append("\n score{" + s.getSubject() + " : " + s.getValue()
                    + "}");
        }
        return buf.toString();
    }

    // XMLGregorianCalendar -> Date
    public static Date toDate(XMLGregorianCalendar xcal) {
        Date dt = xcal.toGregorianCalendar().getTime();
        //java.sql.Date sqlDt = new java.sql.Date(dt.getTime());

        return dt;
    }

    // Date -> XMLGregorianCalendar
    public static XMLGregorianCalendar fromDate(Date date) {
        GregorianCalendar c = new GregorianCalendar();
        c.setTime(date);
        DatatypeFactory df;
        try {
            df = DatatypeFactory.newInstance();
        } catch (DatatypeConfigurationException e) {
            throw new RuntimeException(e);
        }
        XMLGregorianCalendar xcal = df.newXMLGregorianCalendar(c);
        return xcal;
    }
}
class ExamUnmarshallListener extends Unmarshaller.Listener {

    // 一次处理一条记录,因此内存占用量低,
    // 可以由于解析拥有大量记录的XML文件。
    public void afterUnmarshal(Object target, Object parent) {
        // 如果有类似于

的结构的话,就先进行该项检查。
        // 但是若必须
顺序优先于的话,必须通过XSD格式检验提前保证。
        // if (target instanceof HeaderType) {
        // // 获取基本信息,身份验证等。
        // }


        if (target instanceof PersonType) {
            // 我们可以在这里进行业务操作,比如Check,插入DB等
            PersonType p = (PersonType) target;
            System.out.println(JAXBTest.personToString(p));
            if ("991110102".equals(p.getId())) {
                throw new RuntimeException("示例业务异常");
            }
        }
    }
    public void beforeUnmarshal(Object target, Object parent) {

    }
}


阅读(3784) | 评论(1) | 转发(0) |
0

上一篇:StAX 生成XML文件

下一篇:Java - FTPS

给主人留下些什么吧!~~

chinaunix网友2011-01-02 19:40:07

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com