用Java如何处理XML数据

Java原生内置的处理XML的技术基本有这么几种:DOM,SAX,Stax,Jaxb.那么用Java我们要如何处理XML数据,希望对大家有帮助!

用Java如何处理XML数据

DOM :Document Object Model 顾名思义就是在内存中构建树形结构。处理小的XML文件还算勉强应付。如果文件比较大,他需要一次性装载整个XML,你会忍不了他的速度,并且他会吃光你所有的内存,最后程序会负分滚粗。

SAX:Simple API for XML Parsing 一般名字应该是没实现的愿望体现。比如一个人如果叫王金库,那么可以肯定他绝对没有金库。这样你应该理解这个API为啥叫Simple了。这API是回调式的,也就是你写的程序是被别人调戏用的。这API比DOM快点,而且是可以部分装载XML,这样你不用害怕OOME了。啥?你想写XML?忘掉这个叫Simple的玩意儿吧。

Stax: Streaming API for XML 这个总算是靠点谱了。你写的程序是主动式的访问XML各个节点。流式访问,不用担心OOME,速度嘛算是原生态里面最好的了。而且读写都支持,你不用这个还用哪个啊?

给个Stax的代码片段,算是参考吧:

XMLInputFactory xif = nstance();

XMLStreamReader xsr = teXMLStreamReader(new FileReader(""));

Tag(); // Advance to statements element

long i = 0;

String action = null;

while (ext()) {

if (() == T_ELEMENT) {

if ("ContentItem"ls(ocalName())) {

action = getAttributeValue(xsr, "action");

} else if ("Data"ls(ocalName())) {

i ++;

}

}

}

JAXB:Java Architecture for XML Binding 这是一个很酷的API.想法就是把XML各种属性定义映射到普通的Java Bean上。你无须关心解析反解析的细节,只要用普通的Java Bean就完成和XML的交互了。可是怎么构建一一映射的JavaBean呢?在已知XML的定义的情况下你可以用自带的xjc 命令自动生成相对应的`JavaBean.如果你用Eclipse,有类似的插件帮你完成这步。具体可以google一下。然后你要做的就是仅仅是使用数据啦。简单的令人发指:

JAXBContext jc = nstance(""); // 先注册你的JavaBean

// Create unmarshaller

Unmarshaller um = teUnmarshaller();

// Unmarshal XML contents of the file into your Java object

// instance

ObjectFactory objFac = new ObjectFactory(); // 生成Bean之后你会有这个工厂类的

teYourData(teYourDataType());

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("")); // 你要怎么打开你的XML文件呢?

JAXBElement myJAXBObject = (JAXBElement) rshal(bis); // 读取

YourDataType yourData = (YourDataType) alue(); // 可以用啦

// 下面是写XML的例子

Marshaller m = teMarshaller();

roperty(_FORMATTED_OUTPUT, );

File outfile = new File("");

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outfile), 4096);

hal(myJAXBObject, bos); // 一步写入。 myJAXBObject 需要你自己构建,你要存什么呢

try {

h();

} catch (IOException e) {

// TODO Auto-generated catch block

tStackTrace();

} finally {

try {

e();

} catch (Exception e) {

// TODO Auto-generated catch block

tStackTrace();

}

}

你也许意识到问题了:这一下子把XML Load到内存里,你是不是疯了?为了避免疯掉,你可以用Satx啊,那玩意儿不是流式的么?给个栗子,读取这样的XML文件片段:

<OutXMLData>
  <SubXMLItemType>
  …
  </SubXMLItemType>
  <SubXMLItemType>
  …
  </SubXMLItemType>
  <SubXMLItemType>
  …
  </SubXMLItemType>
  …
  </OutXMLData>

private static void readWriteWithStAXAndJAXB() throws FactoryConfigurationError, FileNotFoundException, XMLStreamException, UnsupportedEncodingException, JAXBException,

PropertyException {

// set up a StAX reader

XMLInputFactory xmlif = nstance();

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(""));

XMLStreamReader xmlr = teXMLStreamReader(bis);

File outfile = new File("output");

OutputStreamWriter bos = new OutputStreamWriter(new FileOutputStream(outfile), "UTF-8");

XMLOutputFactory xmlof = nstance();

XMLStreamWriter xmlw = teXMLStreamWriter(bos);

eStartDocument("UTF-8", "1.0");

eStartElement("OutXMLData");

JAXBContext ucontext = nstance(s);

Unmarshaller unmarshaller = teUnmarshaller();

Marshaller marshaller = teMarshaller();

roperty(_FORMATTED_OUTPUT, );

roperty(_FRAGMENT, );

Tag();

ire(T_ELEMENT, null, "OutXMLData");

Tag();

int iCount = 0;

while (ventType() == T_ELEMENT) { // 按标签流式读取

iCount++;

JAXBElement pt = rshal(xmlr, s); // 只读取映射SubItem的内容

hal(pt, xmlw); // 这步是分批流式写入

eCharacters(" ");

if (ventType() == ACTERS) {

();

}

}

h();

eEndElement();

eEndDocument();

tln("Entity Count is :" + iCount);

e();

e();

}

说完这么多,基本上用Java处理XML已经不是难事了。不过,有时候你会有:给你蟹八件儿,你也无从下嘴的感受。比如,解析XML你可以掌控,随便你用啥,可是你调用的下游程序接口却需要另外一种格式的数据。比如,你用Stax解析XML,下游要DOM接口会不会令你抓狂起来?心里咒骂,倒霉玩意儿,你们还有没有点上进心?!最近我就遇到这事了,解析一个大的XML,下游要Sub的XML,或者叫XML片段,或者叫分割XML文件。好么,我把数据都拆成Java的Object,然后再给你拼成一个个小的XML文件发过去,丧心病狂么这不?!你如果真这么做了,就别往下看了,你会哭的!

Java 的XML包下面有个transform的子包,看看里面会有惊喜的。可以用这个工具包帮你完成类似的转换,比如Stax 和 Sax 或者Dom 互相的变换。或者变换成Stream.

拿我这个分割XML的小栗子来说:

XMLInputFactory xif = nstance();

XMLStreamReader xsr = teXMLStreamReader(new FileReader("")); // 用Stax读取XML

Tag(); // Advance to statements element

TransformerFactory tf = nstance();

Transformer t = ransformer();

arameter(_XML_DECLARATION, "no");

arameter(DALONE, "yes");

long i = 0;

String action = null;

while (ext()) {

if (() == T_ELEMENT) {

if ("ContentItem"ls(ocalName())) {

action = getAttributeValue(xsr, "action");

} else if ("Data"ls(ocalName())) {

File file = new File("out/" + action + i++ + "");

sform(new StAXSource(xsr), new StreamResult(file)); // 流式变换,走你~

// DOMResult dr = new DOMResult(); // 如果你要Dom格式的,releaseMe

// sform(new StAXSource(xsr), dr);

}

}

}

知道最变态的是什么吗?需要解析XML整个内容到String里面,不单单是数据,就是整个XML标签和数据。其实就是ouputStream转String的过程:

ByteArrayOutputStream baos = new ByteArrayOutputStream();

sform(new StAXSource(xsr), new StreamResult(baos));

String subXMLStr = ring();