- Sams Teach Yourself XML in 21 Days, Third Edition
- Table of Contents
- About the Author
- Acknowledgments
- We Want to Hear from You!
- Introduction
- Part I: At a Glance
- Day 1. Welcome to XML
- All About Markup Languages
- All About XML
- Looking at XML in a Browser
- Working with XML Data Yourself
- Structuring Your Data
- Creating Well-Formed XML Documents
- Creating Valid XML Documents
- How XML Is Used in the Real World
- Online XML Resources
- Summary
- Q&A
- Workshop
- Day 2. Creating XML Documents
- Choosing an XML Editor
- Using XML Browsers
- Using XML Validators
- Creating XML Documents Piece by Piece
- Creating Prologs
- Creating an XML Declaration
- Creating XML Comments
- Creating Processing Instructions
- Creating Tags and Elements
- Creating CDATA Sections
- Handling Entities
- Summary
- Q&A
- Workshop
- Day 3. Creating Well-Formed XML Documents
- What Makes an XML Document Well-Formed?
- Creating an Example XML Document
- Understanding the Well-Formedness Constraints
- Using XML Namespaces
- Understanding XML Infosets
- Understanding Canonical XML
- Summary
- Q&A
- Workshop
- Day 4. Creating Valid XML Documents: DTDs
- All About DTDs
- Validating a Document by Using a DTD
- Creating Element Content Models
- Commenting a DTD
- Supporting External DTDs
- Handling Namespaces in DTDs
- Summary
- Q&A
- Workshop
- Declaring Attributes in DTDs
- Day 5. Handling Attributes and Entities in DTDs
- Specifying Default Values
- Specifying Attribute Types
- Handling Entities
- Summary
- Q&A
- Workshop
- Day 6. Creating Valid XML Documents: XML Schemas
- Using XML Schema Tools
- Creating XML Schemas
- Dissecting an XML Schema
- The Built-in XML Schema Elements
- Creating Elements and Types
- Specifying a Number of Elements
- Specifying Element Default Values
- Creating Attributes
- Summary
- Q&A
- Workshop
- Day 7. Creating Types in XML Schemas
- Restricting Simple Types by Using XML Schema Facets
- Creating XML Schema Choices
- Using Anonymous Type Definitions
- Declaring Empty Elements
- Declaring Mixed-Content Elements
- Grouping Elements Together
- Grouping Attributes Together
- Declaring all Groups
- Handling Namespaces in Schemas
- Annotating an XML Schema
- Summary
- Q&A
- Workshop
- Part I. In Review
- Well-Formed Documents
- Valid Documents
- Part II: At a Glance
- Day 8. Formatting XML by Using Cascading Style Sheets
- Our Sample XML Document
- Introducing CSS
- Connecting CSS Style Sheets and XML Documents
- Creating Style Sheet Selectors
- Using Inline Styles
- Creating Style Rule Specifications in Style Sheets
- Summary
- Q&A
- Workshop
- Day 9. Formatting XML by Using XSLT
- Introducing XSLT
- Transforming XML by Using XSLT
- Writing XSLT Style Sheets
- Using <xsl:apply-templates>
- Using <xsl:value-of> and <xsl:for-each>
- Matching Nodes by Using the match Attribute
- Working with the select Attribute and XPath
- Using <xsl:copy>
- Using <xsl:if>
- Using <xsl:choose>
- Specifying the Output Document Type
- Summary
- Q&A
- Workshop
- Day 10. Working with XSL Formatting Objects
- Introducing XSL-FO
- Using XSL-FO
- Using XSL Formatting Objects and Properties
- Building an XSL-FO Document
- Handling Inline Formatting
- Formatting Lists
- Formatting Tables
- Summary
- Q&A
- Workshop
- Part II. In Review
- Using CSS
- Using XSLT
- Using XSL-FO
- Part III: At a Glance
- Day 11. Extending HTML with XHTML
- Why XHTML?
- Writing XHTML Documents
- Validating XHTML Documents
- The Basic XHTML Elements
- Organizing Text
- Formatting Text
- Selecting Fonts: <font>
- Comments: <!-->
- Summary
- Q&A
- Workshop
- Day 12. Putting XHTML to Work
- Creating Hyperlinks: <a>
- Linking to Other Documents: <link>
- Handling Images: <img>
- Creating Frame Documents: <frameset>
- Creating Frames: <frame>
- Creating Embedded Style Sheets: <style>
- Formatting Tables: <table>
- Creating Table Rows: <tr>
- Formatting Table Headers: <th>
- Formatting Table Data: <td>
- Extending XHTML
- Summary
- Q&A
- Workshop
- Day 13. Creating Graphics and Multimedia: SVG and SMIL
- Introducing SVG
- Creating an SVG Document
- Creating Rectangles
- Adobe's SVG Viewer
- Using CSS Styles
- Creating Circles
- Creating Ellipses
- Creating Lines
- Creating Polylines
- Creating Polygons
- Creating Text
- Creating Gradients
- Creating Paths
- Creating Text Paths
- Creating Groups and Transformations
- Creating Animation
- Creating Links
- Creating Scripts
- Embedding SVG in HTML
- Introducing SMIL
- Summary
- Q&A
- Workshop
- Day 14. Handling XLinks, XPointers, and XForms
- Introducing XLinks
- Beyond Simple XLinks
- Introducing XPointers
- Introducing XBase
- Introducing XForms
- Summary
- Workshop
- Part III. In Review
- Part IV: At a Glance
- Day 15. Using JavaScript and XML
- Introducing the W3C DOM
- Introducing the DOM Objects
- Working with the XML DOM in JavaScript
- Searching for Elements by Name
- Reading Attribute Values
- Getting All XML Data from a Document
- Validating XML Documents by Using DTDs
- Summary
- Q&A
- Workshop
- Day 16. Using Java and .NET: DOM
- Using Java to Read XML Data
- Finding Elements by Name
- Creating an XML Browser by Using Java
- Navigating Through XML Documents
- Writing XML by Using Java
- Summary
- Q&A
- Workshop
- Day 17. Using Java and .NET: SAX
- An Overview of SAX
- Using SAX
- Using SAX to Find Elements by Name
- Creating an XML Browser by Using Java and SAX
- Navigating Through XML Documents by Using SAX
- Writing XML by Using Java and SAX
- Summary
- Q&A
- Workshop
- Day 18. Working with SOAP and RDF
- Introducing SOAP
- A SOAP Example in .NET
- A SOAP Example in Java
- Introducing RDF
- Summary
- Q&A
- Workshop
- Part IV. In Review
- Part V: At a Glance
- Day 19. Handling XML Data Binding
- Introducing DSOs
- Binding HTML Elements to HTML Data
- Binding HTML Elements to XML Data
- Binding HTML Tables to XML Data
- Accessing Individual Data Fields
- Binding HTML Elements to XML Data by Using the XML DSO
- Binding HTML Tables to XML Data by Using the XML DSO
- Searching XML Data by Using a DSO and JavaScript
- Handling Hierarchical XML Data
- Summary
- Q&A
- Workshop
- Day 20. Working with XML and Databases
- XML, Databases, and ASP
- Storing Databases as XML
- Using XPath with a Database
- Introducing XQuery
- Summary
- Q&A
- Workshop
- Day 21. Handling XML in .NET
- Creating and Editing an XML Document in .NET
- From XML to Databases and Back
- Reading and Writing XML in .NET Code
- Using XML Controls to Display Formatted XML
- Creating XML Web Services
- Summary
- Q&A
- Workshop
- Part V. In Review
- Appendix A. Quiz Answers
- Quiz Answers for Day 1
- Quiz Answers for Day 2
- Quiz Answers for Day 3
- Quiz Answers for Day 4
- Quiz Answers for Day 5
- Quiz Answers for Day 6
- Quiz Answers for Day 7
- Quiz Answers for Day 8
- Quiz Answers for Day 9
- Quiz Answers for Day 10
- Quiz Answers for Day 11
- Quiz Answers for Day 12
- Quiz Answers for Day 13
- Quiz Answers for Day 14
- Quiz Answers for Day 15
- Quiz Answers for Day 16
- Quiz Answers for Day 17
- Quiz Answers for Day 18
- Quiz Answers for Day 19
- Quiz Answers for Day 20
- Quiz Answers for Day 21
A SOAP Example in Java
You can use SOAP with Java by using Web services, but doing so is more advanced than the Java work you've already seen in this book. In this example, you're going to use Java servlets on a Web server. For this example you'll use two servlets—one that sends the SOAP message and one that receives that message. The receiving servlet will decode the data in the SOAP message and return a new SOAP message indicating that it has understood.
You need a Web server that can run Java servlets for this example. The Tomcat server is the premier Web server for JavaServer Pages and servlets; you can download it from http://jakarta.apache.org/tomcat/. Downloading and installing Tomcat is not difficult; just use the installation directions that come with Tomcat. After you have Tomcat installed and running, navigate to http://localhost:8080/index.html, and you should see Tomcat running, as in Figure 18.1.
Figure 18.1 Getting the Tomcat server running.
To support Web services, you also need some additional Java packages. There are two options when you're using SOAP with Java—you can download the Java XML pack, which is at (as of this writing) http://java.sun.com/xml/downloads/javaxmlpack.html, or you can download the Java Web Services Developer's Pack, which is at (as of this writing) http://java.sun.com/webservices/webservicespack.html. It's easiest to download the Java XML pack, which is a simple zipped file that holds the JAR files you'll need: jaxm-api.jar, saaj-api.jar, andactivation.jar. You also need servlet.jar to create servlets, and this file comes with Tomcat, in the lib directory.
There's another step you need to take at this point: You need to set up Tomcat to work with Java XML Messaging (JAXM). You should stop Tomcat if it's running and copy jaxm-docs.war, which comes with the Java XML Pack or the Java Web Services Developer's Pack, to the Tomcat webapps directory, and then you can restart Tomcat and navigate to http://localhost:8080/jaxm-docs/tomcat.html for directions. Setting up Tomcat for JAXM simply involves copying some JAR (Java archive) and WAR (Web archive) files.
With Tomcat set up, you're ready to write the two SOAP servlets you're going to use today: the server, ch18_04, and the client, ch18_05. For this example, you'll start by opening a new Web page, ch18_06.html, that has a link in it to the server servlet, ch18_04. When that link is clicked, the server will send a SOAP message to the client servlet, indicating how many laptops you have in stock, and the client servlet will then send back an acknowledging SOAP message. The actual SOAP messages will also be written to file so you can see what the two servlets sent each other. You'll start by creating the server servlet, ch18_04.
Creating the Server
The first servlet will create and send a SOAP message indicating that you have 216 laptops available. You start by creating a SOAP connection object named connection:
package soapExample; import java.io.*; import java.net.*; import javax.servlet.*; import javax.xml.soap.*; import javax.activation.*; import javax.servlet.http.*; public class ch18_04 extends HttpServlet { private SOAPConnection connection; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); try { SOAPConnectionFactory connectionFactory = SOAPConnectionFactory.newInstance(); connection = connectionFactory.createConnection(); } catch(Exception e) {} }
When the servlet is called, its doGet method will be executed, and that's the method where most of your code will go. Here, you create a MessageFactory object and a SOAP message:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { String outString ="<HTML><H1>Sending and reading the SOAP Message</H1><P>"; try { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage outgoingMessage = messageFactory.createMessage(); . . .
Create the parts of the message, including the envelope, header, and body, like this:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { String outString ="<HTML><H1>Sending and reading the SOAP Message</H1><P>"; try { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage outgoingMessage = messageFactory.createMessage(); SOAPPart soappart = outgoingMessage.getSOAPPart(); SOAPEnvelope envelope = soappart.getEnvelope(); SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody(); . . .
Now you add an element named <laptops:numberAvailable> to the SOAP message's body and indicate that there are 216 laptops available, like this:
body.addBodyElement(envelope.createName("numberAvailable", "laptops", "http://www.XMLPowerCorp.com")).addTextNode("216");
You can also add attachments to SOAP messages, which you'll do next. In this case, you'll send a text attachment. A handy text file is the ch18_06.html document that you browse to in order to run this example, and here's how to attach it to the SOAP message:
StringBuffer serverUrl = new StringBuffer(); serverUrl.append(request.getScheme()).append("://") .append(request.getServerName()); serverUrl.append(":").append(request.getServerPort()) .append(request.getContextPath()); String baseUrl = serverUrl.toString(); URL url = new URL(baseUrl + "/ch18_06.html"); AttachmentPart attachmentpart = outgoingMessage.createAttachmentPart(new DataHandler(url)) ; attachmentpart.setContentType("text/html"); outgoingMessage.addAttachmentPart(attachmentpart) ;
Now you will write our SOAP message to a file, out.msg, so you can look at it later and send that message to the client:
URL client = new URL(baseUrl + "/ch18_05"); FileOutputStream outgoingFile = new FileOutputStream("out.msg"); outgoingMessage.writeTo(outgoingFile); outgoingFile.close(); outString += "SOAP outgoingMessage sent (see out.msg). <BR>"; SOAPMessage incomingMessage = connection.call(outgoingMessage, client);
The SOAP message you get back from the client, which should acknowledge that there are 216 laptops available, is in the incomingMessage object, which you write to the file in.msg so you can take a look at it later:
if (incomingMessage != null) { FileOutputStream incomingFile = new FileOutputStream("in.msg"); incomingMessage.writeTo(incomingFile); incomingFile.close(); outString += "SOAP outgoingMessage received (see in.msg).</HTML>"; } . . .
That completes the server, which is your ch18_04 servlet. The server's code, ch18_04.java, is shown in Listing 18.4.
Example 18.4. SOAP Server (ch18_04.java)
package soapExample; import java.io.*; import java.net.*; import javax.servlet.*; import javax.xml.soap.*; import javax.activation.*; import javax.servlet.http.*; public class ch18_04 extends HttpServlet { private SOAPConnection connection; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); try { SOAPConnectionFactory connectionFactory = SOAPConnectionFactory.newInstance(); connection = connectionFactory.createConnection(); } catch(Exception e) {} } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { String outString = "<HTML><H1>Sending and reading the SOAP Message</H1><P>"; try { MessageFactory messageFactory = MessageFactory.newInstance(); SOAPMessage outgoingMessage = messageFactory.createMessage(); SOAPPart soappart = outgoingMessage.getSOAPPart(); SOAPEnvelope envelope = soappart.getEnvelope(); SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody(); body.addBodyElement(envelope.createName("numberAvailable", "laptops", "http://www.XMLPowerCorp.com")).addTextNode("216"); StringBuffer serverUrl = new StringBuffer(); serverUrl.append(request.getScheme()).append("://"). append(request.getServerName()); serverUrl.append(":").append(request.getServerPort()). append(request.getContextPath()); String baseUrl = serverUrl.toString(); URL url = new URL(baseUrl + "/ch18_06.html"); AttachmentPart attachmentpart = outgoingMessage. createAttachmentPart(new DataHandler(url)); attachmentpart.setContentType("text/html"); outgoingMessage.addAttachmentPart(attachmentpart); URL client = new URL(baseUrl + "/ch18_05"); FileOutputStream outgoingFile = new FileOutputStream("out.msg"); outgoingMessage.writeTo(outgoingFile); outgoingFile.close(); outString += "SOAP outgoingMessage sent (see out.msg). <BR>"; SOAPMessage incomingMessage = connection. call(outgoingMessage, client); if (incomingMessage != null) { FileOutputStream incomingFile = new FileOutputStream("in.msg"); incomingMessage.writeTo(incomingFile); incomingFile.close(); outString += "SOAP outgoingMessage received (see in.msg).</HTML>"; } } catch(Throwable e) {} try { OutputStream outputStream = response.getOutputStream(); outputStream.write(outString.getBytes()); outputStream.flush(); outputStream.close(); } catch (IOException e) {} } }
Creating the Client
The next step is to create the client, the ch18_05 servlet, which gets the server's SOAP message, interprets it, and sends a message back, indicating that it has understood the incoming message. Start by basing this servlet on the JAXMServlet class so that it can handle SOAP messages and creating a MessageFactory object so you can send SOAP messages:
package soapExample; import java.util.*; import javax.servlet.*; import javax.xml.soap.*; import javax.servlet.http.*; import javax.xml.messaging.*; public class ch18_05 extends JAXMServlet implements ReqRespListener { static MessageFactory messageFactory = null; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); try { messageFactory = MessageFactory.newInstance(); } catch (Exception ex) {} } . . .
Now you can decipher the incoming SOAP message by getting the value of the <laptops:numberAvailable> element and storing it in a variable named element, like this:
public SOAPMessage onMessage(SOAPMessage msg) { try { SOAPPart soappart = msg.getSOAPPart(); SOAPEnvelope incomingEnvelope = soappart.getEnvelope(); SOAPBody body = incomingEnvelope.getBody(); Iterator iterator = body.getChildElements( incomingEnvelope.createName("numberAvailable", "laptops", "http://www.XMLPowerCorp.com")); SOAPElement element; element = (SOAPElement) iterator.next(); . . .
The number of laptops left in stock can now be accessed with element.getValue(), and here's how to create a SOAP message to send back to the server, indicating that you've gotten that data:
SOAPMessage message = messageFactory.createMessage(); SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); envelope.getBody().addChildElement(envelope. createName("Response")).addTextNode( "Got the SOAP message indicating there are " + element.getValue() + " laptops available." ); . . . }
Finally, send the new SOAP message that acknowledges the number of laptops back to the client by returning the new message, which automatically sends it back to the server servlet, ch18_04, as you can see in ch18_05.java, the SOAP client, in Listing 18.5.
Example 18.5. A SOAP Client (ch18_05.java)
package soapExample; import java.util.*; import javax.servlet.*; import javax.xml.soap.*; import javax.servlet.http.*; import javax.xml.messaging.*; public class ch18_05 extends JAXMServlet implements ReqRespListener { static MessageFactory messageFactory = null; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); try { messageFactory = MessageFactory.newInstance(); } catch (Exception ex) {} } public SOAPMessage onMessage(SOAPMessage msg) { try { SOAPPart soappart = msg.getSOAPPart(); SOAPEnvelope incomingEnvelope = soappart.getEnvelope(); SOAPBody body = incomingEnvelope.getBody(); Iterator iterator = body.getChildElements( incomingEnvelope.createName("numberAvailable", "laptops", "http://www.XMLPowerCorp.com")); SOAPElement element; element = (SOAPElement) iterator.next(); SOAPMessage message = messageFactory.createMessage(); SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); envelope.getBody().addChildElement(envelope .createName("Response")).addTextNode( "Got the SOAP message indicating there are " + element.getValue() + " laptops available." ); return message; } catch(Exception e) {return null;} } }
To compile these new servlets, ch18_04.java and ch18_05.java, you need to have servlet.jar, jaxm-api.jar, saaj-api.jar, and activation.jar in the Java classpath environment variable. For example, if those JAR files are in the same directory as ch18_04.java and ch18_05.java, here's what this looks like:
%set classpath=servlet.jar;jaxm-api.jar;saaj-api.jar;activation.jar %javac ch18_04.java %javac ch18_05.java
If the JAR files are in the same directory as ch18_04.java and ch18_05.java, you need to make sure to preface every JAR file filename with its correct path.
This gives you the compiled files you need, ch18_04.class and ch18_05.class. How can you run the server, ch18_04.class? Here, you'll use an HTML document, ch18_06.html, to call the ch18_04.class servlet by using a hyperlink. Listing 18.6 shows how this HTML document works. When the user clicks the hyperlink, the server servlet is called, the server servlet sends a SOAP message to the client servlet, and the client servlet returns a SOAP message to the server.
Example 18.6. The SOAP Example Introduction Page (ch18_06.html)
<HTML> <HEAD> <TITLE>SOAP and Java</TITLE> </HEAD> <BODY> <H1>SOAP and Java</H1> Click <A HREF="ch18_04">here</a> to send the SOAP message. </BODY> </HTML>
Now you need to install all that you've done in the Tomcat server. To do that, begin by creating a file named web.xml that will tell Tomcat about the ch18_04.class and ch18_05.class files so that you can use those files with Tomcat. Here's what web.xml looks like:
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <servlet> <servlet-name> ch18_04 </servlet-name> <servlet-class> soapExample.ch18_04 </servlet-class> </servlet> <servlet> <servlet-name> ch18_05 </servlet-name> <servlet-class> soapExample.ch18_05 </servlet-class> </servlet> <servlet-mapping> <servlet-name> ch18_04 </servlet-name> <url-pattern> /ch18_04 </url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name> ch18_05 </servlet-name> <url-pattern> /ch18_05 </url-pattern> </servlet-mapping> </web-app>
Now that you have all the files you'll need, you can install them in the Tomcat webapps directory in order to make them available through the Tomcat server. You'll install these files in a directory named JavaSoap and place your actual servlet code in a directory named soapExample (which is the Java package for those servlets). Here's what the completed directory structure looks like:
webapps [This is a directory] |____JavaSoap [This is a directory] |____ch18_06.html [Our starting Web page] |____WEB-INF [This is a directory] |____web.xml [Configures Tomcat] |____classes [This is a directory] |____soapExample [This is a directory] |____ch18_04.class [The server servlet] |____ch18_05.class [The client servlet]
After you copy these files as shown here, start Tomcat (or if it was already started, stop it and start it again). Now all you need to do is navigate a browser to http://localhost:8080/soap/ch18_06.html, as shown in Figure 18.2.
Figure 18.2 The Java SOAP example's opening page.
Now click the hyperlink shown in Figure 18.2 in order to call the server servlet, which sends the first SOAP message, stating the number of laptops available in stock, to the client servlet, which sends back an acknowledgement. Figure 18.3 shows the results of calling the server servlet.
Figure 18.3 The results of the Java SOAP example.
What does the SOAP message sent from the server to the client look like? You can see it in the file out.msg, which is written to the Tomcat bin directory. Note that out.msg contains not only your SOAP message, but also the attached text, ch18_06.html:
------=_Part_4_6912871.1056396066449 Content-Type: text/xml <?xml version="1.0" encoding="UTF-8"?> <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:Header/> <soap-env:Body> <laptops:numberAvailable xmlns:laptops="http://www.XMLPowerCorp.com"> 216 </laptops:numberAvailable> </soap-env:Body> </soap-env:Envelope> ------=_Part_4_6912871.1056396066449 Content-Type: text/html <HTML> <HEAD> <TITLE>SOAP and Java</TITLE> </HEAD> <BODY> <H1>SOAP and Java</H1> Click <A HREF="ch18_04">here</a> to send the SOAP message. </BODY> </html> ------=_Part_4_6912871.1056396066449--
Here's what the SOAP message the client sent back to the server, as the code stored in in.msg, looks like (note that the client is acknowledging the data the server sent):
<?xml version="1.0" encoding="UTF-8"?> <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:Header/> <soap-env:Body> <Response> Got the SOAP message indicating there are 216 laptops available. </Response> </soap-env:Body> </soap-env:Envelope>
In this example you've been able to send, interpret, and reply to a SOAP message in Java. You've taken a look at programming examples in both .NET and Java now, and as you can see, both packages give SOAP support. You've just scratched the surface so far—covering the uses of SOAP can take whole books—but you have an idea what SOAP is good for from what you've seen. We'll turn now to RDF.