XMLPipe User Guide

Michael Pediaditakis

Created: 2002-04-06 Modified: 2002-04-08


Contents


Chapter 1: Introduction

XMLPipe is an proof-of-concept implementation of the XMLPipe model. It provides an alternative way to orchestrate XML document transformations focused on processing heterogenous documents, [N: 1] using indpendently developed XML languages [N: 2] to produce final form XML representations adequate for a variety of application profiles.

notes[
[N: 1] Hererogeneous documents are documents that combine more than one XML languages. For instance, an XHTML document that also contains XLink attributes is a heterogenous document.
[N: 2] Independetly developes XML languages are the ones where their syntax and/or their handlers are not designed specifically to interoperate with each other.
]

XMLPipe achieves its goals by providing the follwinf set of features:

The purpose of this user guide is to provide a brief overview to the whole concept behing XMLPipe and explain the usage of the XMLPipe implementation. Firstly, in Chapter 2 we provide the absolutely necessary information on the XMLPipe model which is important for getting the most out of the implementation. We then provide some hands-on examples in Chapter 3 with simple and more complex usage examples. We proceed with the basic guidelines on designing XML languages and their handlers in a way that would allow better content interoperation and that would make their processing using XMLPipe easier. Finally, we provide the basic information needed to build custom transformers in Chapter 5. There are reference appendices for the syntax of the configuration filem the command line usage and the transformers that come with XMLPipe.


Chapter 2: XML Pipe model overview

XMLPipe was developed as a means to tranform XML documents that consist of a number of XML languages. The final representation should be the most adequate for a specified application profile. The basic concepts of the XMLPipe model are described below. We do not go into much depth while describing the concept here since this is only a brief overview that explains the core concepts that will be used subsequently. Some of the description might not make much sense here, but they will become more clear during the subsequent chapters.

2.1 Handlers associated with namespaces

Typical transoformation approaches are document oriented. For inctance, the typical way to associate a stylesheet with a document is by invluding an XSL processin instruction in the document. Moreover, typical pipelining architectures either associate documents (or document templates) to processing pipelines or leave the user to make the association. Such an approach is far from adequate since the document author or the document user has to be aware of the document processing required. Moreover, the document transformer blindly applies a sequence of transformation without knowing they processing that is needed for the individual document structures.

In XMLPipe, the handlers are associated with unique URIs that represent language constructs and consist of the language namespace and the name of individual constructs. For instance, a handler for an XHTML table would be associated with a URI such as "http://www.w3.org/1999/xhtml:table". This type of association allow XMLPipe apply the appropriate handler for a construct whenever it is encountered in an XML document.

2.2 Transformation pipelines

The processing of a construct, even in our case which is more fine grained than complete documents, might require several transformation steps. Multiple steps can be required in a number of different cases such as:

XMLPipe allows easy construction of three types of transformation pipelines: sequence, selection and dynamic pipelines. Sequence pipeline allows to define a list of transformation steps which are applied in sequence (each processing the output of the previous one). Selection pipeline allows the selection of different processing according to the application profile or other context information. Finally, the dynamic pipeline allows a tranformation to be parametrized by the output of another transformation (e.g. an XSL-T transformation where the stylesheet is the result of a transformation). All of these pipelines can be nested into eachother allowing fairly complex processing definitions.

2.3 Context, statements and expressions

The context is a very important concept in XMLPipe and is used at several different places to provide a device neutral way of communicating information. Generally, context information is composed out of a set of statements where each statements is defined as a pair of a URI and a corresponding value. Each of these URIs specifies a term which must genrally be declared an has a well defined meaning.

The first occurence of a context in XMLPipe is the definition of an application profile which defines the capablities of the platform that will use the resulting XML document. An example of a profile is:

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/XML/1998/namespace</item>
    </statm>
  </profile>
In this example there are two statements, one for the term xml.asscoder.gr/XMLPipe/Terms:deviceType and one for the term xml.asscoder.gr/XMLPipe/Terms:supported. Each term is declared to hace a specific type which in this example is a string for the first one while a set of strinfs for the latter.

Another important occurence of the context concept is the Transformation context. Each transformation (e.g. an XSLT transformation) has access to context information which might be usefull for the respectice process (e.g. device capabilities, values set by the user etc). The context transformation is composed out of a set of other contexes:

We allow all these different levels of context information so that the information can be added at different levels of abstraction (and scope). The precendence gows from low to high and therefore if there are values defined for the same term in both the transformation specific context and the application profile, only the transformation specific value will be visible by a transformation.

Specifically, the application profile simply includes the statements that are specified as part of the application profile and must at least contain the two statements of the previous example. The Dynamic context is internally computed context which might include inoformation such as the base URI of the currently processed node. The user define context are statements that the user define on a specific XMLPipe invocation, and can be used to customize a specific XMLPipe executin section. Language context is essentially a part of the rest of the contxt definitions and consists of values for terms that have the same namespace with the handled XML languages. If a handler sets the values for terms of the same namespace which is associated with the handler, then this information of propagated to all the handlers of the same namespace for the generated sub-tree. Consequently, the language context allows hanlders that handle the same languge to have a minimum amount of interoperation. Finally, transformer specific context is the context that can be defined for a specific transformer (e.g. a specific invocation of an XSL-T transformer).

The context information can be used in any conceivable manner since terms can be easily defined and used at several different places in the transformers, the pipeline construction etc. There is however a set of predefined terms that have special associated semantics (e.g. the "supported" term which is used to define which XML languages are supported by an application profile).

XMLPipe constraints are essentialy sets of expressions for a set of terms. In the same way that a statement defines the value of a term, an expression defines a constraint for a term. Such expressions can be grouped together in "constraints" in a similar way as statements are group to contexes. Two constraints examples are:

    <constraints>
      <expr ns="www.example.org/xmlpipe/terms"
            name="deviceType">
        <or>
           <equals>
              <termVal/>
              <val>mobile</val>
           </equals>
           <equals>
              <termVal/>
              <val>pda</val>
           </equals>
        </or>
      </expr>
    </constraints>           
and
<expr ns="uri:ukc.ac.uk/~mp49/xml/terms"
      name="screenWidth">
   <div>
       <sub><termVal/><val>400</val></sub>
       <val>624</val>
   </div>
</expr>
The <termVal> element is substituted with the value for the respective term. Each of the expressions evaluates to a value in [0, 1]. Constraints are used when a decision has to be made on which handler to use for a specific handled construct or when a selection pipeline is used. The sum of the values that expressions of a "constraints" group evaluare to becomes the measure of how adequate a specific decision is for the respective context. The evaluation of such constraints is what allows XMLPipe to provide the best final representation for a variety of devices.

The combination of all the ways to define the context and the places where constraints can be used allow a poweful and generic (yet complex) way to provide semi-automated processing of XML content for different devices.

2.4 Multiple documents

A usual problem during XML handling is content which is transformer to multiple documents. The core XSLT 1.0 does not allow a way to define multiple outputs (even though there are vendor specific extensions that allow it). Moreover, when documents are separated, especially if this happens in the middle of the execution of a pipeline, they require specialized handling (e.g. perform the rest of the pipeline processing for each of the generated documents and then tranform any reamaining handled constructs independently

The notion of multiple output documents is well integrated into the XMLPipe processing where the "typical" processing is performed automatically. When a transformer creates additional output documents, XMLPipe performs all the remaining pipeline processing and then handles them as independent documents. The transformer can only specify the content and a realive URI of the document and XMLPipe performs all the reamaining processing and stores the document in the respective document.

Multiple documents can also easily be genereted by generic tranformers such as XSL-T by using the special purpose languages that come with XMLPipe. [CHECK:This is not implemented yet]

2.5 The overal processing

Finally, before proceeding to the XMLPipe examples, we will describe how all the above are combined and used in order to process an XML document.

There is a configration file which contains terms declarations, application profiles definitions, and handlers. Handlers are essentially associations between handled constructs and processing pipelines. The user specifies the target application profile and a source XML document.

There are two processing steps: pre processing and normal processing. Their difference is that during preprocessing only handlers which are declared as "prioritized" are used. During the second processing step, all the handlers are used. This separation is needed for future validation extensions where document validation will be peformed after the pre processing step.

For each of the steps, XMLPipe traverses the document tree in a depth first, post order manner (so that innermost elements are checked before their ancestors). When a handled construct is located, any associated constraints are checked for conformance with the current application profile (and context in general). If there are more than one alternatives, the one that scores higher (in terms of the aforementioned descision measure) is selected. The transformation pipeline is applied to the document sub-tree rooted at the node the corresponds to the handled construct. When the pipeline processing is finished, the new modified subtree is recheked for any new handled constructs and then the rest of the DOM tree is traversed.

By the end of this processing, all the namespace prefixed constructs of the resulting tree should be of namespaces which are included to the "supported" term value for the specified application profile. Otherwise the document cannot be handled.

At the end of the execution the resulting DOM tree(s) is serialized or passed to the final handling application (which is associated with the application profile).

We have to point out that this is only a summary of the actuall processing which is much more complex and many more factors are taken into account in order to accomplish each the aforemention steps. However, we want to keep the description reasonably simple at this point.


Chapter 3: Usage tutorial

Having bloated every conceivable reader with the boring theory details, we will proceed to a hands-on tutorial on the use of the XMLPipe tool, the configuration file syntax and the general concepts behing XMLPipe processing. We will begin with (very) simple examples and icrease the complexity as we move on.

For the ones who cannot be bothered to type in the examples, they are all provided under the samples/tutorial distribution directory. Moreover, a still unresolved XMLPipe issue on the generation of a document type declaration makes some of the example outputs unrenderable in some browsers. Internet Examplorer needs the declaration and does not provide a visual representation. Mozilla seems to handle everything fine.

3.1 The simplest possible XMLPipe use

The most minimal XMLPipe application would be one that does nothing (that is, to simply copy the input). The only thing needed to be declared is an application profile since we always have to specify the name of an application profile during XMLPipe invocation. No tranformers or transformation pipelines have to be declared.

A minimal configuration file is:

<?xml version="1.0"?>

<config xmlns="xml.asscoder.gr/XMLPipe/Representation/Internal"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="xml.asscoder.gr/XMLPipe/Representation/Internal ../../../schemas/XMLPipeConfig.xsd"
        name="Do nothing examples">

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
    </statm>
  </profile>


</config>

All the configuration elements should use the XMLPipe namespace which is xml.asscoder.gr/XMLPipe/Representation/Internal. The name attribute is used for a sort description of the purpose of the configuration file. The XMLSchema information is usefull for validation of the configuration file and is optional. The only child element of the config tag is the profile element which defines an application profile. The syntax of an application profile simple: there is a name attribute which is an identifier and is used to address the profile and a set of statements that define the value of the profile.

Terms are typically declared before their use. However, in this case this is not required since we only use the two predefined terms device and supported (a list of the predefined terms can be found in Table A.1). Specifically, these two terms have to be used for every applicarion profile. The device term defines the type of the target device and takes values such as: desktop, mobile, printer etc. The supported is used to provide the list of the namespaces of the supported XML languages. This allows XMLPipe to decide on how to transform a document according to the technologies that are supported for an application profile. In this case we define an application profile named desktop, which represents a desktop handler and supports XHTML and XML Schemas.

If we process an XML file which does not use any namespaces such as:

<?xml version="1.0"?>
<doc>
   <aTag>This document does not use namespaces</aTag>
</doc>

using the XMLPipe command line tool as follows:
java XMLPipeCmd -c config.xml desktop noNamespace.xml
the result is a copy of the file. XMLPipe does simply copies nodes with no namespace declarations. The invocation of the XMLPipe tool specifies the configuration file (config.xml), the application profile to use (desktop) and the XML file to be processed. By default the main document is output to the console and any additional files to the current directory. This behaviour can be changed using the -o option to specify an output file. If there are secondary documents (not in this case) they are placed at the same directory as the specificed output file. For instance, the command:
java XMLPipeCmd -c config.xml -o noNamespace.out.xml desktop noNamespace.xml
will produce a copy of the input document to the noNamespace.out.xml file.

If we use an alternative source file, such as:

<?xml version="1.0"?>
<doc xmlns="uri:aNamespace">
  This cannot be handled because the namespace is not known.
</doc>
               

XMLPipe will start complaining as follows:
fileLocation: [HANDLING ERROR]Cannot handle aNamespace:doc and the 
specified application profile does not support the associated namespace
. What has happened here is that the document has an element that belongs to a namespace which is not supported by the application profile. If there is not a handler that can tranform this document, the resulting document tree will contain constructs that are not handled by the specified application profile. Therefore, XMLPipe infers that the document cannot be handled.

The exact opposite happens if we have constructs of a handled namespace. For instance, our example application profile is declarted to support xhtml, and therefore the following input:

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  This should be ok, even if this is not
  valid XHTML.
</html>
               

is handled (i.e. copied) without any erros since the profile supports the xhtml namespace. Still, if we include an element of an unhandled namespace, withing the handled content, XMLPipe will start complaining again. For instance, the following:
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  This should be ok, even if this is not
  valid XHTML
  <bizzareElement xmlns="uri:aNamespace"/>
</html>
               

produces exactly the same error message:
Cannot handle uri:aNamespace:bizzareElement and the specified 
application profile does not support the associated namespace.

The only way to handle such a document is to either provide a handler that transforms the "bizzareElement" to something recognized by the application profile (e.g. an xhtml tag in this case), or declare support of this content type in the application profile. Therefore, if we introduce a new application profile in the configuration file, which will become:

<?xml version="1.0"?>

<config xmlns="xml.asscoder.gr/XMLPipe/Representation/Internal"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="xml.asscoder.gr/XMLPipe/Representation/Internal ../../../schemas/XMLPipeConfig.xsd"
        name="Do nothing examples">

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
    </statm>
  </profile>

 <!-- An additional profile -->
  <profile name="desktop2">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
      <item>uri:aNamespace</item>
    </statm>
  </profile>


</config>

and the invoke XMLPipe for the new profile:
java XMLPipeCmd -c config.xml desktop2 unhandledCombination.xml
there will be no error messages.

3.2 Saying "Hello world" using XSLT

In the previous example we have described a minimal XMLPipe application which is of little use since it simply copies the source to the output. In this example we will use the built in XSLT transformer (which uses the Apache Xalan library) to modify the input document.

Since, in XMLPipe everything works using namespaces we will have to define a new "hello world" language with an associated namespace. For now we will assume a simple element <helloWorld> which should be tranformed some for of a "hello world" representation. [N: 1]

notes[
[N: 1] We will not define a schema for this document type, we consider it pretty basic!
]

We wil first define a simple stylesheet that creates a simple textual "hello world". The stylesheet is:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
		version = "1.0"
		xmlns:hello = "uri:example/hello">
  
  <xsl:template match="hello:helloWorld">
    <xsl:text>Hello world from XSL-T</xsl:text>
  </xsl:template>

</xsl:stylesheet>

Note the there is no "root" template and the stylesheet does not take into account any additional document content. After defining the stylesheet we have to inform XMLPipe about our new language and how to handle it. This is performed by creating a handler which calls the XSL-T transformer for the aforementioned stylesheet. The configuration file is:
<?xml version="1.0"?>

<config xmlns="xml.asscoder.gr/XMLPipe/Representation/Internal"
        name="Do nothing examples">

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
    </statm>
  </profile>

  <transformer name="helloTextTr"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="helloText.xsl"/>             

  <handler name="helloTextHandler"
	   ns="uri:example/hello"
           root="helloWorld">
    <pipe>
        <transform ref="helloTextTr"/>
    </pipe>
  </handler>

</config>

The application profile is the same as before. We have only added a transformer declaration and the handler. The transformer declaration consists of a transformer element which specified the name of the transformer, the class the performs the transformation and an (optional) parameter. For the XSLT transformer there is a predefined class, gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer and the parameter is the stylesheet to be applied. The handler, in this case, consists of the handled construct information and the transformation pipeline. The handled construct information is the namespace of the elements or attributes that we want to handle and their names. In this case the namespace is uri:example/hello and the element name is the helloWorld. The pipeline consists of a single transformation which is specified with the transform element which refers to the XSL-T transformer for our stylesheet. This handled definition causes XMLPipe to call apply the the associated stylesheet whenever an element called helloWorld of the namespace uri:example/hello is encountered.

Using all of the above, using a input document such as:

<?xml version="1.0"?>

<html xmlns:hello = "uri:example/hello"
      xmlns="http://www.w3.org/1999/xhtml">
  <head><title><hello:helloWorld/></title></head>
  <body>
     <h1><hello:helloWorld/></h1>
  </body>
</html>

and calling XMLPipe:
java XMLPipeCmd -c config.xml -o helloSimpleOut.xml desktop helloSimple.xml
the result would be (browse here)
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">
  <head><title>Hello world from XSL-T</title></head>
  <body>
     <h1>Hello world from XSL-T</h1>
  </body>
</html>

There might be some compilation warnings, which can be safely ignored at this point (-q option can be used to provide a quieter mode of execution).

We have to point out that stylesheets used with XMLPipe should not use templates that match the root of the document (e.g. <template match="/"> since this would only match the actual root of the tree. This is firstly not the desired behaviour since XMLPipe calls handlers for their specific subtree and additionaly, during XMLPipe processing, the actuall DOM tree might have been broken to a number of trees which are combined before serialisation. As far as transformers only access their assigned subtree this behaviour should be transparent to them.

The easy of use of XMLPipe becomes apparent in less trivial cases. For instance, assume that we also need a custom hello element that will greet whatever is its content. An important design issue for XMLPipe transformers is to generally copy any unrecognized content and not make assumptions on the nature of content. In our case, we cannot assume that the content of the helloCustom element will actually be a text node. It can be a text node, an XHTML tag, an image and any possible conceivable construct that can yield some form of greeting information. XMLPipe processing order ensures that the content of the helloCustom element will be in its final presentation form before the helloWorld transformer is called. Therefore, the safest action is to simply copy it next to our text. Therefore, the stylesheet would be:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
		version = "1.0"
		xmlns:hello = "uri:example/hello">
<xsl:strip-space elements="*"/>
  
  <xsl:template match="hello:helloCustom">
     <xsl:text>Hello </xsl:text>
     <xsl:copy-of select="node()"/>
     <xsl:text> from XSL-T</xsl:text>
  </xsl:template>

</xsl:stylesheet>

Another transformer and handler declaration has to be included to our configuration file to provide all the required information for our custom greeting tag (they are exactly the same except the names so we will not include them again).

XMLPipe allows easy integration of XML languages and when both handlers declarations are in place they can also be used in combination. So if we process the following document:

<?xml version="1.0"?>

<html xmlns:hello = "uri:example/hello"
      xmlns="http://www.w3.org/1999/xhtml">
  <head><title><hello:helloWorld/></title></head>
  <body>
     <p>We can say: <hello:helloWorld/></p>
     <p>We can also say: <hello:helloCustom>Mike</hello:helloCustom></p>
     <p>A more fancy greeting can be:
        <hello:helloCustom>
          <span style="color:red;font-size:300%">Mike</span>
        </hello:helloCustom>
     </p>
     <p>And we can nest constructs as well, providing
        double world greetings such as:<br/>
        <hello:helloCustom>
           <span style="color:blue"><hello:helloWorld/></span>
        </hello:helloCustom> 
    </p>
  </body>
</html>

we will get the following output (browse here):
 
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">
  <head><title>Hello world from XSL-T</title></head>
  <body>
     <p>We can say: Hello world from XSL-T</p>
     <p>We can also say: Hello Mike from XSL-T</p>
     <p>A more fancy greeting can be:
        Hello <span style="color:red;font-size:300%" xmlns="http://www.w3.org/1999/xhtml">Mike</span> from XSL-T
     </p>
     <p>And we can nest constructs as well, providing
        double world greetings such as:<br/>
        Hello <span style="color:blue" xmlns="http://www.w3.org/1999/xhtml">Hello world from XSL-T</span> from XSL-T 
    </p>
  </body>
</html>

Even if this example is simple it illustrates some important aspects behind the XMLPipe design. Firstly, the transformers simply handle only the information they are interested in and ignore everything else. If we tried to have a functionality similar to "helloCustom" without using XMLPipe we would have a number of problems. Firstly, it would have to check the whole document tree for any occurence of the element. This would not allow the use of the "copy-of" xsl construct and element types would have to be explicitly copied. Additionaly, in order to allow use of both the helloWorld and helloCustom handlers we would have to combine their stylesheets. This is not always an easy process and would require to know what languages are used in the document (while in this case we keep a configuration file with as much inofrmation as possible, and leave the descision on what to use to XMLPipe). Moreover, the two handlers could be remotely accessed or be in different technologies (e.g. one in XSL-T and one in Java) so that their combination would not be possible. Applying the transformers in sequence would be adequate in this case. However, what if e.g. the second in the sequence handler needed to generate elements processed by the first handler (and vice versa). XMLPipe handles this situations without any modification to the transformers (the stylesheets) in this case and without any static knowledge on the language constructs used inside a document.

3.3 Saying "Hello world" using Java

Building a transformer using Java requires little more than basic DOM manipulations. Each XMLPipe transformer has to extend the class gr.asscoder.xml.XMLPipe.transform.Transformer and only implement the three methods of the interface TransformerCustom of the same package. A simple transformer that is equivalent to the helloWorld handler is:

import  gr.asscoder.xml.XMLPipe.transform.*;
import  gr.asscoder.xml.XMLPipe.*;
import  gr.asscoder.xml.XMLPipe.terms.*;
import  gr.asscoder.xml.XMLPipe.parsing.DOMUtil;

import org.w3c.dom.*;

/** A simple transformer that handlers the
import tag of the "http://xml.asscoder.gr/XMLPipe/lang/textImport"
namespace. It only has an "href" tag which should point to 
a text file. The file is included as a singe text node.
*/


public class HelloTransformer extends Transformer {

    public static final String NAMESPACE = "uri:example/hello";
    public static final String ELEMENT_NAME = "helloWorld";

    public HelloTransformer()
    {
	super(false, false);
    }
    
    public boolean transformCustom(ComponentInterface ci, 
				   Node root, 
				   boolean isAttr,
				   TransformationContext cnt) 
	throws XMLPipeTransformException,
	       XMLPipeTransformTempException
	       
    {
	//Get the handled construct
	Node helloNode =  DOMUtil.getFirstEl(root);
	
	//Create the text node
	Document doc = root.getOwnerDocument();
	Text textNode = doc.createTextNode("Hello World from Java");
	
	//Replace the handled node with the text
	root.replaceChild(textNode, helloNode);

	return true;
    }

    public boolean transformCustom(ComponentInterface ci, 
				   Node root, 
				   boolean isAttr,
				   TransformationContext cnt,
				   Node par)
	throws XMLPipeTransformException,
	       XMLPipeTransformTempException
	       
	       
    {
	throw new XMLPipeTransformTempException(ErrorHandler.ERROR, 
            "Cannot call hello world with a parameter");
    }
}


The respective configuration will be simial to the simple example of the previous section and would be:
<?xml version="1.0"?>

<config xmlns="xml.asscoder.gr/XMLPipe/Representation/Internal"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="xml.asscoder.gr/XMLPipe/Representation/Internal ../../../schemas/XMLPipeConfig.xsd"
        name="Do nothing examples">

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
    </statm>
  </profile>

  <transformer name="helloTextJava"
	       class="HelloTransformer"/>

  <handler name="helloTextJavaHandler"
	   ns="uri:example/hello"
           root="helloWorld">
    <pipe>
        <transform ref="helloTextJava"/>
    </pipe>
  </handler>

</config>

The onlt difference is that the transformer declaration uses our class instead of the XSLTTransformer and that it does not have an src attribute (the behaviour does not depdend to a parameter in this case). If we invole XMLPipe with exactly the same arguments:
java XMLPipeCmd -c config.xml -o helloSimpleOut.xml desktop helloSimple.xml
we will get a similar result (browse here):
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">
  <head><title>Hello World from Java</title></head>
  <body>
     <h1>Hello World from Java</h1>
  </body>
</html>

Even if the transformer is very simple it illustrates the basic principles of XMLPipe processing. The constructor informs the transformer super class if the transformer accepts a parameter [N: 2] and if it has to be validated. In our case both are false since HelloTransformer does not use a parameter. There are to transformation methods, called transformCustom. One is for transformers that accept a parameter (in which case it is parsed and ready for use) while the other is for transformer not using a parameter. The typical approach is to throw an exception if the wrong one is called. [N: 3]

notes[
[N: 2] such as the "src" attribute of the XSL-T transformer - try to use a transformer declaration using a src attribute and XMLPipe will start crying again.
[N: 3] XMLPipeTransform* exceptions are typically used for errors during the transformation process. XMLPipeTransformTempException when the transforer does not know the location of the cause of the error (e.g. a statement in a stylesheet). In that case the error is reported as if it was caused by the associated pipeline. Otherwise the XMLPipeTransformException is used and the location information is passed using one of its constructors (nodes in XMLPipe tend to have hidden location information and in most of the cases simply passing the DOM node that created the error is enough)
]

The overloaded version of transformCustom has to modify the DOM tree and replace the hellowold element with a text node. When a transformer is called for an element, the root node contains the elements that have to be handled (e.g in this case it will only be the helloWorld element). This allows transformer implementations to avoid searching the tree for the node to transform. After replacing the child we return the value of "true" to denote that the tree was modified (if there are no tree or context modifications, the return value has to be false).

Other information that we do not use here is the ComponentInterface which provides "get" methods for all the XMLPipe components that a transformer migght need (e.g. ErrorHandler, FactoryImplementations etc). The isAttr parameter specifies if the handled construct is an attribute. Finally, the TransformationContext allows access and modification of the context information. We will see the use of all of these in more advanced examples

3.4 Simple tranformation pipelines

The previous examples consisted of simple transformation which could be performed in a single step. However, for more complex handling a pipeline of transformations might be required. XMLPipe allows construction of complex transformation pipelines for each handler by three pipeline types which are described below. These types can be nested to allow construction of even more complex transformation pipelines.

3.4.1 Transformation Sequence

The most usual form of a transformation pipeline is the transformation sequence where the result of a transformation is fed to the next transformation and so on. A typical use of a sequence is to handle a number of languages in a document (e.g. handle XML Inclusions first and then any custom languges). However, the XMLPipe model handles itself the integration of different languages and this transformation sequences are uses when, for some reason, one step is not sufficient.

In accordance with our previous example, we might have a generic (probably a very expensive commercial product :) "greeting" transformer which processes a generic representation of the form:

<genericHi>
  <greeting>
     Hello 
  </greeting>
  <to>
     World!
  </to>
  <from>
    XSL-T
  </from>
</genericHi>
Assume that there is a fully featured processing library of the above content type that we want to reuse. Firstly, pay attention in two basic points: there is no use of namespaces (otherwise it would be easier to define a separate handler) and we do not use real world examples (because we want to point out the basic features of XMLPipe and proper examples would be confusing [N: 4]) We would like to implement our previous handlers using the generic functionality provided by this content type. Since, namespace are not used we can only use its functionality in terms of a pipeline.

notes[
[N: 4] There will be a "case studies" document in the future that provides XMLPipe based solutions for real world situations
]

We we change the previously define helloWorld and helloCustom stylesheets to:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
		version = "1.0"
		xmlns:hello = "uri:example/hello">
  
  <xsl:template match="hello:helloWorld">
     <genericHi>
       <greeting>Hello</greeting>
       <to>World!</to>
       <from>XSL-T</from>
     </genericHi>
  </xsl:template>

</xsl:stylesheet>

and
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
		version = "1.0"
		xmlns:hello = "uri:example/hello">
<xsl:strip-space elements="*"/>
  
  <xsl:template match="hello:helloCustom">
     <genericHi>
       <greeting>Hello</greeting>
       <to><xsl:copy-of select="node()"/></to>
       <from>XSL-T</from>
     </genericHi>
  </xsl:template>

</xsl:stylesheet>

respectively.

The expensive genericHi may contain a stylesheet that converts the greeting to simple text, such as:

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

  <xsl:template match="genericHi">
     <xsl:text>Greeting library output[</xsl:text> 
     <xsl:copy-of select="greeting/node()"/>
     <xsl:text> dear </xsl:text>
     <xsl:copy-of select="to/node()"/>
     <xsl:text> (a greeting issued by: </xsl:text>
     <xsl:copy-of select="from/node()"/>
     <xsl:text>)] A courtesy of Generic Greetings Ltd</xsl:text>
   </xsl:template>
   
</xsl:stylesheet>

Finally, the configuration file that will allow our stylesheets to interoperate is:

<?xml version="1.0"?>

<config xmlns="xml.asscoder.gr/XMLPipe/Representation/Internal"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="xml.asscoder.gr/XMLPipe/Representation/Internal ../../../schemas/XMLPipeConfig.xsd"
        name="Do nothing examples">

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
    </statm>
  </profile>

  <transformer name="helloTextTr"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="helloText.xsl"/>             

  <transformer name="helloCustomTr"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="helloCustom.xsl"/>             

  <transformer name="greetingsTr"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="greetingText.xsl"/>             

  <handler name="helloTextHandler"
	   ns="uri:example/hello"
           root="helloWorld">
    <pipe>
        <transform ref="helloTextTr"/>
        <transform ref="greetingsTr"/>
    </pipe>
  </handler>


  <handler name="helloCustomHandler"
	   ns="uri:example/hello"
           root="helloCustom">
    <pipe>
        <transform ref="helloCustomTr"/>
        <transform ref="greetingsTr"/>
    </pipe>
  </handler>

</config>

The transformation sequence is the default pipeline container and therefore we simply list the transformation without introducing any special syntax. The only difference of this configuration file than the one in Section 3.2 is the additional declaration of the greetingsTr transformer and the used of a sequence of transformations instead of single transformations for the handlers.

The processing of the same input file will yield the following result (browse here):

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">
  <head><title>Greeting library output[Hello dear World! (a greeting issued by: XSL-T)]
               A courtesy of Generic Greetings Ltd
  </title></head>
  <body>
     <p>We can say: Greeting library output[Hello dear World! 
          (a greeting issued by: XSL-T)] A courtesy of Generic Greetings Ltd
    </p>
    
    <p>We can also say: Greeting library output[Hello dear Mike 
         (a greeting issued by: XSL-T)] A courtesy of Generic Greetings Ltd
    </p>

     <p>A more fancy greeting can be:
        Greeting library output[Hello dear 
         <span style="color:red;font-size:300%" xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">Mike</span> 
            (a greeting issued by: XSL-T)] A courtesy of Generic Greetings Ltd
     </p>
     <p>And we can nest constructs as well, providing
        double world greetings such as:<br/>
        Greeting library output[Hello dear 
            <span style="color:blue" xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">
                Greeting library output[Hello dear World! (a greeting issued by: XSL-T)] 
                A courtesy of Generic Greetings Ltd
            </span> (a greeting issued by: XSL-T)] 
        A courtesy of Generic Greetings Ltd 
    </p>
  </body>
</html>

3.4.2 Dynamic transformation

The dynamic transformation pipeline, allows the parameter of a transformation (the src attribute of the transformer) to be dynamically computed as part of another transformation. The typical use of a dynamic pipeline is to dynamicaly produce a stylesheet for a transformation.

For the demonstration of the dynamic pipeline construct we will move to slightly more complex examples than the "helloWorld" examples we used previously.

Assume that we have defined a language that allows an document to include other XML documents. For such an inclusion, we also need a selection mechanism that will be used to specify which parts of the target document will be included. An easy to use selection technique is XPath expressions which are typicaly used in XSL stylesheets.

Let us think of a document containing greetings in several languages such as:

<?xml version="1.0"?>
<greetings>
  <hi>
    <en>Hi</en>
    <gr>Geia</gr>
    <es>Hola</es>
  </hi>
  <howAreYou>
    <en>How are you</en>
    <gr>Pos eisai</gr>
    <es>Como es tas</es>
  </howAreYou>
</greetings>


What we want, is to be able to write an XML document such as:
<?xml version="1.0"?>

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:imp="uri:example/import">

  <head>
    <title>Multilanguage greetings</title>
  </head>

  <body>
    <p><strong>English:</strong>
       <imp:import href="included.xml" 
                   select="/greetings/hi/en/text()"/>
       Mike!
    </p>
    <p><strong>Greek:</strong>
       <imp:import href="included.xml" 
                   select="/greetings/hi/gr/text()"/>
       Mike!
    </p>
    <p><strong>Spanish:</strong>
       <imp:import href="included.xml" 
                   select="/greetings/hi/es/text()"/>
       Mike!
    </p>
  </body>
</html>

which will produce multi language versions of "Hello Mike!".

XSL-T 1.0 does not support dynamic evaluation of XPath expressions and therefore we will have to dynamically construct a stylesheet that processed the included.xml document to extract the greeting specified in the calling document. A stylesheet that can generate the final stylesheet we need is:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
                xmlns:n = "uri:example/import"
                xmlns:xslout="this value is not used"
		version = "1.0">

  <!-- Alias needed when generating stylesheets -->
  <xsl:namespace-alias stylesheet-prefix="xslout" result-prefix="xsl"/>

  <xsl:template match="n:import">
     <xslout:stylesheet version="1.0">
        <xslout:template match="n:import">
           <xslout:copy-of select="document(@href){@select}"/>
        </xslout:template>
    </xslout:stylesheet>
  </xsl:template>

</xsl:stylesheet>

The configuration file that we will use in order to orchestrate the dyanmic stylesheet creation and its application will be:

<?xml version="1.0"?>

<config xmlns="xml.asscoder.gr/XMLPipe/Representation/Internal"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="xml.asscoder.gr/XMLPipe/Representation/Internal ../../../schemas/XMLPipeConfig.xsd"
        name="Do nothing examples">

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
    </statm>
  </profile>

  <transformer name="transformGenerator"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="import.xsl"/>             

  <transformer name="dynamicXSLT"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="xmlPipe:dynamicSrc"/>             

  <handler name="importHandler"
	   ns="uri:example/import"
           root="import">
    <pipe>
       <dynamic>
          <normal/>
          <option>
             <transform ref="transformGenerator"/>
          </option>
          <transform ref="dynamicXSLT"/>
       </dynamic>
    </pipe>
  </handler>

</config>

Similarly to the previous examples we begin with an application profile declaration. Then there is the transformer declaration for the stylesheet that generates the final stylesheet. When we want to use a dynamic pipelines, we need a final transformation which will apply the generated stylesheet to the actual document. Since the gerated stylesheet is still XSL, we will use the usual XSLTTransformer. The only difference is that in the transformer declaration we use src="xmlPipe:dynamicSrc" instead of an actual stylesheet. This is an XMLPipe reserved value which is used to specify the the inpout to a tranformer is to be dynamically computed and cannot be predefined.

Our handler consists of a simple dynamic transformation. A dyanmic transformation has three parts: the normal pipeline, the option pipeline and the final combining transformation. If the original tree to be handled is t, the processing is as follows:

Consequently, in our case the dynamicXSLT transformer applies the transformation created by the transformGenerator transformer to the original handled sub-tree (since the normal transformation is empty).

Therefore, if we call XMLPipe as follows:

java XMLPipeCmd -c configDynamic.xml -o importOut.xml desktop import.xml
we will get the following result (browse here):
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:imp="uri:example/import">

  <head>
    <title>Multilanguage greetings</title>
  </head>

  <body>
    <p><strong>English:</strong>
       Hi
       Mike!
    </p>
    <p><strong>Greek:</strong>
       Geia
       Mike!
    </p>
    <p><strong>Spanish:</strong>
       Hola
       Mike!
    </p>
  </body>
</html>

which is what we aimed for.

In this case the complete stylesheet was generated dynamically. However, there are cases in which we simply want to modify a stylesheet and not generated it (usefull for some stylesheet processing or when the stylesheet is too complex to genrate dynamically). In such cases, the src attribute of the option tag in the XMLPipe configuration file can be used to specify an alternative source. This overides the default behaviour where the souce is the original document tree. This can be used only in cases where access to the original tree is not needed.

For instance, we might want to modify the original "helloWorld" stylesheet to provide greetings in Spanish instead of english. The stylesheet has to be processed before applied to the original document in order to change the "Hello" string to its Spanish alternative. A stylesheet that could do that will have to filter the whole stylesheet by changing all the "Hello" strings to the "Hola" spanish version. This could be performed by:

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

  <xsl:template match="/|*">
     <xsl:copy>
         <xsl:copy-of select="@*"/>
	 <xsl:apply-templates/>
     </xsl:copy>
  </xsl:template>

  <xsl:template match="text()">
    <xsl:choose>
      <xsl:when test="contains(., 'Hello')">
         <xsl:value-of select="substring-before(., 'Hello')"/>
         <xsl:text>Hola</xsl:text>
         <xsl:value-of select="substring-after(., 'Hello')"/>
      </xsl:when>
      <xsl:otherwise>
         <xsl:value-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template> 
</xsl:stylesheet>

which would be used as shown in the respective configuration file:
<?xml version="1.0"?>

<config xmlns="xml.asscoder.gr/XMLPipe/Representation/Internal"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="xml.asscoder.gr/XMLPipe/Representation/Internal ../../../schemas/XMLPipeConfig.xsd"
        name="English to Spanish">

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
    </statm>
  </profile>


  <transformer name="EnToEsTr"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="modifyStylesheetDebug.xsl"/>             

  <transformer name="dynamicXSLT"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="xmlPipe:dynamicSrc"/>             

  <handler name="helloTextHandler"
	   ns="uri:example/hello"
           root="helloWorld">
    <pipe>
        <dynamic>
           <normal/>
           <option src="../helloXSLT/helloText.xsl">
              <transform ref="EnToEsTr"/>
           </option>
           <transform ref="dynamicXSLT"/>
        </dynamic>
    </pipe>
  </handler>
</config>

This would change any single occurence of "Hello" in a text node to "Hola". (the explanation of the use of "modifyStylsheetDebug" instead of the stylsheet shown will be exmplained shortly)

We can see that the configuration file simply reused the old stylesheet for handling the helloWorld elements and it only specifies what is needed to modify and apply the old stylesheet. The attribute src of the option elelement specifies the old stylesheet which will be processed by our stylesheet filter. The result is combines, as previously, using the dynamicXSLT transformer.

Now, for some reason this does not work because the original xmlns:hellp namespace declaration in the original stylesheet is lost and therefore during the processing of the produced stylesheet the namespace prefix "hello" is not bound. This should be corrected in some future better implementations of the XSLTTransformer. A solution would be to create a new xsl:stylesheet element that would contain the namespace declaration. This can be performed using the following stylsheet:

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

  <xsl:namespace-alias stylesheet-prefix="xslout" 
                       result-prefix="xsl"/>

  <xsl:template match="*">
     <xsl:copy>
         <xsl:copy-of select="@*"/>
	 <xsl:apply-templates select="node()"/>
     </xsl:copy>
  </xsl:template>


  <xsl:template match="xsl:stylesheet">
     <xslout:stylesheet  version="1.0" xmlns:hello="uri:example/hello">
	 <xsl:apply-templates select="node()"/>
     </xslout:stylesheet>
  </xsl:template>


  <xsl:template match="text()">
    <xsl:choose>
      <xsl:when test="contains(., 'Hello')">
         <xsl:value-of select="substring-before(., 'Hello')"/>
         <xsl:text>Hola</xsl:text>
         <xsl:value-of select="substring-after(., 'Hello')"/>
      </xsl:when>
      <xsl:otherwise>
         <xsl:value-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

which is exaclty the same apart from the special handling of the xsl:stylesheet element. We can now invoke XMLPipe for the old example file:
java XMLPipeCmd -c configEnToEs.xml desktop ../helloXSLT/helloSimple.xml
and the result would be (browse here):
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">
  <head><title>Hola world from XSL-T</title></head>
  <body>
     <h1>Hola world from XSL-T</h1>
  </body>
</html>

which gives the expected results.

NOTE[
Such bugs/errors as the one we mentioned with the lost namespace prefix declaration are very difficult to trace. These things tend to happen when the XSLTTransformer is used. A debuggin tip is that if the --DEBUG is used, the document to be transformed, the stylesheet and the result are printed out (as well as loads of other debug information) for each XSLT invocation and this allows you to check exactly how XSLT is applied. ]

3.4.3 Selection transformation

In the previous section we modified the existing handler to provide a spanish version of the hello world template. If we have several of these stylesheets we need a way to control which language should be used. An easy way to do this is by using the selection transformation pipeline construct.

The selection pipeline allows different transformation alternatives to be selected according to the context information. They can be used to allow different handling according to the device capabilities (in addition to the automatic handler selection), user defined term values and any other context information.

In our case, we will need a term to be used for defining the language to use. As we have already said a term has an associated namespace, a name and a type. We will use uri:example/hello/Terms for the namespace, language for the name and StringValue for its type. Note, the selection of the URI and its resemblance to the language URI. We have selected a similar uri since this term specifies a property of the language. We did not use the same URI since the term will be considered language context and the behaviour will be different (in this simple example the results would be exactly the same - however, language context should be used only when needed - we'll describe that later).

We will have three versions of the stylesheet of the previous examples, one for each of the following three languages:

The configuration file will also contain the declaration of our term and the additional selection of the stylesheet to apply:

<?xml version="1.0"?>

<config xmlns="xml.asscoder.gr/XMLPipe/Representation/Internal"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="xml.asscoder.gr/XMLPipe/Representation/Internal ../../../schemas/XMLPipeConfig.xsd"
        name="English to Spanish">

  <term ns="uri:example/hello/Terms"
        name="language"
        type="StringValue"/>

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
    </statm>
  </profile>


  <transformer name="EnToEsTr"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="modifyStylesheetEnToEs.xsl"/>             

  <transformer name="EnToGrTr"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="modifyStylesheetEnToGr.xsl"/>             

  <transformer name="dynamicXSLT"
	       class="gr.asscoder.xml.XMLPipe.transformers.XSLTTransformer"
               src="xmlPipe:dynamicSrc"/>             


  <handler name="helloTextHandler"
	   ns="uri:example/hello"
           root="helloWorld">
    <pipe>
        <dynamic>
           <normal/>
           <option src="../helloXSLT/helloText.xsl">
              <selection>
                 <case>
                   <constraints>
                     <expr ns="uri:example/hello/Terms"
                           name="language">
                        <equals>
                           <val>ES</val>
                           <termVal/>
                        </equals>
                     </expr>
                   </constraints>
                   <transform ref="EnToEsTr"/>
                 </case>
                 <case>
                   <constraints>
                     <expr ns="uri:example/hello/Terms"
                           name="language">
                        <equals>
                           <termVal/>
                           <val>GR</val>
                        </equals>
                     </expr>
                   </constraints>
                   <transform ref="EnToGrTr"/>
                 </case>
                 <case>
		    <!-- Default is in english -->
                 </case>
              </selection>
           </option>
           <transform ref="dynamicXSLT"/>
        </dynamic>
    </pipe>
  </handler>
</config>

What we have here, is the declaration of term which merely consists of the specification of the namespace, the name and the type. We have substituted the simple transformation with a selection transformation nested in the dynamic transformation pipeline. Each selection, has a number of cases (three in our example). The case to be selected is identified by the associated constraints (the first child). An optional case without any constraints is allowed and it fucntions as a "default" or "fallback" alternative. For each of the specified constraints, we have a single expression which checks of the specified term "equals" the values "ES" or "GR". If none of these two are true, the default case is used which simply leaves the stylesheet unmodifies (since the default is english).

Now, the question is how to set the term value that we need. The easiest way is to used the command line term specification using the -D option which uses a: <termQName> = <value> syntax. Another alternative would be to specify a value for the term in the application profile. Additionally, we could specify the value as the "pipeline" context (by including a "context" element at the begining of the handler definition).

If we want to use the command line syntax we could type:

java XMLPipeCmd -D uri:example/hello/Terms:language=GR -c configSelection.xml  desktop ../helloXSLT/helloSimple.xml
which would yield the result (browse here):
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">
  <head><title>Geia soy world from XSL-T</title></head>
  <body>
     <h1>Geia soy world from XSL-T</h1>
  </body>
</html>

or use
java XMLPipeCmd -D uri:example/hello/Terms:language=ES -c configSelection.xml  desktop ../helloXSLT/helloSimple.xml
which would yield the result (browse here):
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">
  <head><title>Hola world from XSL-T</title></head>
  <body>
     <h1>Hola world from XSL-T</h1>
  </body>
</html>

or even (the default)
java XMLPipeCmd  -c configSelection.xml  desktop ../helloXSLT/helloSimple.xml
which would yield the result (browse here):
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:hello="uri:example/hello">
  <head><title>Hello world from XSL-T</title></head>
  <body>
     <h1>Hello world from XSL-T</h1>
  </body>
</html>

3.5 Device neutral handling: Hello world spectacular

The previous examples have covered the the most important aspected of XML usage apart from the device neutral handling capabilities which is the main power of XMLPipe. Continuing with our simple "helloWorld" examples we will study how to combine all of the above in a device neutral repesentation.

When we consider handling in device neutral terms we cannot use languages such as XHTML to specify the document structure. Even if XHTML is designed to be a device neutral language, the usual XHTML usage cannot be applied or is not the optimal representation for all the devices. For instance, in a restricted XML appication such a mobile WML browser it not possible to clearlt map all the XHTML constructs. On the other hand, if we have a really fancy XML handling application which supports all the state of the art XML representation such as SMIL and SVG we would propably prefer a fancier rendering of our content which cannot be represented using XHTML.

In this section we will define a "carrier" document type which will be used to describe simple documents. Then we will add support for all the "greeting" languages in a way that they can be represented differently according to the device capabilities, by using a number of different languages.

The different devices that will be used will be a typical desktop browser supporting XHTML and SVG, a mobile supporting WML and WMLS 1.0 and only WBMP for images, and a multimedia browser that supports XHTML, SMIL and SVG. We will have two different modes of presentation: normal and "fancy". The first one will try to convey the information in the best possible way without to many adorments. The latter will use as much of the functionality as possible to provide a more "visual" representation.

Specifically, the application profiles will be declared as follows:

  <profile name="desktop">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
      <item>http://www.w3.org/2000/svg</item>
      <item>xml.asscoder.gr/XMLPipe/Profile/Mime/image/jpeg</item>
      <item>xml.asscoder.gr/XMLPipe/Profile/Mime/image/bmp</item>
      <item>xml.asscoder.gr/XMLPipe/Profile/Mime/image/gif</item>
    </statm>
  </profile>

  <profile name="multimedia">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">desktop</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.w3.org/1999/xhtml</item>
      <item>http://www.w3.org/2001/XMLSchema-instance</item>
      <item>http://www.w3.org/2000/svg</item>
      <item>http://www.w3.org/2001/SMIL20/</item>
      <item>xml.asscoder.gr/XMLPipe/Profile/Mime/image/jpeg</item>
      <item>xml.asscoder.gr/XMLPipe/Profile/Mime/image/bmp</item>
      <item>xml.asscoder.gr/XMLPipe/Profile/Mime/image/gif</item>
    </statm>

  <profile name="mobile">
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="deviceType">mobile</statm>
    <statm ns="xml.asscoder.gr/XMLPipe/Terms"
        name="supported">
      <item>http://www.wapforum.org/DTD/wml_1.1.xml</item>
      <item>xml.asscoder.gr/XMLPipe/Profile/Mime/image/wbmp</item>
    </statm>
  </profile>



There is nothing new in these declaration except from some weird URIs such as: xml.asscoder.gr/XMLPipe/Profile/Mime/image/jpeg. This is the XMLPipe approach for content types that do not have any associated URIs (e.g. they are not XML languages that support namespaces). One could say that these should use URIs of the respective organisation in order to be the closes possible alternatives to the URIs that would be used of there were associated namespaces. However, since there are not clear specification of those, it seems simpler to allocate some XMLPipe base uris for usual content types. For instance, the URI xml.asscoder.gr/XMLPipe/Profile/Mime/ is used for the usual mime types. An application can simply check all the supported technologies that begin with this string to identify the supported media types. Moreover, for older XML languages that do not use namespace, the URL of their DTD can be used as an alternative (e.g. for WML 1.1).

3.5.1 The carrier document type

The carrier document type would be fairly simple since it only has to meet our "hello world" requirements. Specifically, we will have a title field, paragraphs and content that can be emphazied or facyized. We do not have spefic layout constructs (such as "italics" for emphasis) since we would like to use each device capabilities to provide the most adequate representation for each device (e.g. empahsis in a mobile which does not support italics could be by separating the text from its context).

3.5.1.1 The syntax

The schema for the document would be:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	    targetNamespace="uri:example/document"
	    xmlns:ns="uri:example/document"
            elementFormDefault="qualified">

  <xsd:element name="document">
    <xsd:complexType>
      <xsd:sequnce>
        <xsd:element name="title" type="xsd:string"/>
        <xsd:element name="p" type="pType" 
                     minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>

  <xsd:complexType name="pType" mixed="true">
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
       <xsd:element name="em" type="pType"/>
       <xsd:element name="fancy" type="pType"/>
       <xsd:element name="img">
          <xsd:complexType>
             <xsd:attribute name="href" type="xsd:string" use="required"/>
             <xsd:attribute name="mimeType" type="xsd:string" use="required"/>
             <xsd:attribute name="alt" type="xsd:string" use="required"/>
          </xsd:complexType>
       </xsd:element>
       <xsd:any namespace="##other" processContents="lax"/>
    </xsd:choice>
  </xsd:complexType>

</xsd:schema>

which contains the very basic elements for document description. We also allow image inclusion where the mime type has to be explicitly specified in order to check of the application profile supports a specific type of images. We also have the usual alt element that will contain a descriptive text in case the image cannot be rendered. Note the use of the xsd:any to allow integration of content types. The paragrah type is the only place in which we expect arbitrary content. It is essential to allow constructs of other namespaces to be integrated in our paragraphs.

3.5.1.2 The carier language semantics

In order to allow device neutral handling of an XML language, the semantics of the language as well as the supported constructs should be independent of the target platform. Therfore, we cannot restrict the functionality of the language constructs. For instance, the image types that can be included using the img cannot be specified as "the types supported by the target application profile". Such an approach would probably allow easier handler developement but would not provide the document author with a well defined set of the supported functionality. The net result would be document that cannot supported in all application profiles or documents which would only use a restricted set of the functionality in order to ensure that they can be hanlded in a variety of devices.

Therefore, we define the semantics as follows:

3.5.1.3 The carrier document handling

The final presentation of the document will depend on the application profile. The required technologies are different for the general document content, the image handling and the fancy content. Therefore, we will provide separate handlers for each.

The simplest case is the desktop handler for the basic document conent which is the following stylesheet:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
		version = "1.0"
                xmlns = "http://www.w3.org/1999/xhtml"
		xmlns:n = "uri:example/document"
                xmlns:xpipe = "xml.asscoder.gr/XMLPipe/Representation/Internal">

  <xsl:template match="n:document">
    <html>
      <head><title><xsl:value-of select="n:title"/></title></head>
      <body>
        <h1 style="text-align:center">
           <xsl:value-of select="n:title"/>
        </h1>

        <xsl:apply-templates select="n:p"/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="n:p">
    <p>
      <xsl:apply-templates select="*|text()"/>
    </p>
  </xsl:template>

  <xsl:template match="n:em">
    <em><xsl:apply-templates select="*|text()"/></em>
  </xsl:template>


  <!-- Copy any unknown content -->
  <xsl:template match="*">
    <xsl:copy>
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates select="*|text()"/>
    </xsl:copy>     
  </xsl:template>

</xsl:stylesheet>

The onlt requirement of this stlysheet/handler is the support of XHTML.

A different stylesheet has to be provided for the cases where XHTML is not supported. For our application profiles we need a handler that produces WML 1.1 output. We have selected this relatively old standard since producing WML 1.1 using XMLPipe introduces some interesting issues. Firstly, typical mobile WML 1.1 browser do not support namespace, and therefore any namespace declaration have to be removed by the end documnet. Moreover, there is a requirement for a DOCTYPE declatation otherwise the document cannot be handled properly.

In XMLPipe a document type declaration can only be generated by when a handled construct is the root of a document which is signified by the context term: xml.asscoder.gr/XMLPipe/Terms:documentRoot. If a transformer wants to check if the handled construct is the root of the document it has to use this term and not the usual DOM or XSL-T techniques since the root of the tree might not be the actual document node of the DOM representation while XMLPipe processes the document. Document type information can be passed using the setDocType function of the Transformer class. When there is no access to the XMLPipe, the internal representation can be used, and the attributes sysId and pubId of the XML pipe configuration namespace can be specified in the root node of the result.

The stlysheet that we will use for the mobile handler is:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
		version = "1.0"
		xmlns:n = "uri:example/document"
                xmlns:xpipe = "xml.asscoder.gr/XMLPipe/Representation/Internal">
  <xsl:strip-space elements="*"/>

  <xsl:template match="n:document">
    <wml xpipe:sysId="http://www.wapforum.org/DTD/wml_1.1.xml" 
         xpipe:pubId="-//WAPFORUM//DTD WML 1.1//EN">
      <!-- Generic WML template -->
      <template>
        <do type="reset" label="start">
          <go href="#{generate-id(.)}"/>
        </do>
        <do type="prev" label="back">
          <prev/>
        </do>
      </template>

      <!-- The root card -->
      <card id="{generate-id(.)}">
        <xsl:attribute name="title">
          <xsl:value-of select="n:title"/>
        </xsl:attribute>

      <p><em><xsl:value-of select="n:title"/></em></p> 

      <xsl:call-template name="generateLocalIndex"/>
      </card>

      <xsl:apply-templates select="n:p"/>
   </wml>
  </xsl:template>

  <xsl:template match="n:p">
    <card id="{generate-id(.)}">
      <xsl:if test="following-sibling::n:p">
        <do type="accept" label="next">
           <go href="#{generate-id(following-sibling::n:p[1])}"/>
        </do>
      </xsl:if>
      <p>
        <xsl:apply-templates select="*|text()"/>
      </p>
    </card>
  </xsl:template>


  <xsl:template match="n:em">
    <xsl:text> *</xsl:text>
    <xsl:apply-templates select="*|text()"/>
    <xsl:text>* </xsl:text>
  </xsl:template>


  <!-- Copy any unknown content -->
  <xsl:template match="*">
    <xsl:copy>
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates select="*|text()"/>
    </xsl:copy>     
  </xsl:template>

  <xsl:template name="generateLocalIndex">
   <p>
     <xsl:for-each select="n:p">
         <a href="#{generate-id(.)}">
           <xsl:text>Text Section</xsl:text>
           <xsl:number count="n:p"/>
         </a>
   </xsl:for-each>
 </p>
 </xsl:template>


</xsl:stylesheet>

This stylsheet generates a basic WML layout where each paragraph exists in its own WML card. There are event handlers to ease the navigation for the mobile. Finally, since our testing platform does not support the em WML tag, we simply enclose any emphasized text in stars. [N: 5]

notes[
[N: 5] In the final pipeline there will be an additional stylsheet that removes any namespace declarations since WML 1.1 mobiles tend not to be aware of namespaces and we get unrecognized content errors.
]

The support for images introduces an interesting problem. We have specified three types which are supported by our content type. However, even if the typical desktop supports the specified standards, the mobile only supports the WBMP format. We could either use the "alt" text description there is no direct support or attempt to convert an image to the specified format. We will not provide a generic mechanism for converting between different image formats for desktop-like profiles since it would make this already complex example even more complex (this would be the correct approach, however, for proper device neutral handling). We will, however, provide a conversion transformer that allows creates WBMP representations of the graphics. Since we have binary data, we cannot use an XSL-T transformer and we will have to fallback to a custom transformer implementation.

A simple implementation that uses the WBMP conversion library that can be found at here is:

import  gr.asscoder.xml.XMLPipe.transform.*;
import  gr.asscoder.xml.XMLPipe.*;
import  gr.asscoder.xml.XMLPipe.terms.*;
import  gr.asscoder.xml.XMLPipe.parsing.DOMUtil;

import com.unwiredtec.wmcreator.SimpleImageFile;
import com.unwiredtec.wmcreator.WBMPfile;
import com.unwiredtec.wmcreator.WBMPFilter;
import com.unwiredtec.wmcreator.WBMPConstants;
import com.unwiredtec.wmcreator.WBMPDimension;

import java.io.*;

import java.net.*;

import org.w3c.dom.*;

/** A simple converter from common image files
to WBMP. It uses the fine WBMPCreator libary to do 
the hard work.
*/


public class wbmpConverter extends Transformer {

    static final String CAP_NS = "example.org/terms/capabilities";
    static final String CAP_MAXX = "maxImageX";
    static final String CAP_MAXY = "maxImageY";

    public wbmpConverter()
    {
	super(false, false);
    }
    
    public boolean transformCustom(ComponentInterface ci, 
				   Node root, 
				   boolean isAttr,
				   TransformationContext cnt) 
	throws XMLPipeTransformException,
	       XMLPipeTransformTempException
	       
    {

	
	//Get the handled construct
	Element img =  DOMUtil.getFirstEl(root);

	//Get the referenced image
	String imgURI = absoluteInputURI(img.getAttribute("href"), img).toString();

	//Default maximum image dimensions
	int maxX = getIntValue(CAP_NS, CAP_MAXX,
			       ci, cnt);
	if (-1 == maxX) maxX = 100;


	int maxY = getIntValue(CAP_NS, CAP_MAXY,
			       ci, cnt);
	if (-1 == maxY) maxY = 100;

	
	//Check if there is any maximum image specification
	//in the context
	ErrorHandler err = ci.getErrorHandler();
	try {

	    err.error(ErrorHandler.INFO, 
		      "Converting image file: " + imgURI);
	    
	    SimpleImageFile sif = new SimpleImageFile(new URL(imgURI));
	    
	    WBMPFilter wff=new WBMPFilter();
	    //	    WBMPfile w = wff.complexImageFilter(sif.getPointArray(), sif.getLength(),
	    //sif.getWidth(),WBMPConstants.FILTER_DITHER_ORDER_4X4);
	    WBMPfile w = new WBMPfile(sif, -1, -1, -1);
	    
	    err.error(ErrorHandler.INFO, 
		      "Maximum image size: (" + maxX + ", " + maxY + ")");

	    //Resize if bigger than the screen size
	    if (w.getWBMPLength() > maxX || w.getWBMPWidth() > maxX) {
		//Compute the ratio to multiply
		double ratio = computeRatio(w.getWBMPLength(), w.getWBMPWidth(), maxX, maxY);
		
		err.error(ErrorHandler.INFO, 
		      "Resizing image, ratio: " + ratio);

		w.resize((int)(w.getWBMPLength() * ratio), (int)(w.getWBMPWidth() * ratio));
	    } /*else {
		w = w.getRectArea(new WBMPDimension(0, 0, maxX, maxY));
		}*/
	    
	    //Create an output file
	    
	    String relURI = "generatedImg/" + 
		imgURI.hashCode() + ".wbmp";
	    
	    
	    w.saveWBMPFile("WBMP", absoluteOutputURI(relURI).getPath());
	    
	    //Create a WML img tag that refers to the file
	    Document doc = root.getOwnerDocument();
	    
	    Element el = doc.createElement("img");
	    el.setAttribute("src", relURI);
	    el.setAttribute("alt", img.getAttribute("alt"));
	    
	    root.replaceChild(el, img);

	    err.error(ErrorHandler.INFO, 
		      "Generated new image: " + relURI);

	    return true;

	    
	} catch (IllegalArgumentException e) {
	    throw new XMLPipeTransformException(ErrorHandler.ERROR,
						"Cannot construct absolute from URI: " + imgURI + ": " + e.getMessage(),
						img);
	} catch (MalformedURLException e) {
	    throw new XMLPipeTransformException(ErrorHandler.ERROR,
						"Cannot construct URL from URI: " + imgURI + ": "+ e.getMessage(),
						img);
	} catch (NoClassDefFoundError e) {
	    throw new XMLPipeTransformTempException(ErrorHandler.ERROR,
						    "The WBMP Creator library doesnt seem to be accesible: " + e.getMessage()); 
	    
	} catch (Exception e) {
	    throw new XMLPipeTransformException(ErrorHandler.ERROR,
						"Cannot tranform image: " + e.getMessage(),
						img);
	    
	}
	
	
	
    }
    
    public boolean transformCustom(ComponentInterface ci, 
				   Node root, 
				   boolean isAttr,
				   TransformationContext cnt,
				   Node par)
	throws XMLPipeTransformException,
	       XMLPipeTransformTempException
	       
	       
    {
	throw new XMLPipeTransformTempException(ErrorHandler.ERROR, 
            "Cannot call WBMPTransformer with a parameter");
    }

    /** Convenience methid to extract context statemeent
	values. It returns -1 if there is no definition 
    */
    public int getIntValue(String ns, String name,
			   ComponentInterface ci,
			   ContextInformation cnt)
    {
	//Get the term
	
	Term term = (Term)ci.getConfigTable().getTerm(Term.getQName(ns, name));
	
	if (null == term) return -1;

	//Check if there is any statement
	Statement st = cnt.getStatement(term);

	if (null == st  ||
	    !(st.getValue() instanceof NumericValue)) {
	    return -1;
	}

	NumericValue val = (NumericValue)st.getValue();

	return (int)val.getValue();
	    
    }

    public double computeRatio(int x, int y, int maxX, int maxY)
    {
	//Which is the worst?
	boolean xIsWorst = ((double)x / maxX > (double)y / maxY);

	if (xIsWorst) {
	    return (double)maxX / x;
	} else {
	    return (double)maxY / y;
	}
	
	
    }
    
}


Appart from the conversion code (which is not described here) we have the following XMLPipe related features. We always use the TransformerUtil functions to resolve possible relativ URIs. In this case we "absolutize" the URL that specifies the location of the image file. Then we check if any values that specify the maximum image size have been specified and if so they are extracted by the transformation context. Finally, we create a URL for the output file and add the new WBMP "img" element in the place of the old "img" tag.

Finally, as far as the carrier document is concerned (which is the most complex part of our configuration) we need to handle the fancy element. We will provide two stylesheets for each of the three types of profiles we have. One will be called when the "fancy" term is set to false true while the latter otherwise. When there is XHTML and SVG support, we will use blinking colored text and an SVG repesentation of the text for the two cases. If there is additional SMIL support, the above constructs will be moving around as well. Fiannly, for the mobile handler we will have an underlined form of the content and again a graphic representation of the text (which would be automatically converted if we simply create an img tag of the carrier document namespace.

The latter, points out again the power of XMLPipe. As far as some languge construct are handled for the target profile we can easily use them by simply inserting them to the doument tree. This provides an optimal way of interoperation of XML handlers using XML representation.

So, the two stylesheets for the desktop will be, for the less fancy presentation:

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
		version = "1.0"
                xmlns = "http://www.w3.org/1999/xhtml"
		xmlns:n = "uri:example/document">

  <xsl:template match="n:fancy">
    <span style="text-decoration:blink;color:orange;font-size:34pt">
       <xsl:copy-of select="*|text()"/>
    </span>
  </xsl:template>

</xsl:stylesheet>

and for the fancier version:
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
		version = "1.0"
                xmlns = "http://www.w3.org/1999/xhtml"
		xmlns:n = "uri:example/document"
                xmlns:svg = "http://www.w3.org/2000/svg">

  <!-- We can only handle text nodes. The other ones
       use the blink way -->
  <xsl:template match="n:fancy">
     <xsl:apply-templates select="*|text()"/>
  </xsl:template>

  <xsl:template match="*">
    <span style="text-decoration:blink;color:orange;font-size:34pt">
       <xsl:copy-of select="."/>
    </span>
  </xsl:template>

  <xsl:template match="text()">
    <xsl:variable name="charWidth">20</xsl:variable>
    <xsl:variable name="charHeight" select="$charWidth * 2"/>

    <xsl:variable name="textWidth" select="$charWidth * string-length(.)"/>


    <svg xmlns="http://www.w3.org/2000/svg"
         width="{$textWidth * 1.5}" height="{$charHeight * 4}">
  
     <g>
    
       <svg:rect x = "1" y="1" 
             width="{$textWidth * 1.5 - 10}"  height="{$charHeight * 4 - 10}"
             fill="purple" stroke="red" stroke-width="3"/>

       <svg:text x = "{$textWidth * 0.25}" 
             y = "{$charHeight * 2.25}"
             fill="blue" font-size="{$charHeight}">
            <xsl:value-of select="."/>
       </svg:text>

       <xsl:variable name="rad" select="$charWidth"/>

       <svg:circle cx = "{$rad}" cy="{$rad}" r = "{$rad}"
                   fill="red"/>
       <svg:circle cx = "{$textWidth * 1.5 - $rad}" cy="{$rad}" r = "{$rad}"
                   fill="green"/>
       <svg:circle cx = "{$rad}" cy="{$charHeight * 4 - $rad}" r = "{$rad}"
                   fill="orange"/>
       <svg:circle cx = "{$textWidth * 1.5 - $rad}" cy="{$charHeight * 4 - $rad}" r = "{$rad}"
                   fill="blue"/>
    

     </g>
    </svg>


  </xsl:template>
</xsl:stylesheet>

In the last example there is an iteresting issue raised. Up to now we left any interoperation of different content handlers to the end XML application. For instance we simply enclosed any content to blink and em XHTML element and we expect the XHTML handler to do its best to render the content appropriately. However, when the handling has to be performed in XMLPipe, where there is no handler interoperation, we cannot use this technique. For instance, the SVG text generation at the later example need specifically text content. If, for example, there is an image inside the fancy element we need completely different handling. This, of course, is not possible since we cannot now what type of content to expect. Therefore, a common apparoach is to defer what is possible to the end handler (e.g. we use the not-so-fancy blink element for all non-text content) and handle only the content that we can actuall handle at this point (e.g. the text content).

3.6 Integrating a new transformation language

3.7 Using and avoiding recursion

3.8 Context usage at different levels

3.9 Using internal annotations: Better import handler

3.10 Integrating a new transformation language pt 2: XSLTTransformer

3.11 Using multiple output documents

3.12 The XMLPipe transformers


Chapter 4: Languages and transformers design guideline


Chapter 5: Transformer implementation


Chapter 6: Conclusion


Appendix: A Configuration reference

A.1 Terms

A.1.1 Term types

The set of term types is hardcoded into the implementation and cannot be changed without any code modifications. [N: 1] The current set of types is summarized in Table A.1.

notes[
[N: 1] its easy though: simply extend the TermValue class and add a corresponding statement at the init function and the new type will integrated with XMLPipe
]

NameExample valuesEvaluationDescription
BooleanValuetrue, false1: true, 0: falseA boolean value
NumericValue0, 1, 3.14, -3.12E-2v for v in [0, 1], 1 when > 1, 0 when < 0A numeric value
StringValueXMLPipe is amazing, uri:aUriDOES NOT EVALUATEA string value
SetOfStringsValue<item>String 1</item><item>String 2</item>DOES NOT EVALUATESet of strings
SetOfTermsValue<statm ns="..." name="...">value</statm><statm ...>other statement value</statm>...DOES NOT EVALUATESet of statements
Table A.1: Term types

A.1.2 Predefined terms

Predefined terms can be either reserved for XMLPipe use, for specific transformer functionality. These terms cannot be declared and should be used in accordance with their implicit semantics. The following list cannot be complete since each transformer is free to use any number of custom terms. Nevertheless, the list of known reserved terms is shown in Table A.2

NameNamespaceTypeReserved byUse
baseURIxml.asscoder.gr/XMLPipe/TermsStringValueXMLPipeThe base URI for a node or a construct
linexml.asscoder.gr/XMLPipe/TermsNumericValueXMLPipeThe file line for a node or a construct
columnxml.asscoder.gr/XMLPipe/TermsNumericValueXMLPipeThe file column for a node or a construct
computedURIxml.asscoder.gr/XMLPipe/TermsStringValueXMLPipeThe best estimate of the baseURI during a transformation
computedLinexml.asscoder.gr/XMLPipe/TermsNumericValueXMLPipeThe best estimate of the line during a transformation
computeColumnxml.asscoder.gr/XMLPipe/TermsNumericValueXMLPipeThe best estimate of the column during a transformation
documentRootxml.asscoder.gr/XMLPipe/TermsBooleanValueXMLPipeTrue if the handled construct is the root of the tree
outputURIxml.asscoder.gr/XMLPipe/TermsStringValueXMLPipeThe base URI for output documents
transformationxml.asscoder.gr/XMLPipe/TermsSetOfTermsValueXMLPipeTranformation location information. It should contain a baseURI, a column and a line statement
transformationsxml.asscoder.gr/XMLPipe/TermsSetOfTermsValueXMLPipeThe set of tranformations applied to a node. It contains a number of "transformation" statements
deviceTypexml.asscoder.gr/XMLPipe/TermsStringValueXMLPipeThe type of the target device. Typical values are: desktop, mobile, pda, printer, text etc
supportedxml.asscoder.gr/XMLPipe/TermsSetOfStringsValueXMLPipeThe set of namespace of technologies supported by an application profile
validateParxml.asscoder.gr/XMLPipe/TermsBooleanValueXMLPipeIf true then the optional source to tranformations are validated
annotatedImportshttp://xml.asscoder.gr/XMLPipe/XSLTBooleanValueXSTTransformerProduces location annotations for all the XSL-T imported documents. The info is consumed before the transformer returns
outputAnnotationhttp://xml.asscoder.gr/XMLPipe/XSLTBooleanValueXSTTransformerSerializes location information to the resulting tree
Table A.2: Predefined terms

A.1.3 Expression operators

A.2 Context information visibility


Appendix: B Useful classes for custom transformer


Appendix: C Command line usage


Appendix: D The transformers

D.1 XSLT Transformer