文章详情页
使用Java Swing 创建一个XML编辑器
浏览:4日期:2024-06-22 15:25:15
内容: 出自:yesky我想您一定对XML有所了解,说不定您现在还跃跃欲试想写一段XML文本呢,可是现在能找到的跨平台的、免费的XML编辑器太少了。所以在本文中,我想介绍一下或者说带您一步一步的开发一个简单的XML编辑器,当然我们要用到一些最常见的Java 2 Swing组件,不过这些都是免费的,有些是JDK中的,有些是可以从网上下载的。我想通过本文,你就可以创建一个属于你自己的XML编辑器。先让我介绍一下本文辑写的思路。首先我想简要的讨论一下XML和为什么树型结构比较适合用来显示XML,然后我们来看一看JAXP API如何建立所需要的XML类的环境;然后我们将了解用来显示一个图形树的JTree Swing组件;最后,我们将创建一个继承JTree组件的可以重复使用的类,可以用来分析一个XML文档,并把数据显示在一个Jtree中。说到XML(eXtensible Markup Languge),人们往往把它当成是一种新的用于Web浏览器中的标记语言,就象HTML或CSS一样。其实,XML是一种数据表示语言,它允许你使用一种非常有效的方法来描述你的数据。XML能够使你定义诸如“these three words constitutes a heading这样的语句。XML允许你声明任何类型的数据,而不是用来把这些数据显示在网页中。请看一看下面的XML实例:<article><header><title> 使用Java Swing 创建一个XML编辑器<subtitle> 第一部分</subtitle></title><author> Wayne </author><header><content> 这是正文</content></article>请注意,这些元素和标准的HTML语句是不同的,但是它们看上去比较象HTML,这是因为XML和HTML都是来源于SGML语言。不同的是HTML有预定义的标签集,而XML的语法则有许多灵活性,它允许你使用表意的标记如<author>来括在数据两边。你还要注意,所有的元素都从属于根元素(上例中为<article>),有些元素则还有自己的子元素,如<subtitle>就是<title>的子元素。这样的数据组织方式有三个好处:数据能够更加表意,数据更加易维护而且数据更加容易作为一个树的结构表现出来,这就是我们为什么使用JTree对象来显示XML数据的原因。如果你想对XML有更深的了解,请参阅天极网上的相关教程。JAXP是一个用于处理XML的Java API,它能够使应用程序分析并且转化XML文档,它的功能有点象JDBC API,都是把函数功能抽象成一个个方法。你可以去Apache网站找到最新的Xerces分析器,其中含有最新的JAXP,下载下来以后把它放在你的类目录中。下面让我们看一下如何使用JTree Swing组件。我们都知道,在自然界中,一棵树通常都有一个非常粗的树干,树干上有许多树枝分叉。每个树杈和树杈之间都有一定的联系,因为它们都有同一个来源:树干。这种继承的关系并不只在树枝中有,人类谱系也遵循相同的规律。从父母,到子女再到子女的子女,就这样直到数不清为止。同样,在数据存储中,树的概念也是一种使用同人类家谱树一样方法储存数据的方法。树的每一个树杈称为一个节点,每个有子节点的节点称为父节点,所有的子节点的公共的父节点被称为根节点。一个JTree组件就是一个简单的树数据结构的可视化表现形式。几乎所有的XML编辑器都包括一个可视化的树结构,能让你编辑XML文档中的元素。我们马上就会构建一个编辑器,不过在此之前,先让我们再了解一下JTree组件。一个节点在一棵树的某个位置储存数据,为了存储数据,必须知道任何一个父节点和它们的子节点。javax.swing.tree包定义了一些非常有用的接口,提供了一种通用的方法构建和操作一个树结构。TreeNode方法,用于访问树的节点的信息MutableTreeNode方法 用在一个可变的树上(能够添加或删除子节点)TreeModel方法 用于创建和管理与树有关的数据模型。接下来,我们将创建一个继承JTree的类,提供分析XML文档和用可视化JTree组件把节点显示出来的功能。创建XTree组件XTree类由一个构造函数和三个方法组成,为了简单起见我们的组件只能构建一个Xtree,在树创建好之后不能进行处理它的节点。下面让我们来看一个这个类。域:private DefaultMutableTreeNode treeNode 这个成员变量储存TreeNode对象用于存储JTree的模型。 DefaultMutableTreeNode类是在javax.swing.tree中被定义的,默认提供了MutableTreeNode接口的一个实现。private DocumentBuilderFactory dbfprivate DocumentBuilder dbprivate Document doc 这三个成员变量是JAXP的一部分,用来分析XML文本并转化成DOM(Document Object Model) 对象。构造函数public XTree( String text )这个构造函数通过使用传送到构造器中的XML文本创建一个XTree对象。在初始化一些与JTree超类和DOM分析对象有关的基本显示属性后,构造函数生成一个TreeModel 对象用来创建一个实际可视的树。通过把DOM对象传送到createTreeNode()方法来创建一个根节点,createTreeNode()方法返回一个DefaultMutableTreeNode类型的对象。这个对象然后被用来创建树的TreeModel。方法 private DefaultMutableTreeNode createTreeNode( Node root )这个方法采用一个DOM 节点,然后在子节点中递归直到所有的接点都被添加到DefaultMutableTreeNode中。这是一个递归方法,为了找到根节点下的每一个子节点,它每次都要调用自己。JTree然后就可以使用DefaultMutableTreeNode对象了,因为它已经是树型了。 private String getNodeType( Node node )这个方法,被createTreeNode()用来联系一个字符串和某一种类型的节点。 private Node parseXml()这个方法,用来分析XML文本字符串,它返回Node类型的对象,能够被传送到createTreeNode()方法中。 下面我给出了java代码,供大家分析研究。 // 到入W3C的DOM 类import org.w3c.dom.*;// JAXP的用于DOM I/O的类import javax.xml.parsers.*;// 标准Java类import javax.swing.*;import javax.swing.tree.*;import javax.swing.event.*;import java.awt.*;import java.awt.event.*;import java.io.*;public class XTree extends JTree{/*** 这个成员变量储存TreeNode对象用于存储JTree的模型。*DefaultMutableTreeNode类是在javax.swing.tree中被定义的*默认提供了MutableTreeNode接口的一个实现。*/private DefaultMutableTreeNode treeNode;/*** 这三个成员变量是JAXP的一部分,用来分析XML文本并转化成DOM(Document Object Model) 对象。*/private DocumentBuilderFactory dbf;private DocumentBuilder db;private Document doc; /** * 这个构造函数通过使用传送到构造器中的XML文本创建一个XTree对象 * @参数 text是一个XML格式的XML文本 * @异常 ParserConfigurationException 如果构造函数非正常的设置分析器,就会抛出异常 */public XTree( String text ) throws ParserConfigurationException{super();// 设置Tree渲染的基本属性getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION );setShowsRootHandles( true );setEditable( false ); // 允许树可以编辑// 通过初始化对象的DOM来分析对象dbf = DocumentBuilderFactory.newInstance();dbf.setValidating( false );db = dbf.newDocumentBuilder();// 采用DOM根节点并且把它转化成JTree的树模型treeNode = createTreeNode( parseXml( text ) );setModel( new DefaultTreeModel( treeNode ) );} file://中止XTree()/*** 这个方法采用一个DOM 节点,然后在子节点中递归直到所有的接点都被添加到DefaultMutableTreeNode中。* 这是一个递归方法,为了找到根节点下的每一个子节点,它每次都要调用自己。* JTree然后就可以使用DefaultMutableTreeNode对象了,因为它已经是树型了。** @参数 root org.w3c.Node.Node** @返回值 返回一个基于根节点DefaultMutableTreeNode对象*/private DefaultMutableTreeNode createTreeNode( Node root ){DefaultMutableTreeNode treeNode = null;String type, name, value;NamedNodeMap attribs;Node attribNode;// 从根节点中取得数据type = getNodeType( root );name = root.getNodeName();value = root.getNodeValue();treeNode = new DefaultMutableTreeNode( root.getNodeType() == Node.TEXT_NODE ? value : name );// 显示属性attribs = root.getAttributes();if( attribs != null ){for( int i = 0; i < attribs.getLength(); i++ ){attribNode = attribs.item(i);name = attribNode.getNodeName().trim();value = attribNode.getNodeValue().trim();if ( value != null ){if ( value.length() > 0 ){treeNode.add( new DefaultMutableTreeNode( ' Attribute --> ' + name + '='' + value + ''' ) );} file://end if ( value.length() > 0 )} file://end if ( value != null )} file://end for( int i = 0; i < attribs.getLength(); i++ )} file://end if( attribs != null )// 如果存在子节点,递归if( root.hasChildNodes() ){NodeList children;int numChildren;Node node;String data;children = root.getChildNodes();// 如果子节点非空的话,只递归if( children != null ){numChildren = children.getLength();for (int i=0; i < numChildren; i++){node = children.item(i);if( node != null ){if( node.getNodeType() == Node.ELEMENT_NODE ){treeNode.add( createTreeNode(node) );} file://end if( node.getNodeType() == Node.ELEMENT_NODE )data = node.getNodeValue();if( data != null ){data = data.trim();if ( !data.equals('n') && !data.equals('rn') && data.length() > 0 ){treeNode.add(createTreeNode(node));} file://end if ( !data.equals('n') && !data.equals('rn') && data.length() > 0 )} file://end if( data != null )} file://end if( node != null )} file://end for (int i=0; i < numChildren; i++)} file://end if( children != null )} file://end if( root.hasChildNodes() )return treeNode;} file://end createTreeNode( Node root )/*** 这个方法,被createTreeNode()用来联系一个字符串和某一种类型的节点。** @参数 node org.w3c.Node.Node** @返回值 返回显示节点类的字符串*/private String getNodeType( Node node ){String type;switch( node.getNodeType() ){case Node.ELEMENT_NODE:{type = 'Element';break;}case Node.ATTRIBUTE_NODE:{type = 'Attribute';break;}case Node.TEXT_NODE:{type = 'Text';break;}case Node.CDATA_SECTION_NODE:{type = 'CData section';break;}case Node.ENTITY_REFERENCE_NODE:{type = 'Entity reference';break;}case Node.ENTITY_NODE:{type = 'Entity';break;}case Node.PROCESSING_INSTRUCTION_NODE:{type = 'Processing instruction';break;}case Node.COMMENT_NODE:{type = 'Comment';break;}case Node.DOCUMENT_NODE:{type = 'Document';break;}case Node.DOCUMENT_TYPE_NODE:{type = 'Document type';break;}case Node.DOCUMENT_FRAGMENT_NODE:{type = 'Document fragment';break;}case Node.NOTATION_NODE:{type = 'Notation';break;}default:{type = '???';break;}}// 结束 switch( node.getNodeType() )return type;} file://结束 getNodeType()/*** 这个方法,用来分析XML文本字符串,它返回Node类型的对象,能够被传送到createTreeNode()方法中。** @参数 text 一个显示XML文档的字符串* @返回值 返回一个org.w3c.Node.Node对象*/private Node parseXml( String text ){ByteArrayInputStream byteStream;byteStream = new ByteArrayInputStream( text.getBytes() );try{doc = db.parse( byteStream );}catch ( Exception e ){e.printStackTrace();System.exit(0);}return ( Node )doc.getDocumentElement();} file://结束 parseXml()} file://结束 class XTree代码2 XTreeTester.javaimport javax.xml.parsers.*;// GUI类import javax.swing.*;import java.awt.*;import java.awt.event.*;file://标准 Java类import java.io.*;public class XTreeTester extends JFrame{// XTree对象,用来在JTree中显示XMLprivate XTree xTree;// JScrollPane是JTree的容器private JScrollPane jScroll;private WindowListener winClosing;// 设置框架的宽和高private static final int FRAME_WIDTH = 400;private static final int FRAME_HEIGHT = 300;/** 构造器构造一个框架包含JScrollPane,* 把一个基于XML字符串的XTree对象传到构造函数中*/public XTreeTester( String title, String xml ) throws ParserConfigurationException{super( title );Toolkit toolkit;Dimension dim, minimumSize;int screenHeight, screenWidth;// 初始化基本的布局属性setBackground( Color.lightGray );getContentPane().setLayout( new BorderLayout() );toolkit = Toolkit.getDefaultToolkit();dim = toolkit.getScreenSize();screenHeight = dim.height;screenWidth = dim.width;setBounds( (screenWidth-FRAME_WIDTH)/2, (screenHeight-FRAME_HEIGHT)/2, FRAME_WIDTH, FRAME_HEIGHT );// 构建XTree对象xTree = new XTree( xml );file://把XTree封装到JScroll中,以便在JFrame可以使它在屏幕中上下滚动.jScroll = new JScrollPane();jScroll.getViewport().add( xTree );// 添加滚动条到框架中getContentPane().add( jScroll, BorderLayout.CENTER );validate();setVisible(true);// 添加WindowListener用来关闭窗口winClosing = new WindowAdapter(){public void windowClosing(WindowEvent e){exit();}};addWindowListener(winClosing);}// 程序从这里开始执行。必须把一个以xml为扩展名的XML文件传送到这个方法中,其格式为java XTreeTester yourxmlfilename.xmlpublic static void main( String[] args ){String fileName = '';BufferedReader reader;String line;StringBuffer xmlText;XTreeTester xTreeTester;// 创建一个基于特定XML文件的文档对象try{if( args.length > 0 ){fileName = args[0];if ( fileName.substring( fileName.indexOf( '.' ) ).equals( '.xml' ) ){reader = new BufferedReader( new FileReader( fileName ) );xmlText = new StringBuffer();while ( ( line = reader.readLine() ) != null ){xmlText.append( line );}// 分析完文档对象后将重写文件reader.close();// 构造 GUI 组件xTreeTester = new XTreeTester( 'XTree 测试', xmlText.toString() );}else{help();}}else{help();}}catch( FileNotFoundException fnfEx ){System.out.println( '没有发现'+ fileName + '文件。' );exit();}catch( Exception ex ){ex.printStackTrace();exit();}}file://帮助信息private static void help(){System.out.println( 'n使用方法:java XTreeTester yourxmlfilename.xml' );System.exit(0);}// 退出private static void exit(){System.out.println( 'n谢谢使用 XTree' );System.exit(0);} } Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd
标签:
Java
相关文章:
1. HTML中的XML数据岛记录编辑与添加2. Android 在 res/layout 文件夹 下创建一个 子文件夹实例3. 详解idea文件右键创建New没有Create New Servlet的解决办法4. asp文件用什么软件编辑5. 解决Android Studio XML编辑界面不显示下面的Text和Design选项卡6. 利用CSS3新特性创建透明边框三角7. 关于Java中String创建的字符串对象内存分配测试问题8. PHP swoole的process模块创建和使用子进程操作示例9. xml创建节点(根节点、子节点)10. React基础-JSX的本质-虚拟DOM的创建过程实例分析
排行榜