Maydene Fisher and Eric Jendrock

Web服务,通常意义上来说,指的是借助Web来提供的服务。在典型的Web服务情景中,业务应用通过HTTP协议之上的SOAP协议,按照给定的URL将请求发送到一个服务上。服务接收请求,对请求进行处理,然后返回一个响应。Web服务经常被引用的一个例子就是股票行情服务,在该服务中,请求就是要得到某支指定股票的当前报价,而响应则给出这支股票的报价。这种服务是Web服务的一种最简单的形式,服务的请求几乎马上就可以得到满足,因为请求和响应都是同一个方法调用的一部分。

         另一个Web服务的例子就是为货物的运输制定出一个高效的路线。这种情况下,业务的一方发出一个包含运输目的地的请求,而服务则处理该请求,以确定最节省成本的运输路线。服务返回响应所花费的时间取决于路线的复杂程度,因此该响应可能作为一种与请求相独立的操作来发送。

         Web服务与Web服务的使用者构成了一种典型的业务系统,这使得Web服务成为一种占统治地位的企业对企业(B-to-B)事务。企业可以是Web服务的提供者,也可以是其他Web服务的使用者。例如,当使用Web服务来查看香豆的库存时,批发分销商是Web服务的使用者,而当他为预期的客户提供不同的销售价格时,他就成了Web服务的提供者。

XML和Java Trademarked Platform的角色

         Web服务取决于各方彼此通信的能力,即使他们正使用不同的信息系统。XML(可扩展标记语言,Extensible Markup Language)是一种可以使数据具有可移植性的标记语言,它是满足Web服务这种需求的关键技术。很多企业发现使用XML有利于数据的集成,不管是在内部各部门之间共享遗留的数据,还是与其他企业进行数据共享。正因为如此,XML被越来越多地用于企业集成应用,无论是在紧密耦合系统中,还是在松散耦合系统中。由于具有数据集成的功能,XML已经成为与Web 相关处理的支柱。

         Web服务还取决于使用不同处理平台的企业彼此通信的能力。该种需求使得Java平台这种使代码具有可移植性的平台成为开发Web服务的当然选择。如果加上新的Java APIs for XML,这种选择就更具有吸引力了,因为这种Java API使得在Java编程语言中使用XML变得越来越容易。在本引言的后面将总结这些API,并且详细解释每个API的用法。

除了数据的可以移植性和代码的可移植性之外,Web服务还需要是可伸缩的,安全的并且是有效率的,尤其是当Web服务需要扩展时。Java 2平台Enterprise Edition (J2EE Trademarked )就是专门为满足这些需求而设计的。有了这种平台,在开发Web服务时碰到的一些艰巨的任务将变得简单起来,这些艰巨的任务包括编写基础设施,或“管道工程”。这种基础设施包括一些安全方面的特性、分布式事务管理,以及连接池管理,所有这些对于需要稳固的基础设施的Web服务来说,都是必不可少的。并且,由于组件是可重复使用的,开发时间也将大大减少。

什么是XML?

本节的目的是向你快速地介绍一下XML,以及XML如何使得数据具有可移植性,以便使你具备一些背景知识,从而可以顺利地阅读后面关于Java API for XML的概述。第1章包含了关于XML以及如何处理XML的更全面、更详细的介绍

XML是一种工业标准的、系统无关的数据表示方法。和HTML(超文本标记语言)一样,XML将数据包装在标签里面。但是,这两种标记语言也存在着明显的不同。首先,XML标签与被包装的文本的意义有关,而HTML标签则用于指定被包装文本的显示格式。接下来的XML例子展示了一个价格表,其中有两种咖啡的名称和价格。

<priceList>
  <coffee>
    <name>Mocha Java</name>
    <price>11.95</price>
  </coffee>
  <coffee>
    <name>Sumatra</name>
    <price>12.50</price>
  </coffee>
</priceList> 

<coffee> 和</coffee>这两个标签告诉解析器,在这两个标签之间的信息是关于一种咖啡的。在<coffee>标签里面的两个其他的标签则指出了这种咖啡的名称以及每磅的价格。由于XML标签表明了包含在他们里面的数据的内容和结构,所以这些标签使得归档和搜索这样的任务成为可能。

XML和HTML之间的第二个主要差别在于XML是可扩展的。有了XML,你就可以编写自己的标签,来描述某种特定类型的文档中的内容。XML可扩展性的另一个方面是,你可以创建一个模式(schema)文件,以描述一种特定类型的XML文档的结构。例如,你可以为某价格表编写一个模式,用于指定了可以使用哪些标签以及在哪里使用这些标签。任何一个服从于在模式中建立的约束机制的XML文档,都可以称其服从于该模式。

或许使用最广的schema语言依然还是文档类型定义(Document Type Definition,DTD)语言,因为它是XML1.0规范中的必备部分。通常称以这种语言写成的模式是一个DTD。下面的一个DTD就定义了在价格表XML文档中使用的标签。该DTD指定了4种标签(元素),并进一步指定了哪些标签可以(或需要)在其他标签中出现。该DTD还定义了一个XML文档的层次结构,包括标签在XML文档中出现的必须顺序。

<!ELEMENT priceList (coffee)+>
<!ELEMENT coffee (name, price) >
<!ELEMENT name (#PCDATA) >
<!ELEMENT price (#PCDATA) > 

本例中的首行给出了最顶层的元素:priceList,这一行的意思是文档中所有其他的标签都将在<priceList>和</priceList>这一对标签中出现。首行还告诉我们,priceList元素必须包含一个或更多的coffee元素(由加号标明)。第2行规定每个coffee元素都必须包含一个name元素和一个price元素, 并且必须按照这一顺序给出。第3行和第4行规定在标签<name> 和 </name>以及标签<price> 和 </price>之间的数据必须是字符型的数据,这些数据都是要分析的数据。每种咖啡的名称和价格都使组成价格表的实际的文本。

另一种常用的模式语言是XML Schema,这种语言是由万维网联盟(W3C)开发的。比起DTD来,XML Schema是一种强大得多的语言。而且,自从2001年5月它通过了W3C Recommendation之后,XML Schema的应用和实现都得到了良好的发展。使用Java平台的开发者社区已经认识到这一点, JAXP的专家组已经致力于在JAXP 1.2规范中增加对XML Schema的支持。这种Java Web Services Developer Pack的新版本包含了对XML Schema的支持。

XML为什么是可移植的?

模式使得XML数据具有可移植性。前面讨论过的priceList这个DTD就是一个模式的简单的例子。如果应用收到了以XML格式发送的一个priceList文档,还有一个priceList这样的DTD,那么该应用就可以根据DTD中定义的规则来处理这个文档。例如,如果给定的DTD是priceList,则解析器就可以知道任何基于这种DTD的XML文档的结构和其中内容的类型。如果解析器是一种确认解析器,那么它就可以知道,如果文档中含有在这个DTD中没有定义的一个元素,那么该文档就不是有效的文档。例如,如果文档中出现了<tea>这种元素,或者如果文档中的元素没有按照预先定义的顺序出现,比如将price元素排在了name元素的前面,那么该文档就是无效的。

还有一些其他的特性也使得XML被广泛用作数据交换的一种方法。其一,它是以文本的格式编写的,因此无论是对于人还是对于文本编辑软件,它都是可读的。应用可以分析和处理XML文档,而且,如果在处理过程中没有出错的话,人也可以读它们。另一特性就是,XML文档不包括格式规范,它可以通过各种方式显示出来。将数据与格式规范分开,就意味着相同的数据可以发布成不同的媒体。

虽然XML使文档具有可移植性,但这也不是仅仅依靠XML就可以做到的。也就是说,使用XML的人还必须同意服从特定的条件。例如,除了使用XML进行通信之外,两个应用还必须承认它们将用到的元素集以及这些元素的意义。如果这两个应用要使用Web服务,它们还必须承认它们将要使用的Web服务的方法,这些方法的行为,以及调用这些方法的顺序(如果需要调用多个方法的话)。

企业有多种技术可以用来帮助满足这些需求。它们可以使用DTD和XML模式来描述彼此间通信时用到的XML文档和条款的有效格式。Registry(注册中心)为描述Web服务及其方法提供了途径。对于更高级的概念,企业可以使用合伙人协议以及工作流程图和规划图。在本文的后面,还将介绍更多关于模式和注册中心的知识。

由于XML和Java平台在一起工作的效果是如此之好,这一组合已经成为Web服务中的一个核心角色。实际上, Java API for XML和J2EE平台带来的好处使得它们成为部署Web服务的梦幻组合。

该教程中介绍的API是对J2EE API的补充,并且位于J2EE API之上。有了这些API,Java社区、开发者以及工具和容器提供商就可以使用标准Java API来开始开发Web服务应用和产品,这些标准Java API维护了Java技术提倡的Write Once,Run Anywhere(一次编程,随处运行)。Java Web服务开发包(Java WSDP)将所有这些API放在一个单独的包中,供开发者使用。Java WSDP包含了实现这些API的JAR文件以及相关的文档和示例。在Java WSDP中的示例可以在Tomcat容器中运行(为便于使用,Tomcat容器被包含在WSDP中),这些示例还可以在J2EE服务器上的Web容器上运行,只要该J2EE服务器中安装了这种Java WSDP JAR文件,例如Sun Trademarked ONE Application Server (S1AS)。关于如何在S1AS7上安装JAR文件的介绍可以在<JWSDP_HOME>/docs/jwsdpons1as7.html中的Java WSDP文档里找到。

本节剩下的部分将快速介绍一下XML以及XML是如何使得数据具有可移植性的。接着,大致讨论一下Java API for XML,解释这些API的作用以及它们是如何使得编写Web应用更加容易的。本节分别描述了每一个API,并且还通过一个情景来剖析这些API是如何在一起发挥作用的。

接下来的教程给出了更详细的解释,并使你彻底弄懂如何使用Java API for XML来建立Web服务的应用,同时还提供了可以运行的示例。

Java APIs for XML概述

有了Java APIs for XML,就可以完全用Java编程语言来编写Web应用。Java APIs for XML有两类:一类直接处理XML文档,还有一类则处理过程。

·   面向文档的

o      Java API for XML Processing (JAXP) – 使用各种解析器处理XML文档

o      Java Architecture for XML Binding (JAXB) – 使用模式派生JavaBeans Trademarked 组件类处理XML文档。

·   面向过程的

o      Java API for XML-based RPC (JAX-RPC) –通过Internet向远程对方进行SOAP方法调用,并接收返回的结果。

o      Java API for XML Messaging (JAXM) – 通过Internet以一种标准的方式发送SOAP消息。

o      Java API for XML Registries (JAXR) – 为访问业务注册中心和共享信息提供一种标准的方式。

或许Java APIs for XML的最重要的特性就是这些API都支持工业标准,从而保证了互操作性。各种各样的互操作标准组织,如万维网联盟(World Wide Web Consortium ,W3C) 和结构化信息标准促进组织(Organization for the Advancement of Structured Information Standards ,OASIS),都正在致力于定义标准的操作方式,以使得那些遵从了这些标准的企业可以让他们的数据和应用协同工作。

Java APIs for XML的另一个特性就是它们支持强大的灵活性。只要用户善于利用这些API,他们就可以取得可观的灵活性。例如,JAXP代码可以使用各种工具来处理XML文档,而JAXM代码可以使用在SOAP之上的各种发送消息的协议。而且,工具也具有灵活性。虽然Java APIs for XML定义了一些关于严格兼容的需求,以确保所有的实现都能得出标准的功能,但是它们还是为开发者提供了广阔的自由空间,方便他们为特定用途提供合乎要求的实现。

接下来的几节将讨论每一种这样的API,旨在使你对这些API以及如何使用它们有一个感性的认识。

JAXP

JAXP使得采用以Java编写的应用来处理XML数据变得更加容易。JAXP采用了解析器标准SAX(Simple API for XML Parsing)和DOM(Document Object Model),从而为你分析事件流(stream of event)形式的数据或者为这些数据建立树结构的表示提供了选择。JAXP的最新版本还支持XSLT (XML Stylesheet Language Transformations)标准,这样你就可以控制这些数据的表示,并将数据转换成其他的XML文档或者其他的格式,例如HTML。JAXP还支持命名空间(namespace),这样你就可以放心使用本来可能产生冲突的模式。

由于JAXP被设计成具有灵活性,因此你可以在应用中使用任何XML兼容的解析器。之所以能够做到这一点,是因为这里采用了一个所谓的pluggability layer(可插入层),这样你就可以方便地插入SAX或DOM API的实现。可插入层还支持插入一个XAL处理器,利用这个处理器你就可以有各种各样的方式来转换XML数据格式,包括数据的显示格式。

JAXP 1.2.2提供了对XML Schema的支持,它被放在了Java WSDP中。

SAX API

Simple API for XML (SAX)为基于事件的解析器定义了一个API。如果解析器是基于事件的,那么它就可以从头到尾地读XML文档。而且,每当它识别出一个语句,它就会将这个语句通报给正在运行它自己的那个应用。SAX是通过调用来自ContentHandler接口的方法来通知应用的。例如,如果解析器碰到了一个小于号(“<”),它就调用startElement方法;如果解析器碰到的是字符数据,它就调用characters方法;如果解析器碰到的是后面跟一斜杠的小于号(“</”),那么它就调用endElement方法,等等。举个例子,让我们再来看看第一节中的一个XML的例子的一部分,观察解析器对其中的每一行是如何处理的。(为了简化问题,这里略去了对ignorableWhiteSpace方法的调用)

<priceList>   [parser calls startElement]
  <coffee>    [parser calls startElement]
    <name>Mocha Java</name>    [parser calls startElement,
                characters, and endElement]
    <price>11.95</price>    [parser calls startElement,
                characters, and endElement]
  </coffee>    [parser calls endElement] 

解析器要调用的这些方法的默认实现没有做任何事,因此你需要编写一个子类来实现适当的方法,从而得到想要的功能。例如,假设你希望得到每磅Mocha Java咖啡的价格,你就可以编写一个扩展了DefaultHandler(ContentHandler的默认实现)的新类,在这个新类中你就可以编写自己的对startElement和characters方法的实现。

首先,你需要从SAXParserFactory对象创建一个SAXParser对象,对该对象调用parse方法,将价格表和你新建的类(提供了startElement和characters方法的新的实现)的一个实例传给SAXParser对象。在本例中,虽然价格表是一个文件,但是parse方法还是可以采用各种其他的输入源,包括InputStream对象、一个URL和一个InputSource对象。

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
saxParser.parse("priceList.xml", handler); 

当然,调用parse方法的结果取决于方法handler是如何实现的。通过调用适当的方法,SAX解析器将一行一行地遍历priceList.xml文件。除了提到的这些方法以外,解析器还将调用其他的一些方法,如startDocument、endDocument、ignorableWhiteSpace以及processingInstructions,不过,到目前为止,这些方法都还只有默认的实现,因而做不了任何事。

接下来的方法定义展示了一种实现方法characters 和 startElement的方式,以使得这两个方法可以获得Mocha Java咖啡的价格,并将其打印出来。根据SAX解析器的工作方式,这两个方法要一起调用,来查找name元素(即“Mocha Java”),以及紧随其后的Mocha Java咖啡的价格。这两个方法采用了3个标签来跟踪可能碰到的不同情况。注意,SAX解析器需要不止一次地同时调用这两个方法,直到碰到了要打印价格的情况为止。

public void startElement(..., String elementName, ...){
  if(elementName.equals("name")){
    inName = true;
  } else if(elementName.equals("price") && inMochaJava ){
    inPrice = true;
    inName = false;
  }
} 
public void characters(char [] buf, int offset, int len) {
  String s = new String(buf, offset, len);
  if (inName && s.equals("Mocha Java")) {
    inMochaJava = true;
    inName = false;
  } else if (inPrice) {
    System.out.println("The price of Mocha Java is: " + s);
    inMochaJava = false;
    inPrice = false;
    }
  }
} 

一旦解析器找到了Mocha Java咖啡元素,调用以下方法之后,就会得到如下相应的状态:

调用 startElement方法后 -- inName 为 true

调用characters方法后 – inMochaJava为 true

调用startElemen方法后t -- inPrice 为 true

调用characters方法后 – 打印价格

在分析XML数据时,SAX解析器还可以确认这些数据,也就是说,它可以检查数据是否符合该XML文档的schema中定义的规则。如果SAX解析器是由SAXParserFactory对象创建的,那么它就有确认功能,因为SAXParserFactory对象已经实现了确认功能。这些是由SAXParserFactory对象factory实现的,代码如下:

factory.setValidating(true);  
 

这样一来,解析器就知道使用哪种模式作为确认标准,XML文档则必须在DOCTYPE声明中声明这个模式。如果价格表的模式是priceList.DTD,则在XML文档中的DOCTYPE声明如下:

<!DOCTYPE PriceList SYSTEM "priceList.DTD"> 

DOM API

Document Object Model (DOM)是由W3C Working Group(W3C工作组)定义的,它是一套用于建立一个对象的表示的接口集合,这种表示就是将分析过的XML文档表示成树的结构。一旦建立了DOM,你就可以通过DOM方法(如insert和remove)来操纵它,例如,你可以操纵任何其他的树状数据结构。因此,与SAX解析器不同,DOM解析器允许随机访问XML文档中特定的一块数据。还有一点不同就是,通过SAX解析器你只能读一个XML文档,而如果通过DOM解析器,你就可以在内存中为XML文档建立对象

表示,并对其进行操纵,例如添加一个元素,或者删除一个已有的元素。

在前面的例子中,我们使用了一个SAX解析器来查找文档中的一个价格数据。要使用DOM解析器,首先必须将整个文档对象模型存放在内存中,如果只是查找一小部分数据项的话,这样做通常是缺乏效率的,在文档比较大的时候更是如此。在接下来的例子中,我们通过一个DOM解析器将一条新的咖啡元素添加到价格表中。我们不能使用一个SAX解析器来修改价格表,因为它只能读数据。

假设你希望添加Kona咖啡到价格表中。首先,你需要将该XML价格表文件读入一个DOM中,然后插入新的咖啡元素,元素中包含了名称和价格。下面的代码段创建了一个DocumentBuilderFactory对象,然后用这个对象来创建一个DocumentBuilder对象builder。接下来,调用builder的parse方法,将文件priceList.xml传递给builder。

DocumentBuilderFactory factory =
          DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("priceList.xml"); 

在这种情况下,document是价格表在内存中的一个DOM表示。下面的代码段将一条新的咖啡元素(name为“Kona”,price为“13.50”)添加到价格表文档中。由于我们希望将这条新的咖啡元素正好添加在名为“Mocha Java”元素的前面,因此首先要获取一个咖啡元素列表,并从中找到“Mocha Java”元素。接着,通过使用org.w3c.dom包中的Node接口,代码为新的咖啡元素创建了一个Node对象,同时还为name和price元素创建了新的节点。Name和price元素包含了字符数据,所有代码为每个字符数据创建了一个Text对象,并且将这些text节点附加在表示name和price元素的节点上。

Node rootNode = document.getDocumentElement();
NodeList list = document.getElementsByTagName("coffee");
 
// Loop through the list.
for (int i=0; i < list.getLength(); i++) {
  thisCoffeeNode = list.item(i);
  Node thisNameNode = thisCoffeeNode.getFirstChild();
  if (thisNameNode == null) continue;
  if (thisNameNode.getFirstChild() == null) continue;
  if (! thisNameNode.getFirstChild() instanceof
                  org.w3c.dom.Text) continue;
 
  String data = thisNameNode.getFirstChild().getNodeValue();
  if (! data.equals("Mocha Java")) continue;
 
  //We're at the Mocha Java node. Create and insert the new
  //element.
 
  Node newCoffeeNode = document.createElement("coffee");
 
  Node newNameNode = document.createElement("name");
  Text tnNode = document.createTextNode("Kona");
  newNameNode.appendChild(tnNode);
 
  Node newPriceNode = document.createElement("price");
  Text tpNode = document.createTextNode("13.50");
  newPriceNode.appendChild(tpNode);
 
  newCoffeeNode.appendChild(newNameNode);
  newCoffeeNode.appendChild(newPriceNode);
  rootNode.insertBefore(newCoffeeNode, thisCoffeeNode);
  break;
} 

注意,为了简化问题,该代码段假设它所访问的节点都不是注释、属性或者可忽略的空白字符。要了解关于使用DOM来进行更强大的分析的信息,参见Increasing the Complexity(URL:http://java.sun.com/webservices/docs/1.1/tutorial/doc/JAXPDOM2.html#wp68475)

有了DOM解析器,你就可以通过和SAX解析器一样的确认方式来确认数据。在使用DOM 分析工厂来创建DOM分析之前,首先调用parser factory的setValidating(true),并确认XML文档是参考在DOCTYPE声明中声明的模式来进行分析的。

XML命名空间

在一个模式中的所有名字,包括那些在DTD中的名字,都是惟一的,这样就避免了相互之间的混淆。然而,对于一个引用了多个模式的XML文档来说,可能会有两个或更多的模式中包含了相同的名字。这样一来,文档就需要为每个模式定义一个命名空间,使得解析器在分析某个特定模式的一个实例时,能够分清应该使用哪个定义。

这里有一个标准的符号可以用于定义一个XML Namespace,namespace的定义通常被放在XML文档的根元素中。在下面的namespace定义中,通过符号xmlns将nsName指定为一个namespace,并且nsName被设置到实际命名空间的URL上。

<priceList xmlns:nsName="myDTD.dtd"
      xmlns:otherNsName="myOtherDTD.dtd">
...
</priceList> 

在该文档内部,可指定一个元素属于下面的哪个命名空间:

<nsName:price> ... 

为了让SAX或DOM解析器能够承认这样的命名空间,你可以调用ParserFactory实例的setNamespaceAware(true)方法。调用该方法之后,该解析器工厂创建的任何解析器都将承认该命名空间。

XSLT API

XML Stylesheet Language for Transformations (XSLT)是由W3C XSL Working Group定义的,它描述了一种用于将XML文档转换成其他XML文档或者其他格式的语言。在进行转换之前,通常需要提供一个样式表,这种样式表是用XML样式表语言(XML Stylesheet Language,XSL)写成的。XSL样式表指定了数据的显示格式,而XSLT则使用样式表中的格式指令来执行转换。

通过一个javax.xml.transform包,JAXP提供了对XSLT的支持,这样你就可以插入一个XSLT转换器来执行转换。 javax.xml.transform包的子包含有SAX-、DOM-和stream-specific API,通过这些API你可以直接从DOM树和SAX事件执行转换。接下来的两个例子演示了如何从DOM树创建XML文档以及如何通过XSL样式表将得到的XML文档转换成HTML。

将DOM树转换成XML文档

为了将在上一节创建的DOM树转换成XML文档,下面的代码首先创建了一个Transformer对象,该对象将执行转换。

TransformerFactory transFactory =
        TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer(); 

下面一行代码则使用DOM树根节点将DOMSource对象构造成转换源。

DOMSource source = new DOMSource(document); 
 

下面的代码段创建了一个StreamResult对象,通过该对象获取转换的结果,并将树转换成XML文件。

File newXML = new File("newXML.xml");
FileOutputStream os = new FileOutputStream(newXML);
StreamResult result = new StreamResult(os);
transformer.transform(source, result); 

将XML文档转换成HTML文档

你还可以通过XSLT,来将新的XML文档,即newXML.xml,转换成使用了样式表的HTML。编写样式表时,你可以使用XML Namespace来参考XSL结构。例如,每个样式表都有一个根元素,这个根元素指定了样式表语言,如下面的一行代码所示:

<xsl:stylesheet version="1.0" xmlns:xsl=
          "http://www.w3.org/1999/XSL/Transform"> 

当引用样式表语言中的一个特定的结构时,你可以使用namespace前缀,后面加上一个冒号,这样就可以应用这个结构了。例如,下面的一段样式表指定了name数据必须插入到HTML表(table)中的一行(row)。

<xsl:template match="name">
  <tr><td>
    <xsl:apply-templates/>
  </td></tr>
</xsl:template> 

下面的样式表指定了XML数据要转换成HTML,并且咖啡项要插入到HTML中的一个表中的一行。

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="priceList">
    <html><head>Coffee Prices</head>
      <body>
        <table>
          <xsl:apply-templates />
        </table>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="name">
    <tr><td>
      <xsl:apply-templates />
    </td></tr>
  </xsl:template>
  <xsl:template match="price">
    <tr><td>
      <xsl:apply-templates />
    </td></tr>
  </xsl:template>
</xsl:stylesheet> 

为了执行转换,首先需要获取一个XSLT转换器,并且用这个转换器来将样式表应用到XML数据上。接下来的代码段通过实例化一个TransformerFactory对象来得到一个转换器,接着在样式表和XML文件中读数据,然后为HTML输出创建一个文件,最后从TransformerFactory对象Factory获得Transformer对象 transformer。

TransformerFactory tFactory =
          TransformerFactory.newInstance();
String stylesheet = "prices.xsl";
String sourceId = "newXML.xml";
File pricesHTML = new File("pricesHTML.html");
FileOutputStream os = new FileOutputStream(pricesHTML);
Transformer transformer = 
  tFactory.newTransformer(new StreamSource(stylesheet));  

最后,只需调用transform方法,给该方法传递数据和输出流,就可以完成转换。

transformer.transform(

    new StreamSource(sourceId), new StreamResult(os));

 

 

常见问答

下载中心

产品简介

 

 

Solaris论坛