XML文檔和JTree之間如何轉(zhuǎn)換

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é)果涂滴。

圖 可視化結(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程序既靈活又方便庐船。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市嘲更,隨后出現(xiàn)的幾起案子筐钟,更是在濱河造成了極大的恐慌,老刑警劉巖赋朦,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篓冲,死亡現(xiàn)場離奇詭異,居然都是意外死亡宠哄,警方通過查閱死者的電腦和手機壹将,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琳拨,“玉大人瞭恰,你說我怎么就攤上這事∮樱” “怎么了惊畏?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長密任。 經(jīng)常有香客問我颜启,道長,這世上最難降的妖魔是什么浪讳? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任缰盏,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘口猜。我一直安慰自己负溪,他們只是感情好,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布济炎。 她就那樣靜靜地躺著川抡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪须尚。 梳的紋絲不亂的頭發(fā)上崖堤,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天,我揣著相機與錄音耐床,去河邊找鬼密幔。 笑死,一個胖子當著我的面吹牛撩轰,可吹牛的內(nèi)容都是我干的胯甩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钧敞,長吁一口氣:“原來是場噩夢啊……” “哼蜡豹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起溉苛,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弄诲,沒想到半個月后愚战,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡齐遵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年寂玲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梗摇。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡拓哟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出伶授,到底是詐尸還是另有隱情断序,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布糜烹,位于F島的核電站违诗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏疮蹦。R本人自食惡果不足惜诸迟,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阵苇,春花似錦壁公、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至趁怔,卻和暖如春湿硝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背润努。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工关斜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铺浇。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓痢畜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鳍侣。 傳聞我的和親對象是個殘疾皇子丁稀,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)倚聚,斷路器线衫,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法惑折,內(nèi)部類的語法授账,繼承相關(guān)的語法,異常的語法惨驶,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,156評論 25 707
  • 開始記錄... 1白热,我們的目錄結(jié)構(gòu)大概是這樣: 2,index.html文件內(nèi)容粗卜,加載require庫文件屋确,看到d...
    相睡恨晚閱讀 708評論 0 2
  • 父親說,字如其人续扔,寫字要一筆一畫攻臀,一絲不茍,做人也要頂天立地测砂,堂堂正正茵烈。 1 父親愛習字,這是我打小便知道的“秘密...
    權(quán)當歡喜閱讀 538評論 18 25