首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 冲浪宝典-> 网页浏览
在JAVA中使用文档对象模型DOM经验小结-JSP教程,Java技巧及代码
作者:网友供稿 点击:727
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 
文档对象模型 (dom) 是一个文档标准,对于完备的文档和复杂的应用程序,dom 提供了大量灵活性。dom标准是标准的。它很强壮且完整,并且有许多实现。这是许多大型安装的决定因素--特别是对产品应用程序,以避免在api发生改变时进行大量的改写。
以上是我在选择处理xml数据时之所以没有选择jdom或者dom4j等其它面向对象的标准的原因,不过也由于dom从一开始就是一种与语言无关的模型,而且它更趋向用于像c或perl这类语言,没有利用java的面向对象的性能,所以在使用的过程中也遇到了不少的麻烦,今天这里做一个小结。另外,我目前使用xml主要是作为数据传输的统一格式,并统一用户界面展示的接口,应用的面并不是很广,所以使用到的dom的内容其实不多。
在准备使用它的时候,是做了充足的准备的,也有遇到困难的准备,所以一开始就有了一个简单的工具类来封装dom对象使用时必要的公共方法,实际证明这样做是很明智的,一个简单的创建document对象的操作,要是每次都需要写上5行以上代码,并且还要处理那些烦人的exception,实在是会打击大家的积极性,所以在最初,做了一个xmltool类,专门封装了如下的公共方法:
1、 document对象创建(包括空的document对象创建,以一个给定node节点作为根节点创建。
2、 将一个规范的xml字符串转换成一个document对象。
3、 从物理硬盘读取一个xml文件并返回一个document对象。
4、 将一个node对象转换成字符串。

其中每个方法都截获相关的dom操作所抛出的异常,转换成一个runtimeexception抛出,这些异常在实际使用过程中,一般状况下其实都不会抛出,特别是象生成一个document对象时的parserconfigurationexception、转换node节点成字符串时要生成一个transformer对象时的transformerconfigurationexception等等,没有必要在它们身上花时间精力。而且真就出了相关的异常的话,其实根本没有办法处理,这样的状况通常是系统环境配置有问题(比如必要的dom实现解析器等包没有加入环境),所以包装该异常时只是很简要的获取其message抛出。
代码如下:
/**
* 初始化一个空document对象返回。
* @return a document
*/
public static document newxmldocument() {
try {
return newdocumentbuilder().newdocument();
} catch (parserconfigurationexception e) {
throw new runtimeexception(e.getmessage());
}
}

/**
* 初始化一个documentbuilder
* @return a documentbuilder
* @throws parserconfigurationexception
*/
public static documentbuilder newdocumentbuilder()
throws parserconfigurationexception {
return newdocumentbuilderfactory().newdocumentbuilder();
}

/**
* 初始化一个documentbuilderfactory
* @return a documentbuilderfactory
*/
public static documentbuilderfactory newdocumentbuilderfactory() {
documentbuilderfactory dbf = documentbuilderfactory.newinstance();
dbf.setnamespaceaware(true);
return dbf;
}
/**
* 将传入的一个xml string转换成一个org.w3c.dom.document对象返回。
* @param xmlstring 一个符合xml规范的字符串表达。
* @return a document
*/
public static document parsexmldocument(string xmlstring) {
if (xmlstring == null) {
throw new illegalargumentexception();
}
try {
return newdocumentbuilder().parse(
new inputsource(new stringreader(xmlstring)));
} catch (exception e) {
throw new runtimeexception(e.getmessage());
}
}

/**
* 给定一个输入流,解析为一个org.w3c.dom.document对象返回。
* @param input
* @return a org.w3c.dom.document
*/
public static document parsexmldocument(inputstream input) {
if (input == null) {
throw new illegalargumentexception("参数为null!");
}
try {
return newdocumentbuilder().parse(input);
} catch (exception e) {
throw new runtimeexception(e.getmessage());
}
}
/**
* 给定一个文件名,获取该文件并解析为一个org.w3c.dom.document对象返回。
* @param filename 待解析文件的文件名
* @return a org.w3c.dom.document
*/
public static document loadxmldocumentfromfile(string filename) {
if (filename == null) {
throw new illegalargumentexception("未指定文件名及其物理路径!");
}
try {
return newdocumentbuilder().parse(new file(filename));
} catch (saxexception e) {
throw new illegalargumentexception(
"目标文件(" + filename + ")不能被正确解析为xml!\n" + e.getmessage());
} catch (ioexception e) {
throw new illegalargumentexception(
"不能获取目标文件(" + filename + ")!\n" + e.getmessage());
} catch (parserconfigurationexception e) {
throw new runtimeexception(e.getmessage());
}
}
/**
* 给定一个节点,将该节点加入新构造的document中。
* @param node a document node
* @return a new document
*/
public static document newxmldocument(node node) {
document doc = newxmldocument();
doc.appendchild(doc.importnode(node, true));
return doc;
}

/**
* 将传入的一个dom node对象输出成字符串。如果失败则返回一个空字符串""。
* @param node dom node 对象。
* @return a xml string from node
*/
public static string tostring(node node) {
if (node == null) {
throw new illegalargumentexception();
}
transformer transformer = newtransformer();
if (transformer != null) {
try {
stringwriter sw = new stringwriter();
transformer.transform(
new domsource(node),
new streamresult(sw));
return sw.tostring();
} catch (transformerexception te) {
throw new runtimeexception(te.getmessage());

}
}
return errxmlstring("不能生成xml信息!");
}
/**
* 将传入的一个dom node对象输出成字符串。如果失败则返回一个空字符串""。
* @param node dom node 对象。
* @return a xml string from node
*/
public static string tostring(node node) {
if (node == null) {
throw new illegalargumentexception();
}
transformer transformer = newtransformer();
if (transformer != null) {
try {
stringwriter sw = new stringwriter();
transformer.transform(
new domsource(node),
new streamresult(sw));
return sw.tostring();
} catch (transformerexception te) {
throw new runtimeexception(te.getmessage());

}
}
return errxmlstring("不能生成xml信息!");
}
/**
* 获取一个transformer对象,由于使用时都做相同的初始化,所以提取出来作为公共方法。
* @return a transformer encoding gb2312
*/
public static transformer newtransformer() {
try {
transformer transformer =
transformerfactory.newinstance().newtransformer();
properties properties = transformer.getoutputproperties();
properties.setproperty(outputkeys.encoding, "gb2312");
properties.setproperty(outputkeys.method, "xml");
properties.setproperty(outputkeys.version, "1.0");
properties.setproperty(outputkeys.indent, "no");
transformer.setoutputproperties(properties);
return transformer;
} catch (transformerconfigurationexception tce) {
throw new runtimeexception(tce.getmessage());
}
}
/**
* 返回一段xml表述的错误信息。提示信息的title为:系统错误。之所以使用字符串拼装,主要是这样做一般
* 不会有异常出现。
* @param errmsg 提示错误信息
* @return a xml string show err msg
*/
public static string errxmlstring(string errmsg) {
stringbuffer msg = new stringbuffer(100);
msg.append("<?xml version=\"1.0\" encoding=\"gb2312\" ?>");
msg.append("<errnode title=\"系统错误\" errmsg=\"" + errmsg + "\"/>");
return msg.tostring();
}
/**
* 返回一段xml表述的错误信息。提示信息的title为:系统错误
* @param errmsg 提示错误信息
* @param errclass 抛出该错误的类,用于提取错误来源信息。
* @return a xml string show err msg
*/
public static string errxmlstring(string errmsg, class errclass) {
stringbuffer msg = new stringbuffer(100);
msg.append("<?xml version=\"1.0\" encoding=\"gb2312\" ?>");
msg.append(
"<errnode title=\"系统错误\" errmsg=\""
+ errmsg
+ "\" errsource=\""
+ errclass.getname()
+ "\"/>");
return msg.tostring();
}
/**
* 返回一段xml表述的错误信息。
* @param title 提示的title
* @param errmsg 提示错误信息
* @param errclass 抛出该错误的类,用于提取错误来源信息。
* @return a xml string show err msg
*/
public static string errxmlstring(
string title,
string errmsg,
class errclass) {
stringbuffer msg = new stringbuffer(100);
msg.append("<?xml version=\"1.0\" encoding=\"gb2312\" ?>");
msg.append(
"<errnode title=\""
+ title
+ "\" errmsg=\""
+ errmsg
+ "\" errsource=\""
+ errclass.getname()
+ "\"/>");
return msg.tostring();
}

以上都是dom的基本应用,所以就不一一详细说明了。
在实际使用过程中,有几种状况使用很频繁,但是dom的接口的设计却使该操作很麻烦,所以分别添加了相应的处理方法。
其中最麻烦的要数获取一个节点的text子节点文本信息了,如下的xml节点:
<element>
text
</element>
在拥有element节点对象时,要获取其中的文本信息"text",首先要获取element节点的子节点列表,要判断其是否存在子节点,如果存在,那么遍历其子节点找到一个textnode节点,通过getnodevalue()方法来获取该文本信息,由于这里element节点没有信息时没有子节点,所以必须判断element节点是否存在子节点才能去访问真正包含了文本信息的textnode节点,那么如果要处理的数据都是以这种形式给出的,就会增加大量的开发代码同时让开发工作枯燥无味,因此这里使用了一个默认的约定实现,就是,给出了一个公共方法,该方法取给定node下的直接子节点的text节点文本信息,如果不存在text节点则返回null,这个约定虽然使该方法的使用有所限制,也可能导致错误使用该方法,但是,按实际使用的状况来看,这样的约定和使用方式是没有问题的,因为实际用到的都是上面举的例子的状况,代码:
/**
* 这个方法获取给定node下的text节点文本信息,如果不存在text节点则返回null。
* 注意:是直接子节点,相差2层或2层以上不会被考虑。
* @param node a node 一个node。
* @return a string 如果给定节点存在text子节点,则返回第一个访问到的text子节点文本信息,如果不存在则返回null。
*/
public static string getnodevalue(node node) {
if (node == null) {
return null;
}

text text = gettextnode(node);

if (text != null) {
return text.getnodevalue();
}

return null;
}

/**
* 这个方法获取给定node下的text节点,如果不存在text节点则返回null。
* 注意:是直接子节点,相差2层或2层以上不会被考虑。
* @param node a node 一个node。
* @return a text 如果给定节点存在text子节点,则返回第一个访问到的text子节点,如果不存在则返回null。
*/
public static text gettextnode(node node) {
if (node == null) {
return null;
}
if (node.haschildnodes()) {
nodelist list = node.getchildnodes();
for (int i = 0; i < list.getlength(); i++) {
if (list.item(i).getnodetype() == node.text_node) {
return (text) list.item(i);
}
}
}
return null;
}

上面代码将获取给定node节点的直接text子节点分开包装。

另一个很经常碰到的状况是,我希望直接定位到目标节点,获取该节点对象,而不需要通过一层一层的节点遍历来找到目标节点,dom2接口中至少提供了如下的方式来定位节点:
1、 对于document对象:
1) getdocumentelement()――获取根节点对象,实际很少使用的,因为根节点基本也就只是根节点而已,实际的数据节点都是根节点下的直接子节点开始的。
2) getelementbyid(string elementid)――这个方法本来应该是一个最佳的定位方法,但是在实际使用过程中没有被我使用,其主要原因就是,这里的"id"不同于一个节点的属性"id",这在org.w3c.dom.document的api说明中是明确指出,而我找了不少的资料也没有看到有关的使用方式,所以只好放弃了。
3) getelementsbytagname(string tagname)――这个方法其实是没有办法的选择,只好用它了,不过实际倒也很合用,虽然该方法返回的是一个nodelist,但是实际使用时,将节点的tagname设计成特殊字符串,那么就可以直接获取了,而实际使用时,其实也差不多,很多时候会直接拿数据库中的字段名来作为tagname,以方便得获取该字段得值,在一个简单得约定下,使用了如下方法:
/**
* 这个方法检索参数element下所有tagname为:tagname的节点,并返回节点列表的第一个节点。
* 如果不存在该tagname的节点,则返回null。
* @param element 待搜索节点
* @param tagname 待搜索标签名
* @return a element 获得以tagname为标签名的节点列表的第一个节点。
*/
public static element getfirstelementbyname(
element element,
string tagname) {
return (element) getfirstelement(element.getelementsbytagname(tagname));
}
/**
* 从给定节点列表中获取第一个节点返回,如果节点集合为null/空,则返回null。
* @param nodelist a nodelist
* @return a node
*/
private static node getfirstelement(nodelist nodelist) {
if (nodelist == null || nodelist.getlength() == 0) {
return null;
}
return nodelist.item(0);
}
这个约定看似限制很大,其实实际使用时基本都是这样的,只要获取第一个给定tagname的element节点就可以了的。
4)getelementsbytagnamens(string namespaceuri, string localname)――这个方法基本没有使用,因为还没有碰到需要使用命名空间的状况。
2、 对于element对象――――element对象和document对象雷同,少了getdocumentelement()方法,不过和document一样也都是主要使用getelementsbytagname()方法。
3、 其它的节点对象基本没有直接定位的访问方法

还有一种,是由于dom2的限制导致的,dom2规范中,不能将一个document doca的节点直接加入到另一个document docb对象的节点的子节点列表中,要这么做必须首先将doca的节点通过docb的importnode方法转换后在添加到目标节点的子节点列表中,所以也有一个方法来统一处理:
/**
* 这个方法将参数appendeddoc的根节点及其以下节点附加到doc的跟节点下面。
* 作为doc的跟节点的作后一个子节点。
* 相当于:doc.appenddoc(appendeddoc);
* @param doc a document
* @param appendeddoc a document
*/
public static void appendxmldocument(document doc, document appendeddoc) {
if (appendeddoc != null) {
doc.getfirstchild().appendchild(
doc.importnode(appendeddoc.getfirstchild(), true));
}
}
/**
* 这个方法将参数appendeddoc的根节点及其以下节点附加到node节点下面。
* 作为node节点的作后一个子节点。
* 相当于:node.appenddoc(appendednode);
* @param node 待添加的节点将被添加到该节点的最后。
* @param appendednode a node 这个节点将被添加作为node节点的最后一个子节点。
*/
public static void appendxmldocument(node node, node appendednode) {
if (appendednode == null) {
return;
}
if (appendednode instanceof document) {
appendednode = ((document) appendednode).getdocumentelement();
}
node.appendchild(
node.getownerdocument().importnode(appendednode, true));
}

基本上就这些常用的了,其它还有一些零碎的方法,不过都不常用到,就不作介绍了。另外要说的是,如果哪位知道上面说到的getelementbyid()方法的具体可行的方便用法,也请指教下。


文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·OFFICE编程思路(VBA)-.NET教程,数据库应用
·目前最好的JSP分页技术-JSP教程,Jsp/Servlet
·在JAVA中使用文档对象模型DOM经验小结-JSP教程,Java技巧及代码
·J2EE平台WEB组件开发中如何使用定制标签-JSP教程,J2EE/EJB/服务器
·防止Access数据库被下载-ASP教程,数据库相关
·XMLHTTP 对象及其方法简介-.NET教程,XML应用
·在ASP.NET应用中插入flash动画-.NET教程,Asp.Net开发
·Java学习笔记(一)--熟悉开发环境-JSP教程,Java基础
·怎样在C#中调用Delphi6写的DLL-.NET教程,C#语言
·ASP.NET 2.0 中的母版页详解-.NET教程,Asp.Net开发
最新文章
·关于seo最佳的实践方法_seo网站优化
·photoshop cs3新增黑白转换命令原理剖析_photoshop教程
·抛弃acdsee windows live照片库体验_windows vista
·给网络赚钱新手的一些建议_网赚技巧
·google adsense巡讲大会[日期已更新]_网赚技巧
·“口碑营销”的关键问题是在效率_站长心得
·本地分类信息网站线下推广招数_站长心得
·如何提高网站的“友好指数”?_站长心得
·个人网站站长:商业化还是非商业化?_站长心得
·网站排名对网站推广的价值_站长心得
相关主题
  • 在javascript中使用正则表达式_javascript教程
  • 在javascript中实现命名空间_javascript教程
  • 在java和.net平台的加密术比较_asp.net技巧
  • 在java中读写excel文件_java认证
  • 在java中使用正则表达式_java认证
  • 西部数码虚拟主机

    友情链接
    CNNIC 西部数码
    万网 自助建站
    虚拟主机 asp空间
    域名注册 域名
    域名申请 主页空间
    论坛空间 网站空间
    国际域名 虚拟空间
    空间租用 DDOS防火墙
    成都主机托管 四川主机托管
    主机租用 服务器租用
    网站目录 自助建站
    虚拟主机 网址大全
    软件下载
    自助链接
    虚拟主机资讯 特价虚拟主机
    版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
    关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
    特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
    发表评论 打印  刷新     关闭