- XML Reference Guide
- Overview
- What Is XML?
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Table of Contents
- The Document Object Model
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- DOM and Java
- Informit Articles and Sample Chapters
- Books and e-Books
- Implementations
- DOM and JavaScript
- Using a Repeater
- Repeaters and XML
- Repeater Resources
- DOM and .NET
- Informit Articles and Sample Chapters
- Books and e-Books
- Documentation and Downloads
- DOM and C++
- DOM and C++ Resources
- DOM and Perl
- DOM and Perl Resources
- DOM and PHP
- DOM and PHP Resources
- DOM Level 3
- DOM Level 3 Core
- DOM Level 3 Load and Save
- DOM Level 3 XPath
- DOM Level 3 Validation
- Informit Articles and Sample Chapters
- Books and e-Books
- Documentation and Implementations
- The Simple API for XML (SAX)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- SAX and Java
- Informit Articles and Sample Chapters
- Books and e-Books
- SAX and .NET
- Informit Articles and Sample Chapters
- SAX and Perl
- SAX and Perl Resources
- SAX and PHP
- SAX and PHP Resources
- Validation
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Document Type Definitions (DTDs)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XML Schemas
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- RELAX NG
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Schematron
- Official Documentation and Implementations
- Validation in Applications
- Informit Articles and Sample Chapters
- Books and e-Books
- XSL Transformations (XSLT)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XSLT in Java
- Java in XSLT Resources
- XSLT and RSS in .NET
- XSLT and RSS in .NET Resources
- XSL-FO
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XPath
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XML Base
- Informit Articles and Sample Chapters
- Official Documentation
- XHTML
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XHTML 2.0
- Documentation
- Cascading Style Sheets
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XUL
- XUL References
- XML Events
- XML Events Resources
- XML Data Binding
- Informit Articles and Sample Chapters
- Books and e-Books
- Specifications
- Implementations
- XML and Databases
- Informit Articles and Sample Chapters
- Books and e-Books
- Online Resources
- Official Documentation
- SQL Server and FOR XML
- Informit Articles and Sample Chapters
- Books and e-Books
- Documentation and Implementations
- Service Oriented Architecture
- Web Services
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Creating a Perl Web Service Client
- SOAP::Lite
- Amazon Web Services
- Creating the Movable Type Plug-in
- Perl, Amazon, and Movable Type Resources
- Apache Axis2
- REST
- REST Resources
- SOAP
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- SOAP and Java
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- WSDL
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- UDDI
- UDDI Resources
- XML-RPC
- XML-RPC in PHP
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Ajax
- Asynchronous Javascript
- Client-side XSLT
- SAJAX and PHP
- Ajax Resources
- JSON
- Ruby on Rails
- Creating Objects
- Ruby Basics: Arrays and Other Sundry Bits
- Ruby Basics: Iterators and Persistence
- Starting on the Rails
- Rails and Databases
- Rails: Ajax and Partials
- Rails Resources
- Web Services Security
- Web Services Security Resources
- SAML
- Informit Articles and Sample Chapters
- Books and e-Books
- Specification and Implementation
- XML Digital Signatures
- XML Digital Signatures Resources
- XML Key Management Services
- Resources for XML Key Management Services
- Internationalization
- Resources
- Grid Computing
- Grid Resources
- Web Services Resource Framework
- Web Services Resource Framework Resources
- WS-Addressing
- WS-Addressing Resources
- WS-Notifications
- New Languages: XML in Use
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Google Web Toolkit
- GWT Basic Interactivity
- Google Sitemaps
- Google Sitemaps Resources
- Accessibility
- Web Accessibility
- XML Accessibility
- Accessibility Resources
- The Semantic Web
- Defining a New Ontology
- OWL: Web Ontology Language
- Semantic Web Resources
- Google Base
- Microformats
- StructuredBlogging
- Live Clipboard
- WML
- XHTML-MP
- WML Resources
- Google Web Services
- Google Web Services API
- Google Web Services Resources
- The Yahoo! Web Services Interface
- Yahoo! Web Services and PHP
- Yahoo! Web Services Resources
- eBay REST API
- WordML
- WordML Part 2: Lists
- WordML Part 3: Tables
- WordML Resources
- DocBook
- Articles
- Books and e-Books
- Official Documentation and Implementations
- XML Query
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XForms
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Resource Description Framework (RDF)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Topic Maps
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation, Implementations, and Other Resources
- Rich Site Summary (RSS)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Simple Sharing Extensions (SSE)
- Atom
- Podcasting
- Podcasting Resources
- Scalable Vector Graphics (SVG)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- OPML
- OPML Resources
- Summary
- Projects
- JavaScript TimeTracker: JSON and PHP
- The Javascript Timetracker
- Refactoring to Javascript Objects
- Creating the Yahoo! Widget
- Web Mashup
- Google Maps
- Indeed Mashup
- Mashup Part 3: Putting It All Together
- Additional Resources
- Frequently Asked Questions About XML
- What's XML, and why should I use it?
- What's a well-formed document?
- What's the difference between XML and HTML?
- What's the difference between HTML and XHTML?
- Can I use XML in a browser?
- Should I use elements or attributes for my document?
- What's a namespace?
- Where can I get an XML parser?
- What's the difference between a well-formed document and a valid document?
- What's a validating parser?
- Should I use DOM or SAX for my application?
- How can I stop a SAX parser before it has parsed the entire document?
- 2005 Predictions
- 2006 Predictions
- Nick's Book Picks
The ultimate goal of this project is to use Perl to gather information from a web service, so we'll start with that. Amazon's Electronic Commerce System (ECS, formerly Amazon Web Services) provides both a SOAP and a REST interface, but at least for now, we'll stick with SOAP.
We've talked about SOAP, the Simple Object Access Protocol, before. It is, at heart, just XML being sent between two points, usually via HTTP, so you could use Perl to get into the nitty gritty and work with the actual messages. Fortunately, we don't have to work that hard. Instead, we can use the SOAP::Lite package, which provides a number of handy capabilities, from building SOAP messages to analyzing WSDL files to actually sending the messages.
So let's start by building the simplest of systems. For example, consider a sytem that simply takes an ISBN and returns a book title. We might have a request message of:
<?xml version='1.0' ?> <env:Envelope xmlns:env="http://www.w3.org/2002/12/soap-envelope"> <env:Header></env:Header> <env:Body> <isbn:getTitle xmlns:isbn="http://www.nicholaschase.com/BookLook">0672324229</isbn:getTitle> </env:Body> </env:Envelope>
When we send the request to the web service, the service returns a message of:
<?xml version='1.0' ?> <env:Envelope xmlns:env="http://www.w3.org/2002/12/soap-envelope"> <env:Header></env:Header> <env:Body> <isbn:getTitleResponse xmlns:isbn="http://www.nicholaschase.com/BookLook">XML Primer Plus</isbn:getTitleResponse> </env:Body> </env:Envelope>
So how do we make it happen? Well, first, we need a server. (Actually, first we need to start by installing SOAP::Lite and integrating it with a web server. You can get instructions on that here. I've set up a simple server at http://www.nicholaschase.com/cgi-bin/isbn.cgi, which returns the title, author, and price of a book when given the ISBN.
To set that up, we'll start by creating the server.
Once you've got everything installed, create a Perl script and add the following code:#!/usr/local/bin/perl use CGI qw/:standard :netscape/; use SOAP::Transport::HTTP; SOAP::Transport::HTTP::CGI -> dispatch_to('BookLook') -> handle; package BookLook; sub getTitle { my ($class, $isbn) = @_; if ($isbn == '0672324229'){ return "XML Primer Plus"; } else { return "Unknown"; } } sub getAllInfo { my ($class, $isbn) = @_; if ($isbn == '0672324229'){ return 'XML Primer Plus by Nicholas Chase, $32.58'; } else { return "Unknown"; } }
I've saved mine in the cgi-bin
directory and called it isbn.cgi.
Now, besides the fact that I've obviously put this together a s a proof of concept (though it would, of course,
be nice if everyone who ever wanted a book wanted mine), notice that there's not a drop of XML or XML-related
code in this script. Instaed, we're creating a type of proxy. The dispatch_to
command takes the request
message and extracts the actual command, such as getTitle()
or getAllInfo()
, and dispatches
it to the proper subroutine. It then creates the response message from the data, which it sends back to the requestor.
So now we need a client to access the service. Create another script and add the following code:
#!/usr/local/bin/perl use SOAP::Lite; my $lookup = SOAP::Lite->uri('http://www.nicholaschase.com/BookLook') ->proxy('http://www.nicholaschase.com/cgi-bin/isbn.cgi'); print $lookup->getTitle('0672324229')->result;
Once again we're using the SOAP::Lite software to create a proxy, but this time, we're converting a command
into a SOAP message. The proxy creates that message, sends it, and waits for the response. It then extracts
the resulting data from that response. (Note that the uri
method sets the namespace URL for the request. Here,
it's the same as the package name.)
If you run this script from the command line, you should see a response something like:
>>>perl isbnclient.cgi XML Primer Plus
Now all of that is fine, but it's rare to find a web service with such a simple interface. In most cases, you're looking at something more like this request:
<env:Envelope xmlns:env="http://www.w3.org/2002/12/soap-envelope"> <env:Header></env:Header> <env:Body> <isbn:findIsbn xmlns:isbn="http://www.nicholaschase.com/BookLook"> <isbn:author>Nicholas Chase</isbn:author> <isbn:year>2002</isbn:year> </isbn:findIsbn> </env:Body> </env:Envelope>
or this response
<env:Envelope xmlns:env="http://www.w3.org/2002/12/soap-envelope"> <env:Header></env:Header> <env:Body> <isbn:getAllInfoResponse xmlns:isbn="http://www.nicholaschase.com/BookLook"> <isbn:info> <isbn:title>XML Primer Plus</isbn:title> <isbn:author>Nicholas Chase</isbn:author> <isbn:price>32.58</isbn:price> </isbn:info> </isbn:getAllInfoResponse> </env:Body> </env:Envelope>
We can build these complex messages using the SOAP::Data
object.
For example, we can create the request:
... my $lookup = SOAP::Lite->uri('http://www.nicholaschase.com/BookLook') ->proxy('http://www.nicholaschase.com/cgi-bin/isbn.cgi'); my $authorElement = SOAP::Data->name('author') ->value('Nicholas Chase'); my $yearElement = SOAP::Data->name('year') ->value('2003'); print $lookup->findIsbn($authorElement, $yearElement)->result;
Here we create the SOAP::Data
object, which is essentially an
XML element, and set its name and value. (Technically, we're actually creating
an element node and text node child.) We can then send these elements as payload of the message,
where they'll subsequently be used as the arguments of the method.
The server script accesses the data as input parameters:
... sub findIsbn { my ($class, $author, $year) = @_; if ($author == 'Nicholas Chase'){ if ($year == '2002'){ return "0672324229"; } else { return "Other"; } } else { return "Unknown"; } }
The server builds a more complex response the same way:
sub getAllInfo { my ($class, $isbn) = @_; if ($isbn == '0672324229'){ return SOAP::Data->name('info') ->value(SOAP::Data->name('title')->value('XML Primer Plus'), SOAP::Data->name(author=>'Nicholas Chase'), SOAP::Data->name(price=>'$32.58')); } else { return "Unknown"; } }
(Note that the server set up by SOAP::Lite
does not ordinarily return
a message like the one in the previous listing, although it can. By default, the message will
bear the name of the method involved. You can, however, override the Serializer to control
how everything looks, but that is well beyond the scope of this discussion.)
A few things to notice here. First, that we can have an XML element as the child of another element. Second, notice the slightly different structure I used in creating the author and the price. Both of these notations are correct.
The client reads the returned obect partially as an object and partially as an XML stream, using XPath to pull specific data:
my $lookup = SOAP::Lite->uri('http://www.nicholaschase.com/BookLook') ->proxy('http://www.nicholaschase.com/cgi-bin/isbn.cgi'); $response = $lookup->getAllInfo('0672324229'); print "The title is " . $response->dataof('//title')->value; print "\n"; print "The author is " . $response->dataof('//author')->value; print "\n"; print "The price is " . $response->dataof('//price')->value; print "\n";
We'll see more of this next, when we start dealing with actual Amazon data.