momo zone

调核人的blog

Monthly Archives: 十一月 2008

JDom 对象常用的方法。

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;

/**
*这个类提供一些 JDom 对象常用的方法。
*/
public class JDomUtil {

/**
* 根据指定路径的XML文件建立JDom对象
* @param filePath XML文件的路径
* @return 返回建立的JDom对象,建立不成功返回null 。
*/
public static Document buildFromFile(String filePath) {
try {
SAXBuilder builder = new SAXBuilder();
Document anotherDocument = builder.build(new File(filePath));
return anotherDocument;
} catch(JDOMException e) {
e.printStackTrace();
} catch(NullPointerException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据XML 字符串 建立JDom对象
* @param xmlString XML格式的字符串
* @return 返回建立的JDom对象,建立不成功返回null 。
*/
public static Document buildFromXMLString(String xmlString) {
try {
SAXBuilder builder = new SAXBuilder();
Document anotherDocument = builder.build(new StringReader(xmlString));
return anotherDocument;
} catch(JDOMException e) {
e.printStackTrace();
} catch(NullPointerException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据Dom对象建立JDom对象
* @param Dom org.w3c.dom.Document对象
* @return 返回建立的JDom对象,建立不成功返回null 。
*/
public static Document buildFromDom(org.w3c.dom.Document Dom) 
throws JDOMException, IOException {
org.jdom.input.DOMBuilder builder = new org.jdom.input.DOMBuilder();
Document jdomDoc = builder.build(Dom);
return jdomDoc;
}

/**
*这个方法使用XMLOutputer将一个JDom对象输出到标准输出设备,使用 GBK 编码
* @param myDocument 将要被输出的JDom对象
*/
public static void outputToStdout(Document myDocument) {
outputToStdout(myDocument,"GBK");
}
/**
*这个方法使用XMLOutputer将一个JDom对象输出到标准输出设备
* @param myDocument 将要被输出的JDom对象
* @param encoding 输出使用的编码
*/
public static void outputToStdout(Document myDocument,String encoding) {
try {
XMLOutputter outputter = new XMLOutputter(" ", true,encoding);
outputter.output(myDocument, System.out);
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
/**
* 这个方法将JDom对象转换字符串.
* @param document 将要被转换的JDom对象
*/
public static String outputToString(Document document){
return outputToString(document,"GBK"); 
}
/**
* 这个方法将JDom对象转换字符串.
* @param document 将要被转换的JDom对象
* @param encoding 输出字符串使用的编码
*/
public static String outputToString(Document document,String encoding){
ByteArrayOutputStream byteRep = new ByteArrayOutputStream();
XMLOutputter docWriter = new XMLOutputter(" ", true,encoding);
try{
docWriter.output(document, byteRep);
}catch(Exception e){

}

return byteRep.toString();
}
public static org.w3c.dom.Document outputToDom(org.jdom.Document jdomDoc)
throws JDOMException {
org.jdom.output.DOMOutputter outputter = new org.jdom.output.DOMOutputter();
return outputter.output(jdomDoc);
}
/**
* 这个方法使用XMLOutputter将JDom对象输出到文件
* @param myDocument 将要输出的JDom对象
* @param filePath 将要输出到的磁盘路径
*/
public static void outputToFile(Document myDocument,String filePath) {
outputToFile(myDocument,filePath,"GBK");
}
/**
* 这个方法使用XMLOutputter将JDom对象输出到文件
* @param myDocument 将要输出的JDom对象
* @param filePath 将要输出到的磁盘路径
* @param encoding 编码方式
*/
public static void outputToFile(Document myDocument,String filePath,String encoding) {
//setup this like outputDocument
try {
XMLOutputter outputter = new XMLOutputter(" ", true,encoding);

//output to a file
FileWriter writer = new FileWriter(filePath);
outputter.output(myDocument, writer);
writer.close();

} catch(java.io.IOException e) {
e.printStackTrace();
}
}
/**
* 这个方法将JDom对象通过样式单转换.
* @param myDocument 将要被转换的JDom对象
* @param xslFilePath XSL文件的磁盘路径 
*/
public static void executeXSL(Document myDocument,String xslFilePath,StreamResult xmlResult) {
try {
TransformerFactory tFactory = TransformerFactory.newInstance();
// Make the input sources for the XML and XSLT documents
org.jdom.output.DOMOutputter outputter = new org.jdom.output.DOMOutputter();
org.w3c.dom.Document domDocument = outputter.output(myDocument);
javax.xml.transform.Source xmlSource = new javax.xml.transform.dom.DOMSource(domDocument);
StreamSource xsltSource = new StreamSource(new FileInputStream(xslFilePath));
//Get a XSLT transformer
Transformer transformer = tFactory.newTransformer(xsltSource);
//do the transform
transformer.transform(xmlSource, xmlResult);
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(TransformerConfigurationException e) {
e.printStackTrace();
} catch(TransformerException e) {
e.printStackTrace();
} catch(org.jdom.JDOMException e) {
e.printStackTrace();
}
}

//Main 函数,局部测试用。
public static void main(String argv[]) {

}
}

Advertisements

Web Service深度编程——Axis序列化/反序列化器开发指南

Web Service深度编程——Axis序列化/反序列化器开发指南


前言

Axis是Apache组织推出的SOAP引擎,Axis项目是Apache组织著名的SOAP项目的后继项目。
Axis为开发者提供了大量的序列化/反序列化器,能够基本满足大部分应用。但在某些情况下,对特定的对象,现有的序列化/反序列化器不能胜任,于是只有
开发人员自己实现专用于此对象的序列化/反序列化器插入到Axis中来完成序列化工作。考虑到Web
Service是一门新兴技术,中文资料大多是泛泛的讲解,关于序列化/反序列化器的开发鲜有较为深入的介绍,本文提供一份较为完整的开发指南,并提供了
一个十分有用的实现,即序列化JDOM模型的Element,使其可以通过Web
服务在网络上传输,我想这一扩展是许多采用JDOM作为XML解析工具的开发人员都梦寐以求的功能。通过本文的介绍和实例,希望能起到抛砖引玉的作用,读
者在阅读完本文之后可以轻松的实现针对于任何非符合BEAN规范的对象的序列化/反序列化器。

本文所面对的读者需要有一定的使用Axis做Web服务开发的开发经验,因此关于如何Axis的基础知识并不在本文的介绍范围,如果读者对此感兴趣,可以参考本文最后的参考资料部分,去相应的网站进行学习。

序列化/反序列化器简介

序列化/反序列化器在英文中的对应翻译是Serializer/Deserializer,一个序列化器的功能是遵
循一定的映射规则和编码风格,将一种类型的JAVA对象通过某种特定的机制,转换成为XML描述的形式;反序列化器的功能是序列化器所做工作的逆操作,两
者相辅相成,成对出现。Axis中的序列化/反序列化器采用设计范式中的工厂模式,每一个Serializer唯一对应一个
SerializerFactory;每一个Deserializer唯一对应一个DeserializerFactory。一种类型的JAVA对象具体
要采用哪个序列化/反序列化器需要在提供Web服务的服务器和调用Web服务的客户端分别配置,关于这一部分如何配置,我将在本文后面的内容中进行详细介
绍。Axis已经为开发者提供了丰富的序列化/反序列化器,对于java的基本数据类型,绝大部分常用的容器类(比如数组类型,Vector类型等)都提
供了实现,特别是提供了对W3C的DOM对象(比如Document,
Element等)和符合Bean规范的JAVA对象提供了功能完善的序列化/反序列化器,因此我们在需要的时候只要在配置文件中配置一下就可以直接使
用。如果对象中包含其它类型的对象,比如Vector中包含一组Bean对象,Axis会自动叠代的调用序列化器,最终拼装成唯一的XML表述。在还原成
JAVA对象时,也遵循这样的叠代操作逆向进行。关于Axis到底内置了哪些序列化/反序列化器,您可以参照Axis的API文档中包
org.apache.axis.encoding.ser下的类的名称"望文生义"的了解一下,在以后的开发中做到心中有数。但对于一些特殊类型的对象
(其实我们自己开发的很大一部分类都是这种特殊类型的对象,很少有绝对符合Bean规范的),需要通过Web服务进行传递,我们不得不开发自己的序列化/
反序列化器。

开发篇

开发自己的序列化/反序列化器是一个激动人心的工作,但是却并不复杂,需要做的事情包括实现名成为
org.apache.axis.encoding的包中的
SerializerFactory,Serializer,DeserializerFactory和Deserializer这四个接口。下面我将结
合一个实例来讲解序列化/反序列化器的开发方法,希望读者能够一边参看本文提供的源代码一边学习。

JDOM作为一款比较"另类"的XML解析工具(因为它不符合W3C的DOM模型,自己另立一套)默默地占领着
java世界里的xml解析器的半壁江山,由于其简洁的设计和方便灵活的API调用,已经渐渐成为了许多开发人员在进行XML开发的首选。但是Axis是
建立在W3C的DOM模型的基础之上,师出名们正派,自然不屑与JDOM为伍。因此当开发人员想将自己已经写好的基于JDOM的应用模块采用Web服务的
方式发布的时候,不可避免的会遇到如何将JDOM模型下的对象如Document,
Element等序列化的问题。在软件工程师不会自己扩展Axis的序列化/反序列化器的时候,我们只能有两个办法达到这个目的,第一个就是更改以前应用
模块内的API设计,使暴露的入口参数和返回值参数都是W3C的对象类型,但这种做法并不现实,因为这一应用模块往往不是独立存在,牵一发将动全身,导致
旧有系统架构的崩塌;另一种做法就是为这个模块做一个代理类,它做的工作就对外接收或返回DOM模型的对象,对内转换成JDOM模型的对象,然后转发给应
用模块,繁琐且效率低下。当我们向Axis注入了针对于JDOM模型的序列化/反序列化器后,这一工作便可以由Axis代劳了。下面我们将逐个开发这四个
类:

JDomElementSerializerFactory

JDomElementSerializerFactory是一个工厂类,需要通过某种机制注册到Axis引擎(具
体方法见下面"服务器端应用篇");Axis通过调用它,来实例化JDomElementSerializer。Axis
提供了BaseSerializerFactory,这个类是一个抽象类,并实现其中包含了一些可重用的代码。我们自己开发的工厂类只需简单继承这个类就
可以。构造函数中需要调用父类的构造函数将序列器类下面是它的源代码:

package org.apache.axis.encoding.ser;

public class JDomElementSerializerFactory
extends BaseSerializerFactory {

public JDomElementSerializerFactory() {
super(JDomElementSerializer.class);
}
}

JDomElementSerializer

JDomElementSerializer实现
org.apache.axis.encoding.Serializer接口,其核心API是serialize(),我们需要在这个方法的内部完成对
JDOM模型的Element的序列化工作,序列化的结果要保存在入口参数传入的序列化上下文对象(SerializationContext)中:

public void serialize(QName name, Attributes attributes, Object value,
SerializationContext context) throws java.io.IOException {

if (!(value instanceof Element))
throw new IOException(
Messages.getMessage("cant Serialize Object"));

//获取符合JDOM的Element对象
Element root=(Element)value;

//输出到StringWriter
XMLOutputter outputter=new XMLOutputter();//创建一个JDOM的XML输出器
StringWriter sw=new StringWriter();
outputter.output(root,sw);

//用支持W3C的DOM模型的Xerces解析器解析文本流
DOMParser parser=new DOMParser();//创建一个DOM的XML解析器
try {
parser.parse(new org.xml.sax.InputSource(
new java.io.StringReader(sw.toString())));
}catch (Exception ex) {
throw new java.io.IOException("序列化时产生错误");
}

//获取符合DOM模型的Element对象
org.w3c.dom.Element w3c_root =
parser.getDocument().getDocumentElement();

//放入序列化上下文对象中
context.startElement(name, attributes);
context.writeDOMElement(w3c_root);
context.endElement();
}

JDomElementDeserializerFactory

反序列化器的工厂类同序列化器的工厂类一样的设计,在此不在赘述。代码:

package org.apache.axis.encoding.ser;

public class JDomElementDeserializerFactory
extends BaseDeserializerFactory {

public JDomElementDeserializerFactory() {
super(JDomElementDeserializer.class);
}

}

JDomElementDeserializer

用过SAX解析XML的读者,对反序列化的实现比较容易理解,反序列化也采用了消息触发的机制,我们只需继承org.apache.axis.encoding.DeserializerImpl类,并覆盖其中的onEndElement方法:

/**
* 在元素结束触发反序列化的方法
* @param namespace String 命名空间
* @param localName String 本地名称
* @param context DeserializationContext 反序列化上下文
* @throws SAXException
*/
public void onEndElement(String namespace, String localName,
DeserializationContext context) throws SAXException {

try {
//从反序列化上下文对象中获取原始的消息元素
MessageElement msgElem = context.getCurElement();
if (msgElem != null) {
MessageContext messageContext = context.getMessageContext();
Boolean currentElement = (Boolean) messageContext.getProperty(
DESERIALIZE_CURRENT_ELEMENT);

//如果当前的消息元素本身需要反序列化
if (currentElement != null && currentElement.booleanValue()) {
org.w3c.dom.Element element = msgElem.getAsDOM();
org.jdom.input.DOMBuilder db=new org.jdom.input.DOMBuilder();
value=db.build(element);
messageContext.setProperty(DESERIALIZE_CURRENT_ELEMENT,
Boolean.FALSE);
return;
}

//反序列化消息元素中的消息体
java.util.ArrayList children = msgElem.getChildren();
if (children != null) {

//取得消息体
msgElem = (MessageElement) children.get(0);
if (msgElem != null) {
org.w3c.dom.Element ret = msgElem.getAsDOM();
org.jdom.input.DOMBuilder db=new org.jdom.input.DOMBuilder();

//用DOMBuilder将DOM模型的Element,转换成JDOM模型的Element
value=db.build(ret);
}
}

}
}
catch (Exception ex) {
//错误,则记日志,并抛SAXException
log.error(Messages.getMessage("exception00"), ex);
throw new SAXException(ex);
}
}

完成这四个类的编码,序列化/反序列化器的开发工作基本完成,下面将详细讲解使用及部署方法。

服务器端应用篇

为了简单起见,我们将一个很简单的类通过Web服务发布,类中只有一个名称为hello函数,函数的返回值为JDOM模型的Element。代码如下:

package test;

import org.jdom.*;
import java.rmi.RemoteException;

public class Sample1 implements java.rmi.Remote{
public Sample1() {
}

public Element hello(String name){
Element root=new Element("root");
Element hello=new Element("hello");
hello.setText("hello,"+name+"!");
root.addContent(hello);
return root;
}

}

关于如何将一个类发布成Web服务,在此并不进行介绍,相信读者可以自己完成,我们只关注如何将序列化/反序列化器加入到我们的Web服务中。打开web服务的配置文件server-config.xml,编辑关于Sample1的服务的配置部分:

<service name="Sample1" type="" regenerateElement="true"
provider="java:RPC" style="rpc" use="encoded">

<parameter name="scope" value="Request" regenerateElement="false"/>
<parameter name="className" value="test.Sample1" regenerateElement="false"/>
<parameter name="allowedMethods" value="*" regenerateElement="false"/>

<typeMapping
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
qname="ns1:Element"
languageSpecificType="java:org.jdom.Element"
serializer=
"org.apache.axis.encoding.ser.JDomElementSerializerFactory"
deserializer=
"org.apache.axis.encoding.ser.JDomElementDeserializerFactory"
name="Element" regenerateElement="true"
xmlns:ns1="http://jdom.org"/>


</service>

注意上面代码中的粗体字部分,是我们现在要添加的,它表述了如何将序列化反序列化器部署到Web服务中。

部署到Web Server

解压缩本文后面附带的源代码,根目录下有build.xml文件,读者需要正确安装配置好Apache Ant,然后运行

Ant make

编译后可生成压缩文件sample.war。将生成的war包部署到Tomcat4.1下,启动Tomcat,本文
默认的Tomcat监听的http端口为8080。后面的客户端测试程序也将通过连接这一端口访问此Web服务。如果读者的Tomcat不在8080端口
上工作,那么客户端程序也要进行相应的修改。最后启动Tomcat,这部分操作完成。

客户端应用篇

下面我们将编写客户端程序访问刚才部署的Web服务,讲解如何把我们编写的序列化/反序列化器加载到客户端应用程序
中,下面是客户端调用的代码,注意斜体字部分,是关于序列化/反序列化器的注册过程(如果你的Web服务器不是工作在8080端口,或采用了其他Web服
务名,请自行更改下面程序中的url变量中的值),我们在test包下创建了一个名称为 Client的类,代码如下:

package test;

import org.apache.axis.client.Service;
import org.apache.axis.client.Call;
import org.apache.axis.utils.Options;
import javax.xml.namespace.QName;

public class Client {
public Client() {
}

public static void main(String[] args) throws Exception{
if(args.length<1){
System.out.println("错误:缺少参数");
System.exit(0);
}
//Web服务的URL
String url="http://localhost:8080/sample/services/Sample1";
Service service=new Service();
Call call = (Call)service.createCall();
call.setTargetEndpointAddress(url);

//注册序列化/反序列化器
call.registerTypeMapping(org.jdom.Element.class,
new QName("http://jdom.org","Element"),
new org.apache.axis.encoding.ser.JDomElementSerializerFactory(),
new org.apache.axis.encoding.ser.JDomElementDeserializerFactory());

//设置调用方法
call.setOperationName(
new javax.xml.namespace.QName("http://test", "hello"));

//Web服务调用
java.lang.Object _resp = call.invoke(new java.lang.Object[] {args[0]});

//输出到屏幕
org.jdom.output.XMLOutputter out=new org.jdom.output.XMLOutputter();
out.output( (org.jdom.Element) _resp, System.out);

}

}

编译后运行该程序,在控制台窗口工程的根目录下输入

run world  ( 其中"world"为调用例程中API的入口参数)

经过一次web通讯,一两秒后屏幕将显示运行结果:

<root>
<hello>hello,world!</hello>
</root>

至此我们完成了一次Web服务的访问过程。如果在程序执行过程中,我们用TCP Moniter之类的工具监视这一次访问中的在网络中流入流出的数据,可以看到客户端发起调用的xml数据流如下:

POST /sample/services/Sample1 HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml,
application/dime, multipart/related, text/*
User-Agent: Axis/1.1
Host: 127.0.0.1
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Content-Length: 430
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<soapenv:Body>
<ns1:hello soapenv:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://test">
<name xsi:type="xsd:string">world</name>
</ns1:hello>
</soapenv:Body>
</soapenv:Envelope>

服务器端返回的结果的XML输出流如下:

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Date: Wed, 31 Mar 2004 06:42:18 GMT
Server: Apache Coyote/1.0
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<soapenv:Body>
<ns1:helloResponse soapenv:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://test">

<ns1:helloReturn href="#id0"/>
</ns1:helloResponse>
<multiRef id="id0" soapenc:root="0" soapenv:encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:Element"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns2="http://jdom.org">
<root>
<hello>hello,world!</hello>
</root>
</multiRef>
</soapenv:Body>
</soapenv:Envelope>

结语

以上详细讲解了Axis的序列化/反序列化器的开发过程,相信读者已经从中学到了不少知识,并能够应用于自己的项目
开发中去。通过掌握这一技术,我们将更为深刻的理解Axis的内部结构和Web服务的工作机理,这些经验是市面上那些泛泛的讲解JAVA
Web服务的参考书上所学不到的。后续的文章还将向您展示一些在Java Web服务深度开发中的高级技术,让您真正驾驭Axis。

参考资料

应用 AXIS 开始 Web 服务之旅

应用 AXIS 开始 Web 服务之旅

本文介绍使用AXIS作为开发环境来体会Web服务的开发过程。

一. 介绍


本文并不是想介绍Web服务的原理、系统架构等,我们假设您已经了解了关于Web服务的一些基本的概念、原理等知识。本文主要是针对那些已经了解Web服
务概念,但是还没有亲身体会Web服务所带来令人欢欣鼓舞的特征的开发人员。在此我们认为你已经具备了Java、XML等基础知识,如果你还有其他开发环
境的经验例如VB、VC那是再好不过的了。

1.Web服务


虽然我们并不想详细讲述Web服务的体系结构,但是大概的介绍一下还是有必要的。Web服务是一种新型的Web应用程序。不同于其他Web应用程序,它是
自适应、自我描述、模块化的应用程序,并可以跨越Web进行发布、定位以及调用。简单的Web服务可以提供例如天气预报或者航班信息的服务。一旦部署了
Web服务,其他的应用程序就可以发现和调用所部署的服务。

2.AXIS项目


Axis框架来自 Apache 开放源代码组织,它是基于JAVA语言的最新的 SOAP 规范(SOAP 1.2)和 SOAP with
Attachments 规范(来自 Apache Group
)的开放源代码实现。有很多流行的开发工具都使用AXIS作为其实现支持Web服务的功能,例如JBuilder以及著名的Eclipse
J2EE插件Lomboz。AXIS的最新版本是1.1,可以从
http://ws.apache.org/axis/index.html下载。下图是AXIS核心引擎的体系结构图:


图1

整个AXIS项目包括以下几个部分:

  1. 消息流子系统

    消息流子系统提供了灵活的消息传递框架,这个消息传递框架包括处理程序、链、序列化程序和反序列化程序。处理程序是一个处理请求、响应和故障流的对象。处理程序可被组合在一起成为链,而且可以使用一个灵活的部署描述符来配置这些处理程序的顺序。

  2. 传输框架子系统

    提供了一个传输框架,这个传输框架可以帮助您创建自己的可插式传输发送器和传输侦听器。

  3. 数据编码子系统

    AXIS完全按照 XML Schema 规范提供各种数据类型的自动序列化,并且提供功能扩展接口来使用您自己定制的序列化器和反序列化器。

  4. 其他

    AXIS完全支持 WSDL 以及日志记录、出错以及故障处理机制。它同时提供一些工具用来讲WSDL文档转换成客户端的调用框架以及根据类来产生WSDL定义文档。

AXIS
目前版本支持的标准是:W3C SOAP 1.1 和 1.2;WSDL 1.1;SAAJ 1.1(SUN公司:SOAP with
Attachments API for Java);JAX-RPC(SUN公司:Java API for XML-Based RPC)1.0。

除了前面介绍的AXIS外,本文中还将会用到TOMCAT,这里不再另行介绍。另外为了演示Web服务真正
与开发环境无关以及AXIS产生的是标准的、符合规范的Web服务,我们还将用到微软公司的SOAP
TOOLKIT以及微软的开发环境VB和VC来做为Web服务的客户端。


二. 环境搭建



于AXIS本身是基于JAVA语言开发的项目,并且是以Web应用形式发布的,因此它运行时需要一个应用服务器作为支撑。为了方便我们这里选用的是
Tomcat。由于AXIS本身需要用到处理XML信息的包,所以我们建议使用JDK1.4并安装Tomcat
4.1.24。下面是环境搭建步骤,读取根据自身情况进行安装。

  1. 安装JDK1.4.1
  2. 安装Tomcat 4.1.24到C:Tomcat并验证安装是否成功
  3. 下载AXIS项目打包文件axis-1_1.zip解压缩后将目录中的webapps目录下的axis子目录拷贝到C:Tomcatwebapps下。
  4. 验证AXIS的安装:重新启动Tomcat服务器后打开浏览器输入网址http://localhost:8080/axis 后应该出现如下图所示页面,点击链接"Validate"来验证Axis所需的几个JAVA包是否齐全。


图2

点击超链接Validate后,AXIS会自动检查所需的每一个JAVA组件,这协组件分为:必需组件以及可选组件,必须保证所有必需组件都存在,如下图所示即为验证成功。


图3


回页首

三. Web Service服务端开发


经过了前两步之后我们就可以开始Web服务之旅了!大多数人在学习一种编程语言的第一步都是从Hello
world程序开始的,我们也不例外。我们将提供这样一个Web服务,通过给它传入姓名,服务返回:你好[姓名],欢迎来到Web服务的世界。这就是我们
的需求。我们将马上根据AXIS的要求完成我们的需求,你就会发现原来Web服务可以这么简单!

编写JAVA类Hello.java,内容如下:

public class Hello{
public String hello(String name){
if(name==null)
name = "";
return "你好"+name+",欢迎来到Web服务的世界!";
}
}

仅此而已,无需编译,将该文件改名为Hello.jws并拷贝到AXIS应用目录C:Tomcatwebappsaxis下。

下面我们就可以测试该Web服务了,打开浏览器并输入刚刚创建的文件名对应的URL地址

http://localhost:8080/axis/Hello.jws 浏览器显示如下结果:

There is a Web Service here

Click to see the WSDL

点击页面上的链接查看该Web服务对应的WSDL信息如下所示(我们将在下一小节简单介绍WSDL)

<?xml version="1.0" encoding="UTF-8" ?>
-<wsdl:definitions
targetNamespace="http://localhost:8080/axis/Hello.jws"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://www.w3.org/2000/xmlns/"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:impl="http://localhost:8080/axis/Hello.jws"
xmlns:intf="http://localhost:8080/axis/Hello.jws"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
- <wsdl:message name="helloRequest">
<wsdl:part name="name" type="xsd:string" />
</wsdl:message>
+ <wsdl:message name="helloResponse">
- <wsdl:portType name="Hello">
- <wsdl:operation name="hello" parameterOrder="name">
<wsdl:input name="helloRequest" message="intf:helloRequest" />
<wsdl:output name="helloResponse" message="intf:helloResponse" />
</wsdl:operation>
</wsdl:portType>
- <wsdl:binding name="HelloSoapBinding" type="intf:Hello">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
- <wsdl:operation name="hello">
<wsdlsoap:operation soapAction="" />
- <wsdl:input name="helloRequest">
<wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://DefaultNamespace" />
</wsdl:input>- <wsdl:output name="helloResponse">
<wsdlsoap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://localhost:8080/axis/Hello.jws" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
- <wsdl:service name="HelloService">
- <wsdl:port name="Hello" binding="intf:HelloSoapBinding">
<wsdlsoap:address location="http://localhost:8080/axis/Hello.jws" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

到此我们已经完成了hello的Web服务了,那我们怎么告诉用户如何来使用该服务呢?我们只需要告诉用户我们的Web服务的URL地址:

http://localhost:8080/axis/Hello.jws?wsdl 就可以了!下一节我们将介绍如何通过这个地址来访问对应的Web服务。


回页首

四. Web Service客户端开发


在这一节中我们将使用三种不同的语言来访问刚刚创建的Web服务,分别是JAVA、VB、VC。为了使用VB和VC访问Web服务,我们需要安装微软公司的Soap Toolkit 开发工具包,这个工具包可以从微软公司的主页

http://download.microsoft.com/download/xml/soap/2.0/W98NT42KMe/EN-US/SoapToolkit20.exe

下载,下载该软件包并使用默认方式安装即可。

在开始客户端开发之前有两个概念我们必须先粗略的介绍一下。

SOAP:简单对象访问协议。这是一种在松散的、分布的环境中使用XML对等地交换结构化的和类型化的信息提供了一个简单且轻量级的机制,它是一个基于
XML的协议。它包括四个部分:SOAP封装(envelop),封装定义了一个描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它
们的框架;SOAP编码规则(encoding rules),用于表示应用程序需要使用的数据类型的实例; SOAP RPC表示(RPC
representation),表示远程过程调用和应答的协定;SOAP绑定(binding),使用底层协议交换信息。

虽然这四个部分都作为SOAP的一部分,作为一个整体定义的,但他们在功能上是相交的、彼此独立的。特别的,信封和编码规则是被定义在不同的XML命名空间(namespace)中,这样使得定义更加简单。

SOAP的主要设计目标是简明性和可扩展性。这就意味着有一些传统消息系统或分布式对象系统中的特性将不包含在SOAP的核心规范中。这些特性包括:分布式垃圾收集;批量消息传输/处理;对象引用;对象激活。

WSDL:Web
Service描述语言。使用了WSDL,我们就可以通过这种跨平台和跨语言的方法使Web
Service代理的产生自动化。就像COM和CORBA的IDL文件,WSDL文件由客户和服务器约定。由于WSDL设计成可以绑定除SOAP以外的其
他协议,这里我们主要关注WSDL在HTTP上和SOAP的关系。同样,由于SOAP目前主要用来调用远程的过程和函数,WSDL支持SOAP传输的文档
规范。

WSDL文档可以分为两部分。顶部分由抽象定义组成,而底部分则由具体描述组成。抽象部分以独立于平台和语言的方式定义SOAP消息,它们并不包含任何随机器或语言而变的元素。这就定义了一系列服务,截然不同的网站都可以实现。

1. JAVA客户端


使
用AXIS的工具将使Web服务的访问和我们之前介绍的创建一个Web服务一样的简单。我们前面安装的AXIS环境中已经包含着这样的工具,它是一个
JAVA类,类名为:org.apache.axis.wsdl.WSDL2Java。打开命令行窗口,转到AXIS目录下的WEB-INF子目录。确保
Tomcat服务已经处于启动状态,键入命令 :

Java -Djava.ext.dirs=lib org.apache.axis.wsdl.WSDL2Java http://localhost:8080/axis/Hello.jws?wsdl

该命令执行的结果是在当前所在目录下产生一个子目录 localhost/axis/Hello_jws,该目录下有四个JAVA源文件,它们分别是:

Hello.java 定义了Web服务接口,此例中只有一个hello方法。

HelloService.java 定义了用于获取Web服务接口的方法。

HelloServiceLocator.java 接口HelloService的具体实现。

HelloSoapBindingStub.java Web服务客户端桩,通过该类与服务器交互。

这四个JAVA类帮我们处理了大部分的逻辑,我们需要的仅仅是把这些类加到我们的项目然后创建一个我们自己的类来调用它们即可。为此我们新加一个类Main.java,为了方便,让这个类与刚产生的四个类都在同一个包下。内容如下:

//Main.java
package localhost.axis.Hello_jws;
public class Main{
public static void main(String[] args) throws Exception{
HelloService service = new HelloServiceLocator();
Hello hello = service.getHello();
System.out.println("Response:"+hello.hello("罐头"));
}
}

使用以下命令进行编译:

javac -classpath libaxis.jar;libjaxrpc.jar localhostaxisHello_jws*.java

如果编译没有问题的话执行该测试程序:

java -Djava.ext.dirs=lib -cp . localhost.axis.Hello_jws.Main//运行结果:Response:你好罐头,欢迎来到Web服务的世界!

在WSDL2Java工具自动产生的几个
类中,类HelloServiceLocator中保存这一些跟服务器相关的信息,例如URL地址等,当服务器的地址更改后但是服务并没有改动的时候直接
修改该文件中的字符串定义,而无需重新生成这几个类。具体需要修改的内容,打开该文件便可一目了然。

2. VB客户端


有了微软SOAP toolkit,用VB调用Web服务也是一件令人愉快的事情。

打开VB开发环境新建一个标准EXE项目,打开工程(Project)菜单并选择引用打开组件引用对话框如下图所示:找到并选中Microsoft Soap Type Library。


图 4

新建并编辑窗体如下图所示:


图 5

编辑按钮Call的点击事件处理程序如下:(注意窗体的控件名称要与程序中的名称对应)

Private Sub callBtn_Click()    
'这种做法需要在工程中引用Soap Type Library
'Dim soap As MSSOAPLib.SoapClient
'Set soap = New MSSOAPLib.SoapClient
Dim soap
Set soap = CreateObject("MSSOAP.SoapClient")
On Error Resume Next
'soap.mssoapinit urlText.Text
Call soap.mssoapinit(urlText.Text)
If Err <> 0 Then
MsgBox "初始化SOAP失败: " + Err.Description
urlText.SetFocus
Else
If Len(Trim(nameText.Text)) = 0 Then
MsgBox "请输入您的姓名!"
nameText.SetFocus
Else
responseText.Text = soap.hello(nameText.Text)
End If
End If
End Sub

保存项目并运行,输入姓名并点击按钮Call。

3. VC客户端


打开VC开发环境,新建项目HelloClient,项目类型为 Win32 Console Application的空项目。新建C++ Source File文件名为:HelloSoap.cpp,编辑文件内容如下:

//#include "stdafx.h"
#include <stdio.h>
#import "msxml3.dll"
using namespace MSXML2;
//根据自己机器的情况修改下面语句中指定的路径
#import "C:Program FilesCommon FilesMSSoapBinariesmssoap1.dll"
exclude("IStream", "ISequentialStream", "_LARGE_INTEGER",
"_ULARGE_INTEGER", "tagSTATSTG", "_FILETIME")
using namespace MSSOAPLib;
void Hello(){
ISoapSerializerPtr Serializer;
ISoapReaderPtr Reader;
ISoapConnectorPtr Connector;
// Connect to the service
Connector.CreateInstance(__uuidof(HttpConnector));
Connector->Property["EndPointURL"] = "http://localhost:8080/axis/Hello.jws?wsdl";
Connector->Connect();
// Begin message
Connector->BeginMessage();
// Create the SoapSerializer
Serializer.CreateInstance(__uuidof(SoapSerializer));
// Connect the serializer to the input stream of the connector
Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));
// Build the SOAP Message
Serializer->startEnvelope("","","");
Serializer->startBody("");
Serializer->startElement("hello","","","");
Serializer->startElement("name","","","");
Serializer->writeString("罐头");
Serializer->endElement();
Serializer->endElement();
Serializer->endBody();
Serializer->endEnvelope();

// Send the message to the web service
Connector->EndMessage();

// Let us read the response
Reader.CreateInstance(__uuidof(SoapReader));
// Connect the reader to the output stream of the connector
Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");
// Display the result
printf("Response: %sn", (const char*)Reader->RPCResult->text);
}
int main()
{
CoInitialize(NULL);
Hello();
CoUninitialize();

return 0;
}

编译并运行该项目。

本节只是为了演示如果通过VC来访问使用AXIS创建的Web服务,至于Soap toolkit的具体使用请参照soap toolkit的帮助手册,其他语言的访问请查阅相关的文档。


回页首

五. AXIS集成


了让我们的WEB应用程序支持Web服务功能,我们需要将AXIS集成到我们的应用程序中。集成AXIS很简单,首先需要拷贝AXIS用到的几个JAR包
文件,这些文件都在[AXIS]WEB-INFlib目录下,将这些文件拷贝到我们自己的应用目录下的WEB-INFlib。另外如果你用的不是
TOMCAT服务器那就需要拷贝activation.jar,这个JAR文件可以在[TOMCAT]commonlib目录下找到!

拷贝完JAR文件后就是web.xml的配置了,只需要把AXIS中的web.xml中的配置信息添加到我们自己应用程序中的web.xml中即可。最重要的是下面的内容:

<servlet>  
<servlet-name>AxisServlet</servlet-name>
<display-name>Apache-Axis Servlet</display-name>
<servlet-class>
org.apache.axis.transport.http.AxisServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>*.jws</url-pattern>
</servlet-mapping>
<mime-mapping>
<extension>wsdl</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xsd</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>

回页首

六 总结



此文章告一段落,通过以上的演练,我相信你已经对Web服务有一个感性的认识,但是这个仅仅是开始,我们也只是很简单的介绍了Web服务的一些基本概念并
演示了一个无法再简单的例子。Web服务还有很多其他高级的内容例如复杂类型、数据安全等没有涉及到,不过没有关系,万事开头难,希望本文能够促进大家理
解和应用下一代的应用模式并给还没有动手试验的开发人员开一个好头。

参考资料

JDOM与DOM的相互转换

 JDOM与DOM的相互转换

一、DOM2JDOM采用如下方法,不过,这里只能是Document之间的转换:

    public static org.jdom.Document convert(org.w3c.dom.Document domDoc) 
        throws JDOMException, IOException 
{
        
// Create new DOMBuilder, using default parser
        DOMBuilder builder = new DOMBuilder();
        org.jdom.Document jdomDoc 
= builder.build(domDoc);
        
return jdomDoc;
    }

二、JDOM2DOM,分别采用如下方法:
1、Document之间的转换:

public static org.w3c.dom.Document JDomDoc2Dom(org.jdom.Document jdomDoc) throws Exception {
        DOMOutputter outputter 
= new DOMOutputter();
        
return outputter.output(jdomDoc);
}

2、Element之间的转换,采用如下两个方法,演示的是将一个jdom的Element转换成w3c的Element,并将其附加到指定的W3C的Document下:

    /** *//**
     * 将由JDOM返回的如下结果ELEMENT:
     * <Response>
     *     <Data>
     *         <Record>
     *             <id/>
     *             </name>
     *         </Record>
     *     </Data>
     * </Response>
     * 转换到由w3c的Document中
     * 
@param doc    w3c的Document
     * 
@param element    JDom的Element
     * 
@return    由JDom返回结果Element转换到w3c Document Element并附加到其指定的路径
     * 
@throws DOMException
     * 
@throws Exception
     
*/

    
public static Document convert(org.w3c.dom.Document doc,org.jdom.Element element) throws DOMException, Exception{
        org.w3c.dom.Element root
=null,response=null;
        
int layer=1;
        root 
= doc.getDocumentElement();
        response
=convertElement2Dom(doc,element,layer);
        
//System.out.println("convertElement2Dom结果:"+XmlUtil._node2String(response));
        root.getElementsByTagName("data").item(0).appendChild((Node)response);
        
return doc;
    }

    
/** *//**
     * 将JDom的Element转换成org.w3c.dom.Element
     * 
@param doc org.w3c.dom.Document
     * 
@param element org.jdom.Element
     * 
@param layer 用于判断是否第一层,第一层不用其自身的名称创建结点,用Response代替,只起判断做用
     * 
@return org.w3c.dom.Element
     * 
@throws DOMException
     * 
@throws Exception
     
*/

    
private static org.w3c.dom.Element convertElement2Dom(org.w3c.dom.Document doc,org.jdom.Element element,int layer) throws DOMException, Exception{
        org.w3c.dom.Element element3c
=null;
        
if(layer==1){
            element3c
=doc.createElement("Response");
        }
else{
            element3c
=doc.createElement(element.getName());
        }

        layer
++;
        List listChildren
=element.getChildren();
        String elename
="";
        String elevalue
="";
        
if(listChildren.size()>0){//有下级节点
            List listElement=element.getContent();
            
for(int i=0;i<listElement.size();i++){
                org.jdom.Element tmpElement
=(org.jdom.Element)listElement.get(i);
                element3c.appendChild(convertElement2Dom(doc,tmpElement,layer));
                
            }

        }
else{//无下级节点
            elename=element.getName();//名称
            elevalue=element.getText();//
            element3c=doc.createElement(elename);
            BNXmlUtil.setNodeValue(element3c, elevalue);
//给结点赋值(BNXmlUtil为普元EOS类,可换其它设值)
            List eleAttr=element.getAttributes();
            
for(int i=0;i<eleAttr.size();i++){//增加赋性值
                Attribute attr=(Attribute)eleAttr.get(i);
                String attrName
=attr.getName();
                String attrValue
=attr.getValue();
                element3c.setAttribute(attrName, attrValue);
            }

            
//System.out.println("名称:"+elename+"-值:"+elevalue);
            
            
        }

        
return element3c;
    }

参考:
http://www.ibm.com/developerworks/java/library/x-tipcdm.html (Converting from DOM)
http://www.ibm.com/developerworks/xml/library/x-tipcjdm.html (Converting from JDOM)

Converting from JDOM

Converting from JDOM

JDOM doesn’t map exactly to DOM and SAX, but you can easily output
to both


Level: Introductory

Brett McLaughlin (brett@newInstance.com), Enhydra strategist, Lutris Technologies

01 Apr 2001

Learning
to work with JDOM? Well, no API is an island, and in this tip you’ll
learn how to convert with ease from JDOM to SAX and DOM for fluent
programming of XML applications that use all three APIs. The code
samples provide examples of converting from JDOM to SAX and from JDOM
to DOM.

If you are like me, you’ve jumped on the JDOM bandwagon. It’s easy to
work with (yes, as one of the JDOM authors I’m biased) and makes XML
and Java fit well together. That said, I’d be a fool if I even suggested
that JDOM could replace DOM and SAX and become the only Java and XML API.
There are very different applications for DOM, SAX, and JDOM, and you’ll
almost certainly have to work with all three in your XML-based applications.
As for JDOM, you’ll need to convince co-workers and management, who may
not be as cutting-edge as you, that you can use JDOM and still have your
programs interact with the many other applications that aren’t using JDOM.
That means converting from JDOM to SAX and from JDOM to DOM. In this tip,
I’ll show you how to do both.

From JDOM to SAX

When working with SAX, everything is based on an incoming series of
events. The SAX programmer writes callback method implementations that
are the snippets of code executed upon these various event occurrences.
At the core of all SAX parsing is the SAX org.xml.sax.ContentHandler
interface, which defines the callbacks that are part of processing an XML
document. Additionally, the ErrorHandler, DTDHandler,
and EntityResolver interfaces are critical. Once you’ve set
up implementations of these interfaces, you can hand them off to the JDOM
org.jdom.output.SAXOutputter
class and sit back and relax. Listing 1 shows how this works and gives
you some ideas for your own programs.

Listing 1. Converting from JDOM to SAX

                

public convertToSAX(Document jdomDoc) throws JDOMException {
SAXOutputter outputter = new SAXOutputter(new MyContentHandlerImpl());

// Set the EntityResolver impl
outputter.setEntityResolver(new MyEntityResolverImpl());

// Set the DTDHandler impl
outputter.setEntityResolver(new MyDTDHandlerImpl());

// Set the ErrorHandler impl
outputter.setEntityResolver(new MyErrorHandlerImpl());

// Fire the SAX events
outputter.output(jdomDoc);
}

Back to top

From JDOM to DOM

Converting from a JDOM structure to a DOM structure works in a similar
way. In fact, it’s even easier than working with SAX, because DOM and JDOM
have somewhat analogous structures. There are no surprises here: Just as
you used SAXOutputter for outputting to SAX, you will need to
use the org.jdom.output.DOMOutputter class for outputting to DOM. Listing 2 shows the class in action.

Listing 2. Converting from JDOM to DOM

                

public org.w3c.dom.Document convertToDOM(org.jdom.Document jdomDoc)
throws JDOMException {

DOMOutputter outputter = new DOMOutputter();
return outputter.output(jdomDoc);
}

public org.w3c.dom.Element convertToDOM(org.jdom.Element jdomElement)
throws JDOMException {
DOMOutputter outputter = new DOMOutputter();
return outputter.output(jdomElement);
}

public org.w3c.dom.Attr convertToDOM(org.jdom.Document jdomAttribute)
throws JDOMException {
DOMOutputter outputter = new DOMOutputter();
return outputter.output(jdomAttribute);
}

Sure, there are some additional helpful methods in both the SAXOutputter
and DOMOutputter, but I’ve given you the basics. With this tip,
you are equipped to use JDOM, and use it with both applications that receive
SAX and DOM as input as well as applications that produce SAX and DOM,
if you read the other XML tips I’ve been writing (see Resources).
So go forth and prosper, interchanging XML in all its various formats!

Resources

Converting from DOM

Converting from DOM

When you need SAX or JDOM output from DOM

Level: Introductory

Brett McLaughlin (brett@newInstance.com), Enhydra Strategist, Lutris Technologies

01 Apr 2001

In
this tip, you’ll learn how to convert DOM structures to SAX and JDOM to
allow communication with applications that do not use DOM. The code
listings demonstrate how to convert from DOM to an output stream for
use by SAX, and how to convert from DOM to JDOM.

For
those of you who are sold on the W3C’s DOM (the Document Object Model)
and think SAX is silly, you will have to find a way to move from DOM to
the other formats that application
developers use. These other formats are, of course, SAX and JDOM.
What do you do when you have to accept DOM as input and convert
it to something else? This certainly is a valid question. With
DOM providing a complete document representation, converting it
into another format makes a lot of sense. In this tip, you’ll
learn how to perform this conversion from DOM to either SAX or
JDOM

From DOM to SAX

Unfortunately, DOM Level 1 and the newer Level 2 do not
provide a means of outputting a DOM tree to SAX or any other
format. The result is that each parser implementation provides a
set of custom APIs for output, and implementation independence is
lost. In other words, your code only works with the parser you
wrote it for (like Crimson, or Xerces, or Oracle, and so on). DOM
Level 3 is supposed to provide this functionality, so we’ll all
have to wait and see what DOM Level 3 provides in the way of
output methodology. In the meantime, check out your vendor’s
documentation on writing, or on the serialization of, a DOM tree. As an
example, using Apache Xerces, you would need to use the
org.apache.xml.serialize.XMLSerializer
class, as shown in Listing 1. In either case, you will probably
have to output the DOM tree to a stream, then push that
stream back into SAX for sequential processing. Note that Listing
1 only shows outputting a DOM tree to a stream; you can then use
that stream as input to a SAX processor.

import org.apache.xerces.parsers.DOMParser;
import org.apache.xml.serialize.XMLSerializer;
import org.xml.sax.InputSource;
import org.w3c.dom.Document;
public class PrintDOMTree {
public static void main(String[] args) {
try {
InputSource source = new InputSource(args[0]);
DOMParser parser = new DOMParser();
parser.parse(source);
Document doc = parser.getDocument();
XMLSerializer serializer = new XMLSerializer();
// Insert your PipedOutputStream here instead of System.out!
serializer.setOutputByteStream(System.out);
serializer.serialize(doc);
} catch (Exception e) {
e.printStackTrace();
}
}
}

From DOM to JDOM

Moving from DOM to JDOM is quite a bit easier than moving from
DOM to SAX. This actually makes sense, since once you have a DOM
tree, you’ve probably already had a chance to get at the data
through SAX. In fact, rarely do situations arise where a DOM tree
is best handled by SAX, because you’ve already used up the memory for
storing the XML in memory through a DOM representation. A far more
common task is to convert an XML document that is coming in as a DOM
tree to a JDOM tree. Since these formats
are both document representations, but substantially different
in behavior and functionality, you may want to let someone else
take your DOM tree and deal with it as JDOM. While you might
argue that this should be their job, you do need to know (at
least!) how to convert from your structure to theirs.

For converting from DOM to JDOM, the JDOM API provides a
consumer for DOM Nodes, which is called org.jdom.input.DOMBuilder.
This class will take in a DOM Document (as well as some
other DOM structures, such as Element and Attr)
and convert the DOM tree to a JDOM Document. There
really isn’t much to this operation, so I’ll simply show you the
code in Listing 2 and let you see the process in action.

// Java imports
import java.io.IOException;
// JDOM imports
import org.jdom.JDOMException;
import org.jdom.input.DOMBuilder;
import org.jdom.output.XMLOutputter;
// SAX and DOM
import org.xml.sax.InputSource;
// Xerces
import org.apache.xerces.parsers.DOMParser;
public class DOMtoJDOM {
// DOM tree of input document
org.w3c.dom.Document domDoc;
public DOMtoJDOM(String systemID) throws Exception {
DOMParser parser = new DOMParser();
parser.parse(new InputSource(systemID));
domDoc = parser.getDocument();
}
public org.jdom.Document convert()
throws JDOMException, IOException {
// Create new DOMBuilder, using default parser
DOMBuilder builder = new DOMBuilder();
org.jdom.Document jdomDoc = builder.build(domDoc);
return jdomDoc;
}
public static void main(String[] args) {
try {
DOMtoJDOM tester = new DOMtoJDOM(args[0]);
org.jdom.Document jdomDoc = tester.convert();
// Output the document to System.out
XMLOutputter outputter = new XMLOutputter();
outputter.output(jdomDoc, System.out);
} catch (Exception e) {
e.printStackTrace();
}
}
}

There’s nothing more to say. Once you know how to move from
DOM to SAX and JDOM, you’re all set for tackling any output
format you need and interacting with pretty much any type of XML
representation you’ll come up against. Watch the DOM Level 3
specification for changes to outputting DOM trees in a standard,
vendor-independent way, and until then, enjoy using the DOM!

Resources