The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at Mozilla Public License Version 1.1
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License.
The Original Code is Presenting XML.
The Initial Developer of the Original Code is Daniel Parker. Portions created by Daniel Parker are Copyright (C) 2003 Economic Technology, Inc. All Rights Reserved.
Contributor(s): Bob Bartholomay
Alternatively, the contents of this file may be used under the terms of the LGPL license (the "GNU LESSER GENERAL PUBLIC LICENSE") license, in which case the provisions of LGPL License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the LGPL License and not to allow others to use your version of this file under the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the LGPL License. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the LGPL License.
Table of Contents
Table of Contents
Table of Contents
Presenting XML is an extendible, component-based framework for XML/XSLT applications that aims at achieving a complete separation of content from presentation. It supports styling XML content with XSLT stylesheets, as well as additional processing to other formats like pdf. It supports targeting different types of devices (e.g. browsers,handhelds) with different flavors of markup (e.g. HTML,WML.)
The promise of an XML/XSLT based approach to achieve separation of content and presentation is compelling. Many companies are moving in this direction, away from approaches like JSPs.
There are a number of frameworks out there that support publishing content styled with XSLT sheets. Apache Coccon is one that is well known in the open source community. Most existing approaches, however, do not allow for much richness in the way that XSLT sheets get selected to style content. Obviously required is the ability to choose stylesheets based on target device, but that is not enough.
Dynamic, interactive sites require a much richer way of selecting styleheets at runtime. The selection of a stylesheet may need to depend on parameters in the http request, and also on tags in the supplied XML content. A request may be for a summary or a detailed view; we may want to style the same content differently depending on the view requested. A request may be for dynamic content to be fed back from some remote resource; that request may fail, and we may end up needing to style error tags with an error sheet.
Presenting XML attempts to recognize the device and determine its supported MIME types, and then sends the request to the most conforming request handler. The request handler authenticates the request, and, if the request passes, assembles a pipeline for servicing the request. Alternate pipelines may be assembled based on tests of XPATH expressions matched on request parameters. Simple examples with XML, XSLT, and java are used to illustrate how this works.
The current version can be configured to work with any fully TrAX conformant XSLT transformer, including Saxon and Apache Xalan. The default configuration is for the Saxon XSLT transformer, the Apache Xerces XML parser, and the Apache fop pdf driver. Future versions will support any conformant XML parser.
Configuration is based on XML files.
Presenting XML provides a Model-View-Presenter framework for web applications that supports:
The nature of the model data itself is largely outside the scope of the Presenting XML pipeline framework; the content management layer merely specifies a way for transferring XML back to the presenter as SAX events. Where that content comes from is no business of the framework; it could come from Entity Java Beans, direct access to the database, or system files - the framework doesn't care.
The distribution provides components that implement adapters for certain kinds of content, including XML files, delimited and fixed length flat files, and SQL databases. It also provides a component that implements a more general adapter for user defined dynamic content.
The presenter gets back a representation of the data as a stream of SAX events. The presenter then needs to do something - perhaps style the XML source with an XSLT sheet and send the result back to a browser, or perhaps redirect the request to another url. These actions are described declaratively in a resources script.
Table of Contents
The full Presenting XML distribution may be obtained from https://sourceforge.net/projects/presentingxml/. It includes the source code and build files as well as binary jar files, a sample web application, and run scripts. It includes api documentation and a user guide. It also includes a number of third party jar files.
The directory layout under the top level presentingxml directory is as follows:
src/java - Directory containing the java source files for the Presenting XML framework.
src/docs - Directory containing the DocBook XML source files for documentation.
src/resources - Directory containing the startup.xml file for managing configuration.
modules - Directory containing the source code and third party jar files for optional modules.
docs - Directory containing javadoc and a user guide.
lib/ - Directory containing jar files that will be copied to the web server lib deployment directory.
lib/local - Directory containing your own jar files you want to use in a console app or web app.
lib/optional - Directory containing jar files copied during the build process from the modules/<module>/lib directories.
lib/servletapi - Contains the servlet.jar file used in building the distribution files.
tools/junit - Directory containing the junit jar file for the test suite.
tools/ant - Directory containing the ant jar files for the builds.
webapps/bookstore - Directory containing a sample web application.
consoleapps - Directory containing examples of running presentingxml from the command line.
tests - Directory containing junit tests.
build - Directory containing temporary files during the build process.
The following software components are not included and must be downloaded and installed separately:
Java development environment.
Servlet 2.2 compliant web server, such as Jakarta Tomcat
A WAP browser emulator.
Presenting XML requires Java JDK 1.3 or later (it will not work with earlier versions.) It has been tested with Sun's Java JDK 1.3.1, on Windows 2000 and on Linux.
You will need to configure your web server to work with Presenting XML. This section describes how to do that for Jakarta Tomcat 4.0.
The distribution files for the Jakarta Tomcat 4.0 web server may be obtained from http://jakarta.apache.org/site/binindex.html.
The steps to configure Jakarta Tomcat to work with Presenting XML are as follows:
Edit the server.xml file in the tomcat conf directory. Add the following Context element in the server.xml file (changing docBase as appropriate):
<Context path="/bookstore"
docBase="C:/Projects/presentingxml/webapps/bookstore"
debug="0"
reloadable="true" >
</Context>
Set the environmental variable JAVA_HOME to a version of the jdk 1.3 or above, i.e.
set JAVA_HOME=C:\tools\java\jdk1.3.1(changing C:\tools as appropriate), or add the above line to the top of the startup.bat file (tomcat.sh for Unix) in the jakarta tomcat bin directory.
Presenting XML requires a WAP browser emulator for viewing the sample WML pages. A free WAP browser emulator may be obtained from OPENWAVE.
Before building the sample web application, be sure to build the presentingxml project. From the command prompt in the top level presentingxml directory, enter build.
The webapps/bookstore subdirectory is the "document root" for a sample web application. It is set up to be compatible with the Web Application Architecture (WAR) standard. It has the following components:
config - Directory containing the presentingxml.xml configuration file.
pages - Directory containing the pages.xml file.
documents - Directory containing the document catalog and any system XML files.
styles - Directory containing the style catalog and the stylesheets.
java - Directory containing the java source files for the sample.
build - Directory containing temporary files during the build process.
WEB-INF/web.xml - The Web Application Deployment Descriptor for the sample application.
WEB-INF/lib - Directory that will contain the deployed jar files.
Set the environmental variable JAVA_HOME to a version of the jdk 1.3 or above, i.e.
set JAVA_HOME=C:\tools\java\jdk1.3.1(changing C:\tools as appropriate), or add the above line to the top of the build.cmd file (build.sh for Unix) in the webapps/bookstore directory.
Build the sample web application by entering build at the command prompt in the webapps/bookstore directory.
If everything has gone correctly you should now be able to run the sample web application.
Start the tomcat server by entering startup at the command prompt in the jakarta tomcat bin directory.
Open the following URL in a browser: http://localhost:8080/bookstore/pages/books
Now click on one of the categories in the left panel.
For a pdf example, under the Featured Books section in the left panel, click on "Pulp"
Finally, try opening the books URL http://localhost:8080/bookstore/pages/books in a WAP browser emulator.
Shutdown the tomcat server by entering shutdown at the command prompt in the jakarta tomcat bin directory.
The pages subdirectory contains the pages.xml file. The purpose of the pages.xml file is to define the pages that a client may request of the web server. Each request for a page has a specified source of XML content and the rules for styling that XML content. The source of XML content is represented by a document name. The rules for styling that XML content are specified by transform and serialize actions. A style attribute specifies which stylesheet to use.
The documents sub-directory contains the configuration file documents.xml. The purpose of the documents.xml file is to define sources of XML content and to give them names. A source of XML content need not exist as a document per se. It may exist as a java object which is capable of feeding start/end elements into a SAX 2 ContentHandler.
The documents.xml defines a source of XML content with a url (if it is really an XML file) or a request handler (if the data will be coming from a SAX source.)
There are two types of request handlers.
SelectHandler - Defines an interface for getting dynamic XML content (e.g. a document, results from a database query.) This content may be cached depending on the caching options in effect. An example is BookCatalog under the java/samples/books subdirectory.
UpdateHandler - Defines an interface for posting data values (e.g. updating values in a database.) A UpdateHandler may also return dynamic XML content. If it does, that content is never cached.
The WEB-INF/web.xml file is the Web Application Deployment Descriptor for the sample application.
<?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>presenter</servlet-name>
<servlet-class>com.presentingxml.presenter.http.PresenterServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>appName</param-name>
<param-value>myapp</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>presenter</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
</web-app>
Note the init-param element, which defines the name of the web app as "myapp."
Table of Contents
The purpose of a resources script is to provide a catalog of named pages that encapsulate a service of some kind. A page is associated with actions - transforming XML to HTML through the application of a stylesheet, serializing XML to PDF, transforming a flat file to XML, updating records in a database, and so forth.
A simple example is shown below.
Example 3.1. The Books Resources Script
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
xmlns:myapp="http://www.presentingxml.com/myapp"
ns="http://www.presentingxml.com/myapp">
<px:app>
<px:mapRequest>
<px:matchRequestURI match="/bookstore/pages/(.+)">$1</px:matchRequestURI>
</px:mapRequest>
</px:app>
<px:page name="books">
<px:parameter ns="" name="category"/>
<px:show>
<px:transform>
<px:content ref="myapp:books"/>
<px:style ref="myapp:books"/>
</px:transform>
</px:show>
</px:page>
<px:dynamicContent name="books" className="samples.books.BookCatalog">
<px:key>
<px:field name="category"/>
</px:key>
</px:dynamicContent>
<px:style name="books" href="html/books/books.xsl"/>
</px:resources>
Each element in the resources script has a prefix px:. The resources element associates the px: prefix with the Presenting XML namespace in the declaration xmlns:px="http://www.presentingxml.com/PresentingXML". In this way, the page, content and style elements are identified as belonging to Presenting XML, not to the author of the books content and stylesheet.
Note the px:app element at the head of the books resources script. The app element optionally contains a px:mapRequest element that defines the mapping of request URIs into page names. If no request mapper element is specified, the default is to look for a page with whatever namespace happens to be in scope and a local name the same as the request URI. In the example, we see a single px:matchRequestURI element that maps a request URI like /bookstore/pages/welcome into a page with namespace "http://www.presentingxml.com/myapp" and local name "welcome".
The books resources script defines a number of resources: a page, a document, and a style. These names belong to the author of the books resources. Each resource is given a name. A name has two parts, a local name and a namespace URI. The local name is specified by a name attribute. The namespace URI is specified by a ns attribute. If the element defining the resource does not specify a ns attribute, the namespace URI defaults to that of the nearest ancestor element that does have a ns attribute, or the empty string if there is none. In the books example, therefore, the page takes a local name "books" and the namespace URI "http://www.presentingxml.com/myapp". The prefix myapp: is associated with that namespace.
Pages are defined with the page element. In the books page element above, we see a page element that defines a response, which consists of a transform instruction applied to a document and a stylesheet. The consequence of this definition is that if a browser sends a request to the web server for the page named books, the document named "books" will be styled with the stylesheet named "books", resulting in an HTML page being returned to the browser.
Documents are defined with a content element. In the books example above, we see a px:dynamicContent element with a className attribute, associating the document "books" with the Java class sample.books.BookCatalog.
public class BookCatalog implements SelectHandler {
public void doRequest(PageContext context, Book parameters,
ContentWriter contentWriter) throws PresentingXMLException {
// Implementation
}
public long getLastModified(RuntimeContext context, Book key,
long timestamp, long elapsed) {
// Indicate changed if older than 10 seconds
return elapsed > 10000 ? timestamp : timestamp + elapsed;
}
}
The consequence of this definition is that when the document named "books" is accessed,
the doRequest method of the BookCatalog object is called.
The Presenting XML framework
is responsible for mapping request parameters to properties
declared in the Book interface; the
BookCatalog object is responsible for feeding start/end elements to the
SAX 2 ContentHandler.
Note that the doRequest method defined above takes a user defined interface Book as its second argument,
public interface Book {
public String getCategory();
}
The Presenting XML framework creates a proxy class that implements this interface at runtime.
If the HTTP request has the parameter category, the value of that parameter may be obtained
with the getCategory() method. The method signatures on the user defined parameters interface
need to follow the standard naming conventions for beans.
Stylesheets are defined with the style element. In the books example above, we see a px:style element with an href attribute, associating it with the relative url "html/books/books.xsl". By default this relative url is resolved relative to the location of the resources script. The base may be overriden with an xml:base attribute.
There are three kinds of elements that may appear in a resources script:
As the resources script becomes larger, it becomes desirable to reorganize it, splitting off document and style elements into separate files, in separate directories. For example, we may wish to have the directory tree:
pages - Directory containing the books pages.xml file.
documents - Directory containing the documents.xml file.
styles - Directory containing the styles.xml file, with subdirectories containing the actual stylesheets.
Example 3.2. The Reorganized Books Resources Script
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
xmlns:myapp="http://www.presentingxml.com/myapp"
ns="http://www.presentingxml.com/myapp">
<px:include href="../documents/documents.xml"/>
<px:include href="../styles/styles.xml"/>
<px:app>
<px:mapRequest>
<px:matchRequestURI match="/bookstore/pages/(.+)">$1</px:matchRequestURI>
</px:mapRequest>
</px:app>
<px:page name="books">
<px:parameter ns="" name="category"/>
<px:show>
<px:transform>
<px:content ref="myapp:books"/>
<px:style ref="myapp:books"/>
</px:transform>
</px:show>
</px:page>
</px:resources>
A pipeline body defines the sequence of steps applied to content to transform it into an XML stream for the serializer. A pipeline starts with content, passes it through a number of stages where it gets filtered and transformed, and finally hands it off to a serializer.
The simplest possible pipeline is a single px:content instruction. Such a pipeline simply passes the content "as is" to the serializer.
Consider the following pipeline body.
<px:transform>
<px:transform>
<px:systemContent href="documents/mixed-up.xml"/>
<px:saxFilter className="PreFilter"/>
</px:transform>
<px:style href="styles/filter.xsl"/>
<px:saxFilter className="PostFilter"/>
</px:transform>
This pipeline body may be thought of as a sequential process that executes from right to left. The inner transform is executed first. Here, the content mixed-up.xml is passed through the SAX filter PreFilter, and then streamed to the outer transform. In the outer transform, the result tree is first transformed with the XSLT stylesheet filter.xsl, and then passed through the SAX filter PostFilter, finally making its way to the serializer.
A pipeline body may have any number of nested transform stages. The innermost transform stage must contain a content instruction. Within a transform stage, there may be any number of filters and XSLT transformations that are executed in document order.
A filter performs processing on the XML tags at a lower stage before passing them on to a higher stage.
Presenting XML supports a rich variety of ways for selecting a pipeline body at runtime. Test expressions may be used to pick one of a number of candidate pipeline bodies based on the request parameters. The example below shows a page that is styled differently depending on whether the HTTP request has a parameter named "category."
Example 3.3. The Books Resources Script with Choices
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
xmlns:myapp="http://www.presentingxml.com/myapp"
ns="http://www.presentingxml.com/myapp">
<px:include href="../documents/documents.xml"/>
<px:include href="../styles/styles.xml"/>
<px:app>
<px:mapRequest>
<px:matchRequestURI match="/bookstore/pages/(.+)">$1</px:matchRequestURI>
</px:mapRequest>
</px:app>
<px:page name="books">
<px:parameter ns="" name="category"/>
<px:show>
<px:choose>
<px:when test="$category">
<!-- request has parameter category -->
<px:transform>
<px:style ref="myapp:books"/>
<px:content ref="myapp:books"/>
</px:transform>
</px:when>
<px:otherwise>
<!-- request does not have parameter category -->
<px:transform>
<px:style ref="myapp:welcome"/>
<px:content ref="myapp:request"/>
</px:transform>
</px:otherwise>
</px:choose>
</px:show>
</px:page>
</px:resources>
The syntax for a test expression is a small subset of the syntax for an XPath expression, including the parts that make sense for testing parameter values.
Examples of test expressions are shown below.
A serializer takes the output of a transformer - an XML or HTML tree - and serializes it to a byte stream before sending it back to the client device. The default serializer simply transforms the tree to text and sends that back as a byte stream.
The example below illustrates the use of a serializer to produce a pdf document:
Example 3.4. A Serializer to Produce PDF
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
xmlns:myapp="http://www.presentingxml.com/myapp"
ns="http://www.presentingxml.com/myapp">
<px:app>
<px:mapRequest>
<px:matchRequestURI match="/bookstore/pages/(.+)">$1</px:matchRequestURI>
</px:mapRequest>
</px:app>
<px:page name="pulp">
<px:clientOptions caching="yes"/>
<px:cachingOptions caching="yes" revalidate="synch"/>
<px:show>
<px:fopSerializer/>
<px:transform>
<px:style ref="myapp:novel-fo"/>
<px:content ref="myapp:pulp"/>
</px:transform>
</px:show>
</px:page>
<px:systemContent name="pulp" href="books/pulp.xml"/>
<px:style name="novel-fo" href="fo/books/novel.xsl"/>
</px:resources>
A serializer is defined with the serializer element. The example above uses the apache fop serializer.
The example below shows the "update-cart" page which updates a shopping cart in a Java UpdateCart object, adding a new book title, and then performs a client-side redirect to the "books" page. The URI of the "books" page is evaluated as an XPATH expression that can refer to any XML content generated in the pipeline that appears in its content, or to any parameters passed to the page.
<px:page name="update-cart">
<px:parameter ns="" name="category"/>
<px:parameter ns="" name="bookId"/>
<px:parameter ns="" name="title"/>
<px:show>
<px:clientRedirect select="concat('/bookstore/pages/books?category=',$category)">
<px:dynamicContent className="samples.books.UpdateCart"/>
</px:clientRedirect>
</px:show>
</px:page>
Presenting XML uses the <xsl:output> element in the XSLT stylesheet to obtain information about the MIME type that the stylesheet produces. It is therefore important that the media-type attribute of the <xsl:output> element is assigned a value, for example "text/html" for HTML stylesheets and "text/vnd.wap.wml" for WML stylesheets.
The figure below shows the px:devices section in the system configuration file. It defines a number of known devices and the MIME-types they accept. It also defines maps from the HTTP User-Agent to the device. If the device can be identified, Presenting XML will use that information first. If the device cannot be identified, Presenting XML will use the HTTP accept header.
Figure 3.1. Device Configuration
<px:devices>
<!-- Define devices and accepted MIME types -->
<px:device name="explorer"
accept="text/html,application/pdf"/>
<px:device name="pocketexplorer"/>
<px:device name="handweb"/>
<px:device name="avantgo"/>
<px:device name="imode"/>
<px:device name="opera"/>
<px:device name="lynx"/>
<px:device name="java"/>
<px:device name="wap"
accept="text/vnd.wap.wml"/>
<px:device name="mozilla5"
accept="text/html"/>
<px:device name="netscape"
accept="text/html,application/pdf"/>
<!--
Map a pattern in the User-Agent to a device name.
A pattern may contain unix wildcards.
-->
<px:deviceMap search="MSIE" device="explorer"/>
<px:deviceMap search="MSPIE" device="pocketexplorer"/>
<px:deviceMap search="HandHTTP" device="handweb"/>
<px:deviceMap search="AvantGo" device="avantgo"/>
<px:deviceMap search="DoCoMo" device="imode"/>
<px:deviceMap search="Opera" device="opera"/>
<px:deviceMap search="Lynx" device="lynx"/>
<px:deviceMap search="Java" device="java"/>
<px:deviceMap search="(Nokia)|(UP)|(Wapalizer)" device="wap"/>
<px:deviceMap search="(Mozilla/5)|(Netscape6/)" device="mozilla5"/>
<px:deviceMap search="Mozilla" device="netscape"/>
</px:devices>
Note that the search attribute appearing in the px:deviceMap element can take regular expressions.
The following example shows how the same request URI may be mapped into different pages depending on the device and on the mime types that the device accepts.
Example 3.5. Device Configuration
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
xmlns:myapp="http://www.presentingxml.com/myapp"
ns="http://www.presentingxml.com/myapp">
<px:include href="../styles/styles.xml"/>
<px:include href="../documents/documents.xml"/>
<px:app>
<px:mapRequest>
<px:matchDevice device="explorer">
<px:matchRequestURI match="/bookstore/pages/(.+)">$1/explorer</px:matchRequestURI>
</px:matchDevice>
<px:matchDevice accept="text/html">
<px:matchRequestURI match="/bookstore/pages/(.+)">$1/html</px:matchRequestURI>
</px:matchDevice>
<px:matchDevice accept="text/vnd.wap.wml">
<px:matchRequestURI match="/bookstore/pages/(.+)">$1/wml</px:matchRequestURI>
</px:matchDevice>
</px:mapRequest>
</px:app>
<px:page name ="books/wml">
<px:parameter ns="" name="category"/>
<px:show>
<px:transform>
<px:style ref="myapp:books/wml"/>
<px:content ref="myapp:books"/>
</px:transform>
</px:show>
</px:page>
<px:page name ="books/html">
<px:parameter ns="" name="category"/>
<px:show>
<px:transform>
<px:style ref="myapp:books/html"/>
<px:content ref="myapp:books"/>
</px:transform>
</px:show>
</px:page>
</px:resources>
Suppose in this example we receive the request URI "/bookstore/pages/books".
If the sending device is recognized to be "explorer" according to the rules defined in the presentingxml.xml configuration file, the first request matcher attempts to resolve the request to a page with namespace "http://www.presentingxml.com/myapp" and local name "books/explorer". This fails, since there is no such page, The second request matcher then checks that the device accepts the mine type "text/html" (which it does) and also that there is a page having namespace "http://www.presentingxml.com/myapp" and local name "books/html", which there is.
If the sending device is unrecognized, and the HTTP accept header indicates that the device does not accept mime type "text/html", but does accept mime type "text/vnd.wap.wml", then the third request matcher will attempt to find a page having namespace "http://www.presentingxml.com/myapp" and local name "books/wml".
Table of Contents
The config subdirectory is found immediately beneath the document root. The configuration file presentingxml.xml is in the config folder. It contains a number of sections:
The transformer section species the jaxp transformer factory that is used. A jaxp transformer factory is any java class that implements the javax.xml.transform.TransformerFactory interface.
The device-map section defines a mapping of device descriptions (e.g. "MSIE") to device names (e.g. "explorer"). This roughly follows Cocoon's approach. Regular expressions are allowed for device descriptions.
The Presenting XML framework supports caching document, stylesheet and page resources. Whether or not a resource can be cached is configurable, and the way in which a resource becomes invalidated - asynchronously or synchronously - is also configurable.
For documents, the framework supports caching both
XML content read from system files, and
XML content generated dynamically through a SAX 2 ContentHandler.
Documents are optionally cached, depending on the settings in the px:cachingOptions element in scope when the documents are defined. Cached representations are built from the stream of SAX events when the document is initially loaded.
Stylesheets are cached as compiled Templates objects.
Pages are cached as text markup.
Two major issues in caching are object identity and cache entry invalidation:
How do we know that two requests are for the same cached node, particularly when the node has been generated dynamically?
How can we tell when an entry in the cache needs to be reloaded?
Caching has the result of improving performance but using up valuable memory. The final section describes the role of the cache manager in managing the memory resource, in ensuring that the cached nodes will not grow to the point of overwhelming the available memory.
A request for dynamic XML content comes with a document name and some parameters. The document name determines the RequestHandler used to handle the request. Different requests, of course, could come with different parameter values and so result in different nodes.
The notion of keys is used to assign an identity to what a RequestHandler writes into a ContentHandler. Keys are set up for dynamic content in the documents.xml file. A key consists of the document name and an ordered sequence of attributes that taken together assigns an identity to the XML content.
When a request for dynamic XML content comes in, the parameters are matched up by name with the attributes that make up the key. The matched parameter values are saved in the key object. These key objects are used to identify the dynamic resource.
If a request for dynamic content originates through a call to the document function in an XSLT stylesheet, an additional parameter may be added to the current parameter set by appending a ? to the document URL followed by a name/value pair.
Suppose, for example, that the key for some dynamic content is defined by the following entry in the documents.xml file:
<px:systemContent name="categories" className="books.CategoryHandler">
<px:key>
<px:field name="category"/>
</px:key>
</px:systemContent>
Now, suppose that the following document function call occurs in an XSLT stylesheet:
<xsl:value-of select="document('categories?category=S',/)//category/@desc" />
Then, the URI resolver that resolves the request for the url categories?category=S
will add a parameter named category to the current parameter set that has the value "S".
Table of Contents
There are three kinds of elements that may appear in a resources script:
A property element may appear anywhere in a resources script. The following elements fall into this category.
The example below shows two named resources (the px:content elements), and two properties (the px:cachingOptions elements.)
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML">
<px:cachingOptions caching="no"/>
<px:systemContent name="books" href="documents/books.xml"/>
<px:systemContent name="authors" href="documents/books.xml">
<px:cachingOptions caching="yes"/>
</px:systemContent>
</px:resources>
In this example, the default rule is set so that there is no caching of content. In particular, the books document is not cached. The authors document, on the other hand, is cached.
Any element, in addition to the attributes listed in the reference entries, may have the following attributes.
| Name | Mand. | Value | Description |
|---|---|---|---|
| ns | no | URI | The namespace of the resource. Defaults to the namespace in scope. |
Many of the elements listed below permit a pipeline body in their content. A pipeline body defines the sequence of steps applied to content to transform it into an XML stream for the serializer.
A pipeline body may contain one of the following elements:
Table of Contents
This reference provides an alphabetical list of the core elements that may appear in a resources script.
Below is a list of the core elements in alphabetical order.
Example 9.1. Example of px:app element.
<px:app name="bookstore">
<px:validateRequest><px:page ref="myapp:gatekeeper"/></px:validateRequest>
<px:mapRequest>
<px:matchDevice accept="text/html">
<px:matchRequestURI match="/bookstore/pages/(.+)">$1/html</px:matchRequestURI>
</px:matchDevice>
<px:matchDevice accept="application/vnd.wap.wmlc">
<px:matchRequestURI match="/bookstore/pages/(.+)">$1/wml</px:matchRequestURI>
</px:matchDevice>
<px:matchRequestURI match="/bookstore/pages/(.+).pdf">$1/pdf</px:matchRequestURI>
</px:mapRequest>
</px:app>
<px:page name="gatekeeper">
<px:show>
<px:localRedirect select="$px:requestURI">
<px:dynamicContent className="samples.common.BookstoreGatekeeper"/>
</px:localRedirect>
</px:show>
</px:page>
| Name | Mand. | Value | Description |
|---|---|---|---|
| caching | yes | "yes" or "no" | Indicates whether server side caching is in effect for the pages, documents and styles in the current scope. |
| revalidate | no | string | A list of revalidation codes with possible values "synch" or "asynch" (or both), or "full" or "none". |
| Name | Mand. | Value | Description |
|---|---|---|---|
| caching | yes | "yes" or "no" | Indicates client side caching is in effect for the pages in the current scope. |
Optionally, a pipeline body.
Performs a client-side redirect to the URI that results from evaluating the xpath expression in the select attribute.
A client-side redirect sends a URI back to the client, in the expectation that the client will resubmit the request with the new URI. If you want to have state sent with the new URI, you have two options:
Example 9.2. Example of a client-side redirect.
This example shows the "update-cart" page which updates a shopping cart in a Java UpdateCart object, adding a new book title, and then performs a client-side redirect to the "books" page. The URI of the "books" page is evaluated as an XPATH expression that can refer to any XML content generated in the pipeline that appears in its content, or to any parameters passed to the page.
<px:page name="update-cart">
<px:parameter ns="" name="category"/>
<px:parameter ns="" name="bookId"/>
<px:parameter ns="" name="title"/>
<px:show>
<px:clientRedirect select="concat('/bookstore/pages/books?category=',$category)">
<px:dynamicContent className="samples.books.UpdateCart"/>
</px:clientRedirect>
</px:show>
</px:page>
| Name | Mand. | Value | Description |
|---|---|---|---|
| ref | no | QName | A reference to a defined top-level px:content resource. |
Example 9.3. Using a px:content instruction to refer to dynamic content.
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
ns="http://www.presentingxml.com/myapp">
<px:page name="books">
<px:parameter ns="" name="category"/>
<px:show>
<px:transform>
<px:style ref="myapp:books"/>
<px:content ref="myapp:books"/>
</px:transform>
</px:show>
</px:page>
<px:dynamicContent name="books" className="samples.books.BookCatalog">
<px:key>
<px:field name="category"/>
</px:key>
</px:dynamicContent>
</px:resources>
| Name | Mand. | Value | Description |
|---|---|---|---|
| name | no | NCName | The name of the serializer. |
| className | yes | Java Class | The name of a java class that implements com.presentingxml.components.serializer.Serializer. |
Example 9.4. Defining an Apache fop serializer.
<px:serializer name="fop-serializer"
className="com.presentingxml.components.serializer.fop.FOPSerializer">
</px:serializer>
Example 9.5. Serializing an xsl-fo XML tree with an Apache fop serializer to produce pdf.
<px:page name="pulp">
<px:show>
<px:serializer ref="myapp:fop-serializer"/>
<px:transform>
<px:style ref="myapp:novel-fo"/>
<px:content ref="myapp:pulp"/>
</px:transform>
</px:show>
</px:page>
One or more action elements from the following list.
Example 9.6. Apply a stylesheet to a SOAP fault raised in the book-order document handler.
<px:page name="post-book-order">
<px:parameter ns="" name="name"/>
<px:parameter ns="" name="addressLine1"/>
<px:parameter ns="" name="addressLine2"/>
<px:parameter ns="" name="city"/>
<px:parameter ns="" name="state"/>
<px:parameter ns="" name="zip"/>
<px:parameter ns="" name="country"/>
<px:parameter ns="" name="phoneNumber"/>
<px:show>
<px:transform>
<px:style ref="myapp:confirm-order"/>
<px:content ref="myapp:book-order"/>
</px:transform>
<px:doFault>
<px:transform>
<px:style ref="myapp:book-order"/>
</px:transform>
</px:doFault>
</px:show>
</px:page>
| Name | Mand. | Value | Description |
|---|---|---|---|
| name | no | NCName | The name of the content resource. |
| className | no | Java Class | The name of a java class that implements com.presentingxml.components.content.dynamic.SelectHandler or com.presentingxml.components.content.dynamic.UpdateHandler. |
Example 9.7. Defining a document with reference to a java class that simulates a SAX parser.
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML"
ns="http://www.presentingxml.com/myapp">
<px:dynamicContent name="books" className="samples.books.BookCatalog">
<px:key>
<px:field name="category"/>
</px:key>
</px:dynamicContent>
</px:resources>
| Name | Mand. | Value | Description |
|---|---|---|---|
| name | no | Name | Reference to the name of a parameter. On a request, the field value will be set to that parameter value. |
See px:dynamicContent.
| ref | no | QName | A reference to a defined top-level filter. |
Optionally, a pipeline body.
Allows a resources script to pass control locally to another page.
A local redirect computes a new request URI in its select attribute, transfers the request back to the app, skips the validation steps defined in the px:validateRequest element (since its already inside the gate), and attempts to match the new request URI with a page using the rules defined in the px:mapRequest element.
Example 9.8. Example of a local redirect to the original request URI.
<px:page name="bookstore-gatekeeper">
<px:show>
<px:localRedirect select="$px:requestURI">
<px:dynamicContent className="samples.common.BookstoreGatekeeper"/>
</px:localRedirect>
</px:show>
</px:page>
Note that the variable px:requestURI appearing in the select attribute of the local redirect is a built-in variable that holds the original request URI. This local redirect transfers the request back to the app, skips the validation steps defined in the px:validateRequest element (since its already inside the gate), and attempts to match the request URI with a page using the rules defined in the px:mapRequest element.
| Name | Mand. | Value | Description |
|---|---|---|---|
| ref | no | QName | A reference to a defined top-level request matcher. |
One or more elements derived from px:mapRequest, including px:matchDevice and px:matchRequestURI elements.
Example 9.9. Example of px:mapRequest element.
<px:app name="bookstore">
<px:mapRequest>
<px:matchDevice accept="text/html">
<px:matchRequestURI match="/bookstore/pages/(.+)">$1/html</px:matchRequestURI>
</px:matchDevice>
<px:matchDevice accept="application/vnd.wap.wmlc">
<px:matchRequestURI match="/bookstore/pages/(.+)">$1/wml</px:matchRequestURI>
</px:matchDevice>
<px:matchRequestURI match="/bookstore/pages/(.+).pdf">$1/pdf</px:matchRequestURI>
</px:mapRequest>
</px:app>
| Name | Mand. | Value | Description |
|---|---|---|---|
| name | no | NCName | The name of the px:matchRequestURI instruction. |
| device | no | String | A comma separated list of device names. |
| accept | no | String | A comma separated list of mime types. |
Text.
Optionally, one or more px:mapRequest type elements, including px:matchDevice and px:matchRequestURI elements.
Example 9.10. Example of matching on a device and request URI.
<px:matchDevice accept="text/vnd.wap.wml">
<px:matchRequestURI match="/bookstore/pages/(.+)">$1/wml</px:matchRequestURI>
</px:matchDevice>
| Name | Mand. | Value | Description |
|---|---|---|---|
| name | no | NCName | The name of the px:matchRequestURI instruction. |
| match | yes | Regex | A perl regular expression that matches on the rquest URI. |
Text that may include regular expression wildcard characters.
Optionally, one or more px:mapRequest type elements, including px:matchDevice and px:matchRequestURI elements.
Example 9.11. Example of matching on a request URI.
<px:matchRequestURI match="/bookstore/pages/(.+)">html/$1</px:matchRequestURI>
Optionally, one or more px:parameter elements.
One or more action elements from the following list.
Example 9.12. Books page.
<px:page name="books">
<px:parameter ns="" name="category"/>
<px:show>
<px:transform>
<px:style ref="myapp:books"/>
<px:content ref="myapp:books"/>
</px:transform>
</px:show>
</px:page>
Optionally, text. If the content contains text, it is evaluated as the value of the parameter.
Used to define the parameters of a px:page element.
A document root element, which in turn may contain other elements and a px:recordMapping element.
| Name | Mand. | Value | Description |
|---|---|---|---|
| ns | no | URI | The default namespace for the pages, documents, styles and serializers defined in this resources script. |
The list of elements that may be defined with a qualified name at the top level of the resources script includes all the elements that are defined in the px:instructions section of the presentingxml.xml configuration file. These include
| Name | Mand. | Value | Description |
|---|---|---|---|
| name | no | NCName | The name of the filter. |
| className | yes | Java Class | The name of a java class that implements org.xml.sax.XMLFilter. |
Example 9.13. Constructing a SAX pipeline.
The example below shows a resources script that implements a SAX pipeline. PreFilter and PostFilter are the names of Java classes that implement the org.xml.sax.XMLFilter interface.
<px:resources xmlns:px="http://www.presentingxml.com/PresentingXML">
<px:page name="pipeline">
<px:show>
<px:transform>
<px:systemContent href="documents/mixed-up.xml"/>
<px:saxFilter className="PreFilter"/>
<px:style href="styles/filter.xsl"/>
<px:saxFilter className="PostFilter"/>
</px:transform>
</px:show>
</px:page>
</px:resources>
| Name | Mand. | Value | Description |
|---|---|---|---|
| ref | no | QName | A reference to a defined top-level serializer. |