因项目需要,开始学起了Java, 还摆弄起了XML。原来有过一些其他语言的面向对象的基础,也对XML有所了解,所以心理上首先战胜了自己。但是一下Java和DOM两样新东西摆在面前 还是有点费劲。查阅了无数资料,算是有一点眉目,简要自我总结一下,也供同样面对新问题的老革命们提供一些线索。
本文并不是教程或者技术文章,仅仅个人学习中的自我体会。处于 实用的目的,本文将标准DOM模型和JDOM(javax.xml)混用,并没有分得很清楚,并暂时忽略了很多其他很优秀的parsers(如 apache的)。本文只涉及xml的创建,并没有讨论读取等。
简单回顾一下xml的要素:纯文本格式,标记将数据括起来表意,标记大小写敏感,每 个xml文档只能有一个根节点,节点(Node)类型:元素(Element)、注释(Comment)、处理指令(Processing Instruction)、CDATA、命名空间(Namespaces)、属性(Attribute)。展示如下:
<!--It's an example of XML Documents>
?
John Smith
?
?
?
|
Java提供了通 用的DOM模型和SAX模型来处理XML文档,其中SAX是只读的,而DOM则可以创建XML。需要包含地package:
javax.xml.parsers.*;
javax.xml.parsers.*;
javax.xml.transform.*;
javax.xml.transform.stream.*;
javax.xml.transform.dom.*;
org.xml.sax.*;
org.w3c.dom.*;
步骤简单叙述如下:由 DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()获 得文档对象实例。Document对象有各种方法产生对应的 Node(Element,Attribute,Comment,ProcessingInstrucion,CDATASection)。文档、节点、 子节点之间通过appendChild()方法指名父子关系。DOM树构建好之后,取得DOMSource对象,将Document对应到XML源码,然 后创建一个文件流,通过Transformer的方法将源码写入流中,我们就完成了创建XML文件的工作。
import java.io.*; import javax.xml.parsers.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.stream.*; import javax.xml.transform.dom.*; import org.xml.sax.*; import org.w3c.dom.*; public class WriteXML { ? public WriteXML(String fn) { ??? /行26-38创建了文档对象// ??? Document xmlDoc=null; ??? try { ????? //如果将这些工厂、Builder都单独获得实例将有更大的配置灵活性 ????? //但这里方便起见直接得到文档 ????? xmlDoc = DocumentBuilderFactory.newInstance(). ????????? newDocumentBuilder().newDocument(); ??? } ??? catch (FactoryConfigurationError ex) { ????? ex.printStackTrace(); ??? } ??? catch (ParserConfigurationException ex) { ????? ex.printStackTrace(); ??? } ??? 形成DOM树 ??? //下面两行加入了根节点 ??? Element bookRoot=xmlDoc.createElement("book"); ??? xmlDoc.appendChild(bookRoot); ??? //创建子节点 ??? Element title=xmlDoc.createElement("title");//节点标记名称 ??? title.appendChild(xmlDoc.createTextNode("My Story"));//节点文字内容 ??? bookRoot.appendChild(title); ??? //创建带属性节点 ??? Element author=xmlDoc.createElement("author"); ??? author.appendChild(xmlDoc.createTextNode("John Smith"));//普通文字内容 ??? Attr gender=xmlDoc.createAttribute("gender");//属性名称 ??? gender.setValue("M");//属性值 ??? author.setAttributeNode(gender);//将属性附加到节点 ??? /*上面三行和这一行的效果一样: ???? author.setAttribute("gender","M"); ??? */ ??? bookRoot.appendChild(author); ??? //创建注释 ??? Comment cmnt=xmlDoc.createComment("It's just a comment."); ??? bookRoot.appendChild(cmnt); ??? /写磁盘/ ??? Source xmlSrc=new DOMSource(xmlDoc);//获得源码 ??? //获得输出流 ??? Result rslt=null; ??? try { ????? rslt = new StreamResult(new FileOutputStream(fn)); ??? } ??? catch (FileNotFoundException ex1) { ????? ex1.printStackTrace(); ??? } ??? //转换写入 ??? Transformer tr=null; ??? try { ????? tr = TransformerFactory.newInstance().newTransformer(); ????? tr.transform(xmlSrc, rslt);//将源码转换入流 ??? } ??? catch (TransformerException ex2) { ????? ex2.printStackTrace(); ??? } ??? catch (TransformerFactoryConfigurationError ex2) { ????? ex2.printStackTrace(); ??? } ? } ? public static void main(String[] args) { ??? WriteXML xmlWriter = new WriteXML("aBook.xml");//指定文件名 ? } } |
执行,在程序所在目录下会产生一个 aBook.xml的文件,用浏览器(如IE):
?
-
?????
?????
John Smith
?????
查看用文本编辑器(如记事本,UltraEdit)查看:
John Smith
可见文本 内容不换行,只保证语义正确,格式由浏览器决定。
最后需要说明一点:Source一旦被创建就是和Document对象相关联的。Document树改变Source 自动改变,不需要我们显式做什么动作。也就是说Source不一定非要在被Transform()之前创建。当然不能期望Transformer也有这样 的效果了,因为它的目标是FileOutputStream,写上磁盘就只能继续追加了。