XML文档和JTree之间如何转换

XML因为良好的结构,被广泛地应用于文档格式的定义。我们知道,应用软件一般需要用配置文件来决定运行时的一些参数。以前的应用程序的配置文件一般是一个.ini文件。虽然现在,ini文件仍然在使用,但是由于XML的出现,越来越多的商用软件正在把XML当作配置文件的格式,如BEA的Weblogic,以及IBM的Websphere等。所以,当我们设计一个软件的配置文件时,将会越来越多地考虑使用XML作为该配置文件的格式。

而因为配置文件有时候必须让用户修改,所以提供一个可视化的编辑配置文件的格式,是一个软件具有良好的用户可交互性的体现。我们必须给XML文档找到一个可视化的方法。Java语言中的Swing组件里面的JTree,用于XML文档的可视化是非常适合的。这两者之间存在着很方便的转换方法。这就意味着我们能将用户在JTree上面的操作,在存盘后方便地表现为在XML文件中的修改,也能将XML文件方便地表现为一棵JTree展现给用户。

XML文档的可视化

一个XML文档其实是一个树形的结构。比如下面这个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>现代</name>
    <dir>d:\software\App\skin</dir>
    <head>head2.bmp</head>
    <center>center2.bmp</center>
    <foot>foot2.bmp</foot>
  </skin2>
</skin>

可以看得出来,该XML文档是一个多界面程序的界面图片配置程序,如果将该XML文档可视化,那么使用JTree的话应该得到的是如下图所示的结果。

图 可视化结果

所有的XML文档,都能够生成这样一个Jtree。使用XML的Parser和Java里的JTree类,可以构造出一个通用的可视化XML文档从而构成一棵JTree。XML Parser对XML文档解析的结果是生成一颗DOM(Document Object Model)树,DOM树的结构和JTree的结构其实是一样的,这使JTree和XML Parser的配合非常自然。下面就介绍一下做法。

一个读写XML文件的类

首先必须获得XML Parser的包,可以从下面的地址获得:http://xml.apache.org/xerces2-j/index.html
然后设计一个XMLTree的类,继承自JTree类的定义和成员变量,函数定义如下:

public class XMLTree extends JTree{   
    private           DefaultMutableTreeNode      treeNode;  //JTree的根节点
    private           DocumentBuilderFactory    dbf; 
    // 这三个成员变量是xml parser需要的
    private           DocumentBuilder       db; 
    private           Document              doc;  
    XMLTree(String fileName);  
    //构造函数,做初始化工作
    public DefaultMutableTreeNode LoadFile(Node root);     
    //从某个XML文件生成该树
    public void SaveToFile(DefaultMutableTreeNode root,FileWriter fw);     
    //将该树存盘成XML文件
    private Node parseXml( String text )
}

其中构造函数所做的初始化工作如下:

XMLTree(String fileName){
      dbf = DocumentBuilderFactory.newInstance(); 
      //生成dbf的实例
      db = dbf.newDocumentBuilder();  
      //生成db的实例
      treeNode = LoadFile( getXMLRoot( text ) );  
      //解析该xml文件,返回JTree的根节点
      setModel( new DefaultTreeModel( treeNode ) );  
      //根据该根节点生成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; 
         //定义要返回的根节点
      String name = root.getNodeName();
         //获得该节点的NodeName
         String value = root.getNodeValue(); 
         //获得该节点的NodeValue
     treeNode = new DefaultMutableTreeNode( root.
getNodeType() == Node.TEXT_NODE ? value : name );
      //如果为值节点,那么取得该节点的值,否则取得该节点的Tag的名字 
      if ( root.hasChildNodes() ) 
      //如果该节点有孩子节点,那么递归处理该节点的孩子节点
      {  NodeList children = root.getChildNodes();  
        //取得该节点的子节点列表
         if( children != null ){       
         //判断子节点是否为空
          int numChildren = children.getLength();  
           //取得字节数目
            for (int i=0; i < numChildren; i++){  
               Node node = children.item(i); 
                  //循环处理每个子节点
               if( node != null )
               {  if( node.getNodeType() == Node.ELEMENT_NODE )
                  { treeNode.add( createTreeNode(node) ); 
                  //如果该子节点还有孩子节点使用递归的方法处理该子节点
                  } 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()));
                       //如果该节点没有孩子节点,那么直接加到节点下
                       }   
                   }  
                 } 
               } 
            }
         }
      } 
      return treeNode;  //返回节点 }

使用Java的Swing包里的方法能够很容易地在JTree上做改动,可以使用弹出对话框的方法,也可以直接在JTree上改动。总之,JTree改动后,需要重新写回文件中去将一棵JTree写成XML文件是一个递归的过程,方法如下:

public void SaveToFile(DefaultMutableTreeNode, FileWriter fw)
    {try {
      if (root.isLeaf()) fw.write(root.toString()+“\r\n”); 
//如果是叶子节点则直接将该节点输出到文件中
     else { //不是叶子节点的话递归输出该节点
      fw.write(“<”+root.toString()+“>\r\n”); 
     for (int i=0; i < root.getChildCount(); i++)
       { DefaultMutableTreeNode childNode =(DefaultMutableTreeNode) 
root.getChildAt(i);
         saveFile(childNode, fw); 
         //递归输出该节点的所有子节点 }
   fw.write(“</”+root.toString()+“>\r\n”);
    }
      } catch (Exception e)
      {  e.printStackTrace();
      } }

必须注意的是,如果XML文件中包含中文,那么需要在调用上面的函数之前,先在文件中输入该XML文件的编码方式,方法如下:

fw.write(“<?xml version=“1.0” encoding=“GB2312”?>\r\n”);

在调用该函数结束后,还应该关闭该文件,方法是:

fw.close()

结论

XML文件广泛地运用于配置文件、信息传递中。它的可视化方法有很多,本文通过结合Java的JTree类,介绍了其中一种实现方法。Java语言和XML的良好结合,让使用Java编制XML程序既灵活又方便。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,380评论 25 707
  • 开始记录... 1,我们的目录结构大概是这样: 2,index.html文件内容,加载require库文件,看到d...
    相睡恨晚阅读 693评论 0 2
  • 父亲说,字如其人,写字要一笔一画,一丝不苟,做人也要顶天立地,堂堂正正。 1 父亲爱习字,这是我打小便知道的“秘密...
    权当欢喜阅读 525评论 18 25