XML因為良好的結(jié)構(gòu),被廣泛地應(yīng)用于文檔格式的定義叉趣。我們知道烟具,應(yīng)用軟件一般需要用配置文件來決定運行時的一些參數(shù)冀痕。以前的應(yīng)用程序的配置文件一般是一個.ini文件。雖然現(xiàn)在满哪,ini文件仍然在使用勘高,但是由于XML的出現(xiàn)赖舟,越來越多的商用軟件正在把XML當作配置文件的格式子漩,如BEA的Weblogic讲衫,以及IBM的Websphere等别厘。所以,當我們設(shè)計一個軟件的配置文件時嚣艇,將會越來越多地考慮使用XML作為該配置文件的格式。
而因為配置文件有時候必須讓用戶修改秘豹,所以提供一個可視化的編輯配置文件的格式膊升,是一個軟件具有良好的用戶可交互性的體現(xiàn)瓜挽。我們必須給XML文檔找到一個可視化的方法。Java語言中的Swing組件里面的JTree佳头,用于XML文檔的可視化是非常適合的聚假。這兩者之間存在著很方便的轉(zhuǎn)換方法。這就意味著我們能將用戶在JTree上面的操作尔店,在存盤后方便地表現(xiàn)為在XML文件中的修改嚣州,也能將XML文件方便地表現(xiàn)為一棵JTree展現(xiàn)給用戶。
XML文檔的可視化
一個XML文檔其實是一個樹形的結(jié)構(gòu)阱州。比如下面這個XML文檔:
<?xml version=“1.0”encoding=“GB2312”?>
<skin>
<skin1>
<name>古典</name>
<dir>d:\software\App\skin</dir>
<head>head1.bmp</head>
<center>center1.bmp</center>
<foot>foot1.bmp</foot>
</skin1>
<skin2>
<name>現(xiàn)代</name>
<dir>d:\software\App\skin</dir>
<head>head2.bmp</head>
<center>center2.bmp</center>
<foot>foot2.bmp</foot>
</skin2>
</skin>
可以看得出來鹊汛,該XML文檔是一個多界面程序的界面圖片配置程序至耻,如果將該XML文檔可視化疤苹,那么使用JTree的話應(yīng)該得到的是如下圖所示的結(jié)果涂滴。
所有的XML文檔壮吩,都能夠生成這樣一個Jtree进苍。使用XML的Parser和Java里的JTree類,可以構(gòu)造出一個通用的可視化XML文檔從而構(gòu)成一棵JTree鸭叙。XML Parser對XML文檔解析的結(jié)果是生成一顆DOM(Document Object Model)樹觉啊,DOM樹的結(jié)構(gòu)和JTree的結(jié)構(gòu)其實是一樣的,這使JTree和XML Parser的配合非常自然沈贝。下面就介紹一下做法杠人。
一個讀寫XML文件的類
首先必須獲得XML Parser的包,可以從下面的地址獲得:http://xml.apache.org/xerces2-j/index.html宋下。
然后設(shè)計一個XMLTree的類嗡善,繼承自JTree類的定義和成員變量,函數(shù)定義如下:
public class XMLTree extends JTree{
private DefaultMutableTreeNode treeNode; //JTree的根節(jié)點
private DocumentBuilderFactory dbf;
// 這三個成員變量是xml parser需要的
private DocumentBuilder db;
private Document doc;
XMLTree(String fileName);
//構(gòu)造函數(shù)学歧,做初始化工作
public DefaultMutableTreeNode LoadFile(Node root);
//從某個XML文件生成該樹
public void SaveToFile(DefaultMutableTreeNode root,FileWriter fw);
//將該樹存盤成XML文件
private Node parseXml( String text )
}
其中構(gòu)造函數(shù)所做的初始化工作如下:
XMLTree(String fileName){
dbf = DocumentBuilderFactory.newInstance();
//生成dbf的實例
db = dbf.newDocumentBuilder();
//生成db的實例
treeNode = LoadFile( getXMLRoot( text ) );
//解析該xml文件罩引,返回JTree的根節(jié)點
setModel( new DefaultTreeModel( treeNode ) );
//根據(jù)該根節(jié)點生成JTree
}
其中,parseXml是一個返回XML文件根元素的程序枝笨,如下:
private Node getXMLRoot( String text ){
ByteArrayInputStream byteStream;
byteStream = new ByteArrayInputStream( text.getBytes() );
//將XML文件讀到Stream里去
try{
doc = db.parse( byteStream );
//解析該xml文件袁铐。
} catch ( Exception e )
{ e.printStackTrace();}
return ( Node )doc.getDocumentElement();
//返回該XML文件的DOM樹的根元素
}
核心部分的LoadFile是一個遞歸過程,如下:
private DefaultMutableTreeNode createTreeNode( Node root ){
DefaultMutableTreeNode treeNode = null;
//定義要返回的根節(jié)點
String name = root.getNodeName();
//獲得該節(jié)點的NodeName
String value = root.getNodeValue();
//獲得該節(jié)點的NodeValue
treeNode = new DefaultMutableTreeNode( root.
getNodeType() == Node.TEXT_NODE ? value : name );
//如果為值節(jié)點横浑,那么取得該節(jié)點的值剔桨,否則取得該節(jié)點的Tag的名字
if ( root.hasChildNodes() )
//如果該節(jié)點有孩子節(jié)點,那么遞歸處理該節(jié)點的孩子節(jié)點
{ NodeList children = root.getChildNodes();
//取得該節(jié)點的子節(jié)點列表
if( children != null ){
//判斷子節(jié)點是否為空
int numChildren = children.getLength();
//取得字節(jié)數(shù)目
for (int i=0; i < numChildren; i++){
Node node = children.item(i);
//循環(huán)處理每個子節(jié)點
if( node != null )
{ if( node.getNodeType() == Node.ELEMENT_NODE )
{ treeNode.add( createTreeNode(node) );
//如果該子節(jié)點還有孩子節(jié)點使用遞歸的方法處理該子節(jié)點
} else {
String data = node.getNodeValue();
if( data != null )
{
data = data.trim();
if ( !data.equals(“\n”) && !data.equals(“\r\n”) &&
data.length() > 0 )
{ treeNode.add(new
DefaultMutableTreeNode(node.getNodeValue()));
//如果該節(jié)點沒有孩子節(jié)點徙融,那么直接加到節(jié)點下
}
}
}
}
}
}
}
return treeNode; //返回節(jié)點 }
使用Java的Swing包里的方法能夠很容易地在JTree上做改動洒缀,可以使用彈出對話框的方法,也可以直接在JTree上改動张咳〉酆椋總之似舵,JTree改動后,需要重新寫回文件中去將一棵JTree寫成XML文件是一個遞歸的過程葱峡,方法如下:
public void SaveToFile(DefaultMutableTreeNode, FileWriter fw)
{try {
if (root.isLeaf()) fw.write(root.toString()+“\r\n”);
//如果是葉子節(jié)點則直接將該節(jié)點輸出到文件中
else { //不是葉子節(jié)點的話遞歸輸出該節(jié)點
fw.write(“<”+root.toString()+“>\r\n”);
for (int i=0; i < root.getChildCount(); i++)
{ DefaultMutableTreeNode childNode =(DefaultMutableTreeNode)
root.getChildAt(i);
saveFile(childNode, fw);
//遞歸輸出該節(jié)點的所有子節(jié)點 }
fw.write(“</”+root.toString()+“>\r\n”);
}
} catch (Exception e)
{ e.printStackTrace();
} }
必須注意的是砚哗,如果XML文件中包含中文,那么需要在調(diào)用上面的函數(shù)之前砰奕,先在文件中輸入該XML文件的編碼方式蛛芥,方法如下:
fw.write(“<?xml version=“1.0” encoding=“GB2312”?>\r\n”);
在調(diào)用該函數(shù)結(jié)束后,還應(yīng)該關(guān)閉該文件军援,方法是:
fw.close()
結(jié)論
XML文件廣泛地運用于配置文件仅淑、信息傳遞中。它的可視化方法有很多胸哥,本文通過結(jié)合Java的JTree類涯竟,介紹了其中一種實現(xiàn)方法。Java語言和XML的良好結(jié)合空厌,讓使用Java編制XML程序既靈活又方便庐船。