yax - an XProc (XML Pipeline) Implementation

description under construction

2008-03-03

Revision History

Table of Contents

What is yax?
Quickstart
Approach
Features
Status
Reference
Roadmap
Examples
Tutorial
Links
Legal Notice
Powered by

yax is an Java implementation of the XProc Specification, an XML Pipeline Language (XProc: An XML Pipeline Language W3C Working Draft 17 November 2006). yax processes XProc Scripts like:

<?xml version="1.0" encoding="UTF-8"?>
<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT" 
      yax:description="transforms 'a*' elements to 'b*' elmenents.">
      <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
   </xproc:step>
   <xproc:step name="trans2" type="xproc:XSLT" 
      yax:description="transforms 'b*' elements to 'c*' elmenents.">
      <xproc:input port="stylesheet" href="test/transformation2.xsl"/>
      <xproc:parameter name="transformer" value="Saxon6" /> 
   </xproc:step>
   <xproc:step name="trans3" type="xproc:XSLT" 
      yax:description="transforms 'c*' elements to 'd*' elmenents.">
      <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
      <xproc:parameter name="transformer" value="XSLTC" /> 
   </xproc:step>
</xproc:pipeline>

            

The following packages have to be available (installed):

Download yax from http://yax.sourceforge.net and unzip the file to an arbitrary <yax-installation-directory>.

On the command line change to the <yax-installation-directory> and start yax with:

# java -classpath lib/yax-0.7.jar net.sf.yax.Yax examples/example1.xproc examples/example1.xml 
         

If all works well you will get a set of messages like the following. Which transformation processor appears in the messages depends on your actual environment configuration.

            
default transformer is set to system transformer.
automaticOutput of pipe trace is set to 'yes'.
automaticOutput of port trace is set to 'yes'.
suppress of process is set to 'no'.
step 'trans1': transformer Apache Software Foundation (Xalan XSLTC)(Version 1.0) is used.
step 'trans2': transformer Apache Software Foundation (Xalan XSLTC)(Version 1.0) is used.
step 'trans3': transformer Apache Software Foundation (Xalan XSLTC)(Version 1.0) is used.
Yax run sucessful completed.
                        
         

This run generates several output file in the <yax-installation-directory>/examples directory:

The core idea of yax is to implement the XProc specification in a way that

a) makes it easy to follow the 'evolution' of the specification,

b) makes it easy to implement custom extentions and

c) makes some suggestions to the specification possible.

I assume for the majority of pipeline use cases the position of steps (and constructs) implies the chaining of input and output ports in the sequence of its appearance. That in mind it would be the easiest way to omit the explicit port entries where the intention of chaining the input and output ports is expressed by position of the components. Going this way it is necessary to write port entries only for the situation in which one want deviate the ordinary sequence.

In case of a closed pipeline structure the pipeline processing is quiet obvious:

<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
   </xproc:step>
   <xproc:step name="validate1" type="xproc:Validate"/> 
   <xproc:step name="trans2" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
   </xproc:step>
   <xproc:step name="trans3" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
   </xproc:step>
   <xproc:step name="validate2" type="xproc:Validate"/> 
</xproc:pipeline>
         

In case of using switching constructs like <Choose> <Try/Catch> the pipeline keeps closed and the pipeline processing as in the previous case:


   <xproc:pipeline name="pipe1" 
      xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
      xmlns:yax="http://opsdesign.eu/yax/1.0">
      <xproc:step name="trans1" type="xproc:XSLT">
         <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
      </xproc:step>
      <xproc:step name="trans2" type="xproc:XSLT">
         <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
      </xproc:step>
      <xproc:choose name="choose1">
         <xproc:when name="choose1when1">
            <xproc:step name="trans3.1.1" type="xproc:XSLT">
               <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
            </xproc:step>
            <xproc:step name="trans3.1.2" type="xproc:XSLT">
               <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
            </xproc:step>
         </xproc:when>
         <xproc:when name="choose1when2">
            <xproc:step name="trans3.2.1" type="xproc:XSLT">
               <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
            </xproc:step>
            <xproc:step name="trans3.2.2" type="xproc:XSLT">
               <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
            </xproc:step>
         </xproc:when>
         <xproc:otherwise name="choose1otherwise">
            <xproc:step name="trans3.9.1" type="xproc:XSLT">
               <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
            </xproc:step>
            <xproc:step name="trans3.9.2" type="xproc:XSLT">
               <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
            </xproc:step>
         </xproc:otherwise>
      </xproc:choose>
      <xproc:step name="trans4" type="xproc:XSLT">
         <xproc:input port="stylesheet" href="test/transformation4.xsl"/> 
      </xproc:step>
   </xproc:pipeline>            
            
         

Components like <Store> and <Load> opens a pipeline.

<Store> (and all other output components) opens the pipeline backward by transfering the current result to somewhere, but the main trunk of the pipeline will be kept untouched.

<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
   </xproc:step>
   <xproc:step name="trans2" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
   </xproc:step>
   <xproc:step name="store1" type="xproc:Store"/>
   <xproc:step name="trans3" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation4.xsl"/> 
   </xproc:step>
   <xproc:step name="trans4" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation4.xsl"/> 
   </xproc:step>
</xproc:pipeline>
            
         

Only <Load> (and all other input components) cuts the main trunk and and a decision how to continue is necessary. For instant yax simply cuts the trunk of the pipeline. The effect is - assuming c.p. - the result of the previous pipeline is simply discarded.

            
<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
   </xproc:step>
   <xproc:step name="trans2" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
   </xproc:step>
   <xproc:step name="load1" type="xproc:Load"/>
   <xproc:step name="trans3" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation4.xsl"/> 
   </xproc:step>
   <xproc:step name="trans4" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation4.xsl"/> 
   </xproc:step>
</xproc:pipeline>
            
         

So using input components only makes sense if one uses expicit references to the output port of the preceding part of an input component.

<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
   </xproc:step>
   <xproc:step name="trans2" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
   </xproc:step>
   <xproc:step name="load1" type="xproc:Load"/>
   <xproc:step name="trans3" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation4.xsl"/> 
   </xproc:step>
   <xproc:step name="trans4" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation4.xsl"/> 
      <xproc:input port="in" step="trans2" source="out"/> 
   </xproc:step>
</xproc:pipeline>
            
         

Issues concerning the Specification

Table 1.  Features

Feature

Description

common features

logging

You can use either log4j or another logging subsystem. Is no logging system is determined the log will be written to the system ports.

Implementation of Constructs

<p:pipeline>

The <Pipeline> element should be implemented in accordance with the specification.

The input port provides the documents to the contained components. The output port receives the result and provides it to the external realm.

<p:choose>/<p:when>/<p:choose>

The <p:choose>/<p:when>/<p:choose> element should be implemented in accordance with the specification.

Beside the source and the result port <p:choose>/<p:when>/<p:choose> uses the reference port. You can define a reference port either for each <p:when> or a general reference port at the <p:choose> element (or a mix from both). The input port provides the documents to the contained components. <p:choose>/<p:when>/<p:choose> communicates only via the ports of the <p:choose> element with the external realm.

<p:try>/<p:group>/<p:catch>

The <p:try>/<p:group>/<p:catch> element should be implemented in accordance with the specification.

The <p:try> element traps all exception which appears while processing the <p:group> elements content. If an exception appears the <p:catch> gets the control to continue the processing. <p:try>/<p:group>/<p:catch> communicates only via the ports of the <p:try> element with the external realm.

Implementation of Steps

<p:XSLT>

The <XSLT> step should be implemented in accordance with the specification.

The step receives the document, which is to treat via the input port and provides the transformation result at the output port.

<p:XInclude>

The <XInclude> step should be implemented in accordance with the specification.

The step receives the document, which is to treat via the input port and provides the transformation result at the output port.

<p:Load>

The <Load> step should be implemented in accordance with the specification.

The step loads an XML document from somewhere accessed via the URI expressed in the href attribute and provides this document at the result port. The URI might also reference to an database server or any other service, which is able to return XML documents. (yax will provide a (experimental?) data source interface in one of the next releases.)

<p:Store>

The <Store> step should be implemented in accordance with the specification.

The step store the content of a context to somewhere accessed via the URI expressed in the href attribute. The URI might also reference to an database server or any other service, which is able to return XML documents. (yax will provide a (experimental?) data source interface in one of the next releases.)


yax currently provides a command line interface (see Quickstart and Reference). Other interfaces will follow in short.

All language components will be implemented step by step. Currently the most important components

are usable. The other components still exist but have got an interims implementation, which passes a document through the pipeline process without treating it in the specification conformant way. Such an interims implementation is indicated by a warning message. You can omit the output of these messages by setting the preference standardImplementationWarnings to "no".

The interims implementation of language constructs resp. containers (controlling parts like choose, try/catch, etc.) acts like the pipeline construct. It passes the treated document to the contained components, receives the result and provides it for further treatment.

The interims implementation of steps (active pipeline parst, which treat the documents like XInclude, XSLT, etc.), acts like the Identity step. It receives the treated document and provides it for further treatment without doing something by its own.

The first releases of yax will be published continuously in short intervals with the hope of vital feedback.


The following packages have to be available (installed) on an arbitrary location:

Table 3.  Required Packages

Package

Usage

Java (Version 5 or above)

Since Version 1.4 Java contains a default transformation processor (XSLTC). This processor will be used if no other processors are visible (in the classpath). yax assumes the presence of this processor. So at least Java 1.4 is necessary for using yax. As yas is developed under Java 5 it is the recommended Java version.

Ant(Version 1.7.0 or above)

yax comes with an ant task, so you can use yax also under ant. An ant installation is only needed if you want to use the yax ant task.

Log4j(Version 1.2.14 or above)

log4j is the recommended logging system. If log4j is not installed (resp. not reachable) yax uses its own ConsoleLogger. If you yax only under ant from yax perspective a log4j installation is not necessary because all log messages will be redirected to the ant logger.

Saxon(xls1: Version 6.5.3 or above, xls2: Version 8.6. or above)

yax provides the usage of different XSL processors. The saxon processors builds the preferred test environment for the yax development. (Obviously you can use any xsl processor which is reachable vie JAXP). The preferences file still includes the Saxon processors. If you want to use it follow Saxonias instruction how to obtain and install them. If no xsl processor is installed yax uses the system default transformer which comes with JRE (XSLTC).

Xalan /(XSLTC)(Version 2.7.0 or above)

yax provides the usage of different XSL processors. Xalan comes from Apache. The preferences file still includes the Xalan and the XSLTC processor. If you want to use them follow Apaches instruction how to obtain and install them. If no xsl processor is installed yax uses the system default transformer which comes with JRE (XSLTC).

Graphviz - Graph Visualization Software

yax provides the graphical visualisation of a pipeline in two ways. The port trace depicts the flow of the input(s) by drawing the expected usage of the components ports. The pipeline trace is a more compressed mode of the same matter.

For these features yax generates dot scripts and executes dot.exe of Graphviz to generate the pictures of the graphs.

If you would like to use these features dot.exe must be installed and reachable (via system path).


Download yax from http://yax.sourceforge.net and unzip the file to an arbitrary <yax-installation-directory>.


<yax-installation-directory>/lib
|
+--- lib
     |
     +--- yax-<n.m>.jar (<n.m> = Version Number)
         

yax preferred logging system is log4j. yax comes with a log4j configuration containing a console appender and a rolling file appender which writes a log file each day.

To simplify the beginning the recent Log4j library comes with yax. You can find the library in YAX_HOME/lib.

In the root of YAX_HOME you can find the two bat-files 'runExample1.console.bat' and 'runExample1.log4j.bat. The two batches demonstrates who to use and how to avoid using log4j. Wether yax uses log4j or not depends simply on the fact whether yax finds log4j on the classpath or not.

While yax runs in ant mode yax redirects all log messages to ant's logger and all other log configuraiton take no effect.

An XML catalog maps (usually remote) URIs to other (usually local) URIs.

yax uses Norman Walsh's resolver. You can configure the resolver - especially the link to your catalog file - by editing the config/CatalogManager.properties file. How to configure the the resolver is explained in an excellent manner on the resolver's site

For your confinience the yax distribution contains the recent resolver library (lib/resolver.jar). If you want to use the xml catalog feature the config directory and the resolver.jar have to be part of your the classpath. Start yax with the '-noCatalog' option If you want to suppress the xml catalog usage.

At the present time the property reference mechanism known from http://ant.apache.org/manual/index.html is implemented.

You can use parameter references with the form ${<parameter name>} within href attribute (or parameter). This reference will be replaced by the value of parameter with the same name passed either by property file or by start parameter ('-D<parameter name>').

With a combination of start parameter and parameter references within the xproc script you can build your scripts in a more flexible way. Example:

# java -classpath lib/yax-0.7.jar 
       net.sf.yax.Yax 
       -Dexample.dir=examples 
       -Dtest.dir=test 
       -DoutputFilename=output1.xml 
       example1.xproc
            
<xproc:pipeline name="pipe1" 
    xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
    xmlns:yax="http://opsdesign.eu/yax/1.0">
    <xproc:step name="Load1" type="xproc:Load" href="${examples.dir}/${inputFilename}"/>
    <xproc:step name="Store1" type="xproc:Store" href="${test.dir}/${outputFilename}"/>
</xproc:pipeline>
            

All I/O effects by start parameters (or other interface input) is called outer I/O.

Passing only input file location start parameter The most simple variant of an outer I/O is to use an input location parameter beside the mandatory xproc script location parameter:

java -classpath lib/yax-0.8.jar net.sf.yax.Yax examples/example1.xproc examples/example1.xml
              

yax completes the necessary information based on the input location. Assuming you pass the input file

path/to/input/resource/inputname.xml                   
              

derived from that input location yax generates the output location:

path/to/input/resource/inputname.output.xml                   
              

Passing input and output file location start parameter The straight forward way of outer I/O is to pass an input location parameter and a corresponding output location parameter:

java -classpath lib/yax-0.8.jar net.sf.yax.Yax examples/example1.xproc 
input/inputname.xml
output/outputname.xml
              

In that case the processing is obvious. yax takes the input document, passes it through the pipeline and writes the result to the ouput document.

Applying the XProc script on multiple input documents. yax can also process multiple input documents in one run. For applying this feature it is recommended to use ant because in ant you can use the full flexibility of the fileset feature. Example:

...
  <target 
    name="pipeline1"
    description="uses different multiple input files"
    >
    <yax 
      verbose="yes"
      script="test/pipeline00.xproc"
      outDir="test"
      outPattern="${inputName}.out.${inputExtension}"
      >
      
      <fileset 
        dir="examples" 
        includes="
        example*.xml
        " 
        excludes="
        example2.xml
        " 
      />
      
    </yax>
  </target>
...              
              

Alltough you can you this feature in commmandline mode. You pass a colon separated input file list with the -inList parameter:

java -classpath lib/yax-0.8.jar net.sf.yax.Yax examples/example1.xproc 
-inList={input/inputname1.xml;input/inputname1.xml}
outDir=test outPattern="${inputName}.out.${inputExtension}
              

In case of processing multiple input documents it is not possible (or better makes no sense) to pass an output location for each input document. Therefore yax provides to other parameter for determining the output location(s).

With -outDir you can choose an arbitrary output directory>. If you this parameter as the only output parameter the processed documents will be written to the output directory with its input filename.

The other parameter is the -outPattern parameter. With -outPattern you describes the pattern for building the output file name. Example:

Assuming you are using the pattern:

outPattern="${inputName}.out.${inputExtension}              
              

and you are processing the input files example1.xml and example3.xml by using ant's fileset

...
<fileset 
  dir="examples" 
  includes="
  example*.xml
  " 
  excludes="
  example2.xml
  " 
/>
...              
              

yax will created the two file:

...
 examples
 |
 +-- example1.out.xml
     example2.out.xml
       
              

If you combine this parameter with the -outDir parameter determining the 'test' directory as output directory:

...

outDir="test"
outPattern="${inputName}.out.${inputExtension}"

...              
              

yax writes the two files to the 'test' directory:

...

 test

 |
 +-- example1.out.xml
     example2.out.xml
              

Beside the outer I/O which is effected by the usage of start parameters you can use the steps p:Load and p:Store to read resp. write xml documents during the pipeline process.

Although they are alternative instruments outer I/O and inner I/O they work simultaniously. If you process for example a pipeline which includes inner I/O without any output start parameter:

...              
<target 
  name="runExample5.1"
  description="uses inner and outer I/O"
  >
  <yax 
    script="examples/example5.xproc"
    >
    ...  
  </yax>
</target>
...
              

You will get two times the same output in different files:

...
INFO [Load:Load1] Reading input file '...\examples\xincludeArticle.xml' into Context '2'.
...
INFO [Store:Store1] Writing output file '...\test\example5.output.cmd.xml' from Context '2'.
...
INFO [root:yax.root] Writing output file '...\yaxOutput.xml' from Context '2'.
...
              

This is triggered by a)p:Store step and b) the automatic ouput determination of the root element. The following graphic shows this circumstance:


The p:Store step creates a side branch but yax ports the content through the hole pipeline to the root container which is manages the outer I/O.

To avoid such undesired output behaviour (assuming in this case the outer output is undesired) you can use the -noOutputfile parameter:

...              
<target 
  name="runExample5.2"
  description="uses only inner I/O"
  >
  <yax 
    noOutputfile="yes" 
    script="examples/example5.xproc"
    >
    ...  
  </yax>
</target>
...
              

In this case the content on the output port of root will be discarded.

On the command line change to the <yax-installation-directory> and start yax with:

# java -classpath lib/yax-0.7.jar net.sf.yax.Yax [options]pipeline file location [XML input data file location  [XML output data file location]]
            

If all works well you will get a set of messages like the following. Which transformation processor appears in the messages depends on your actual environment configuration.


element 'yax:transformers' has ...something about transformer preference
... 
step 'step name': something about transformer which will be used
...
messages from each step
... 
Yax run sucessful completed.

            

If you start yax with the option -h or without any start parameter you will get a message about the usage alternatives like:


Usage: java yax [options] pipelineURI [inputfileURI [outputfileURI]]

Options: 

-h, -help              print this message (and exit)
-version               print version information (and exit)
-quiet, -q             be extra quiet
-verbose, -v           be extra verbose (quiet takes precedence)
-debug, -d             print debugging information
-baseURI=<value>       set the baseURI to value
-noOutputfile          suppress generation of an outputfile (overrides all other output parameters)
                       (make sense if output is created within the pipeline)
-D<property>=<value>   provide property for using within the xproc script as '${property}'
-propertyfile <name>   load properties from file (-D<property>s take precedence)

(for further usage alternatives see http://yax.sourceforge.net/)

            

This run generates several output file within the pipeline file directory and within the XML input data file directory:

the usage of the yax ant task is designed with the XSLT task in mind. if you are familiar with the XSLT task you will find some similarities. For the determination of single input and output files the attributes in and out are used. The attributes which holds the script file location is called in the XSLT task style. The corresponding attribute in yax is called script.

As the XSLT task do not provide multiple input (and output) yax provides an own solution using ant's well known fileset feature in collaboration with the outDir and/or outPattern attributes.

Corresponding to the XSLT task yax also provides passing parameters to the pipeline processor and the used subsystems (as transformers). While these parameters are not exclusively passed for the usage in transformers to yax the different name 'property' was used. But these 'properties' will also be passed as parameters to the transformers.

If you intend to use other xslt processors than the system defualt processor please consider that all necessary libraries must be assigned to the classpath BEFORE starting ant. Passing the transformer libraries via ant's classpath features (either within taskdef or with classpathref attribute) do not work.

...
<target 
  name="runExample1"
  description="transforms an input file with concatenated transformation steps"
  >
  <yax 
    in="examples/example1.xml"
    out="test/example1.output.ant.xml"
    script="examples/example1.xproc"  
    >
  </yax>
</target>
...
              

The <pipeline filename>.config.xml contains the pipeline with all implicit ports and resulting connections between the ports and all used pipeline-library (the actual implementation is handled as serveral libraries):

               
<yax:configuration xmlns:yax="http://www.opsdesign.eu/yax/1.0">
<!--configuration description generated by Yax - Do not edit by hand-->
<pipeline name="pipe1">
..
<step name="trans1">
<output port="out" sequence="no" yax:creator="implementation.xproc.standard"/>
<input port="in" sequence="no" yax:creator="implementation.xproc.standard">
<yax:connection port="in" yax:component="pipe1"/>
</input>
<input port="stylesheet" sequence="no" yax:creator="implementation.xproc.standard"/>
<input href="examples/transformation1.xsl" port="stylesheet" yax:creator="pipeline"/>
</step>
...
</pipeline>
<xproc:pipeline-library name="xproc.options" xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0">
<xproc:declare-step-type type="Rename" yax:description="">
<xproc:output port="out" select="" sequence="no" yax:bySourceRequired="no"/>
<xproc:input port="in" select="" sequence="no" yax:bySourceRequired="no"/>
<xproc:parameter name="name" required="yes" yax:values="{$any}"/>
<xproc:parameter name="select" required="yes" yax:values="{$xpathExpression}"/>
</xproc:declare-step-type>
...
</xproc:pipeline-library>
<xproc:pipeline-library name="xproc.standard" xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0">
...
</xproc:pipeline-library>
<xproc:pipeline-library name="yax.standard" xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0">
...
</xproc:pipeline-library>
</yax:configuration>
               
            

The <p:pipeline> construct is a container for steps and other construct.

<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
   </xproc:step>
   <xproc:step name="validate1" type="xproc:Validate"/> 
   <xproc:step name="trans2" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
   </xproc:step>
   <xproc:step name="trans3" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
   </xproc:step>
   <xproc:step name="validate2" type="xproc:Validate"/> 
</xproc:pipeline>
           

The most simple pipeline is an empty pipeline:

<xproc:pipeline name="pipe1" 
    xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
    xmlns:yax="http://opsdesign.eu/yax/1.0">
</xproc:pipeline>
            
            

When you run such an empty pipeline you get a message that the pipeline will be bridged. In that case the pipeline construct has the same behaviour as the identity step.

            
...
Construct 'pipe1' is empty and will be bridged.
...
            
            

pipelines can contain nested components in an arbitrary (??) depth:

            
<xproc:pipeline name="pipe1" 
    xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
    xmlns:yax="http://opsdesign.eu/yax/1.0">
    <xproc:pipeline name="pipe1.1">
        <xproc:step name="step1" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="examples/transformation1.xsl"/>
        </xproc:step>
        <xproc:pipeline name="pipe1.1.1">
            <xproc:step name="step1" type="xproc:XSLT">
                <xproc:input port="stylesheet" href="examples/transformation2.xsl"/>
            </xproc:step>
            <xproc:pipeline name="pipe1.1.1.1">
                <xproc:step name="step1" type="xproc:XSLT">
                    <xproc:input port="stylesheet" href="examples/transformation3.xsl"/>
                </xproc:step>
            </xproc:pipeline>
        </xproc:pipeline>
    </xproc:pipeline>
</xproc:pipeline>
            
            
            

The usual form of the xproc:XSLT step consists of the <xproc:step> element itself which contains an <input> port element. This port refers to the stylesheet port.

               
<xproc:step name="trans1" type="xproc:XSLT">
   <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
</xproc:step>
               
            

This step uses the default transformer determined by the mechanism described below in this chapter. If you would like to use a particular transformer for a step, you can place a parameters:

               
<xproc:step name="trans1" type="xproc:XSLT">
  <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
               <xproc:parameter name="transformer" value="Saxon8"/>
</xproc:step>
               
            

Currently only the href reference to the source is supported.


The step receives the document, which is to treat via the input port and provides the result of the transformation at the output port.

It determins the processor according the following mechanism:

Determination of the appropriate transformation processor

There are three ways to determine the processor. The ways overrides the effects of their ancestors in the sequence of its appearance. (The numbers 1) and 2) are part of the processor selection mechanism of JAXP. For further information concerning this mechanism please refer to Suns JAXP documentation. The numbers 3 to 5) all uses the system property mechanism).

<p:Load> loads an XML Document from an external data source. <p:Load> references the source via an URI which is placed either in an href attribute or (as requested from the specification) parameter with the name href.

               
...
<xproc:step name="Load1" type="xproc:Load" href="examples/example1.xml"/> 
...
               
            

In comparision to other steps at <p:Load> the input port is replaced by an external content source. The consequence is a break of the pipeline chain at this point. That means that the content at the result port of the preceding component of of the <p:Load> step will be discarded except other components refer to it explicitly.

<p:Load> can be used to replace the initial content load via the input file start paramter. So with <p:Load> you can place the reference to input data into the pipeline and can access yax with a single reference to location of the pipeline document.

# java -classpath lib/yax-0.7.jar net.sf.yax.Yax [options]pipeline file location
            

you can use parameter references with the form ${<parameter name>} within href attribute (or parameter). This reference will be replaced by the value of parameter with the same name passed either by property file or by start parameter ('-D<parameter name>').

With a combination of start parameter and parameter references within the xproc script you can build your scripts in a more flexible way. Example:

# java -classpath lib/yax-0.7.jar 
       net.sf.yax.Yax 
       -Dexample.dir=examples 
       -Dtest.dir=test 
       -DoutputFilename=output1.xml 
       example1.xproc
            
<xproc:pipeline name="pipe1" 
    xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
    xmlns:yax="http://opsdesign.eu/yax/1.0">
    <xproc:step name="Load1" type="xproc:Load" href="${examples.dir}/${inputFilename}"/>
    <xproc:step name="Store1" type="xproc:Store" href="${test.dir}/${outputFilename}"/>
</xproc:pipeline>
            

<p:Store> stores an XML Document at external data target location. <p:Store> references the target location via an URI which is placed either in an href attribute or (as requested from the specification) parameter with the name href.

               
...
<xproc:step name="Store1" type="xproc:Store" href="examples/output.xml"/> 
...
               
            

In comparision to other steps at <p:Load> the input port is replaced by an external content source. The consequence is a break of the pipeline chain at this point. That means that the content at the result port of the preceding component of of the <p:Load> step will be discarded except other components refer to it explicitly.

<p:Load> can be used to replace the initial content load via the input file start paramter. So with <p:Load> you can place the reference to input data into the pipeline and can access yax with a single reference to location of the pipeline document.

# java -classpath lib/yax-0.7.jar net.sf.yax.Yax [options]pipeline file location
            

you can use parameter references with the form ${<parameter name>} within href attribute (or parameter). This reference will be replaced by the value of parameter with the same name passed either by property file or by start parameter ('-D<parameter name>').

With a combination of start parameter and parameter references within the xproc script you can build your scripts in a more flexible way. Example:

# java -classpath lib/yax-0.7.jar 
       net.sf.yax.Yax 
       -Dexample.dir=examples 
       -Dtest.dir=test 
       -DoutputFilename=output1.xml 
       example1.xproc
            
<xproc:pipeline name="pipe1" 
    xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
    xmlns:yax="http://opsdesign.eu/yax/1.0">
    <xproc:step name="Load1" type="xproc:Load" href="${examples.dir}/${inputFilename}"/>
    <xproc:step name="Store1" type="xproc:Store" href="${test.dir}/${outputFilename}"/>
</xproc:pipeline>
            

The usual case using a choose/when/otherwise construct will be that you define only one reference source (at the choose element) and applies the test clause of all <when> elements on it:

               
<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
   </xproc:step>
   <xproc:choose name="choose1" type="xproc:XSLT">
      <xproc:input port="ref" href="test/chooseInput0.xml"/>
      <xproc:when name="when1" test="/test1">
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>
      </xproc:when>
      <xproc:when name="when2" test="/test2">
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>            
      </xproc:when>
      <xproc:otherwise name="otherwise">
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>
      </xproc:otherwise>
   </xproc:choose>
   <xproc:step name="trans3" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
   </xproc:step>
</xproc:pipeline>
                                             
            


               
            

Also it is possible to define a reference source for each when clause:

               
<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
   </xproc:step>
   <xproc:choose name="choose1" type="xproc:XSLT">
      <xproc:when name="when1" test="/test1">
         <xproc:input port="ref" href="test/chooseInput1.xml"/>
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>
      </xproc:when>
      <xproc:when name="when2" test="/test2">
         <xproc:input port="ref" href="test/chooseInput2.xml"/>
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>            
      </xproc:when>
      <xproc:otherwise name="otherwise">
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>
      </xproc:otherwise>
   </xproc:choose>
   <xproc:step name="trans3" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
   </xproc:step>
</xproc:pipeline>
                                             
            

If you do not define at least one reference port:

               
<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT">
   </xproc:step>
   <xproc:choose name="choose1" type="xproc:XSLT">
      <xproc:input port="ref" href="test/chooseInput0.xml"/>
      <xproc:when name="when1" test="/test1">
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>
      </xproc:when>
      <xproc:when name="when2" test="/test2">
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>            
      </xproc:when>
      <xproc:otherwise name="otherwise">
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>
      </xproc:otherwise>
   </xproc:choose>
   <xproc:step name="trans3" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
   </xproc:step>
</xproc:pipeline>
                                             
            

triggers an error message at the first when element:


construct 'when1': reference port not found.
               
            

You can also equip all elements of the choose/when/otherwise construct simultaniously with a reference port. In that case the reference port of the choose element triggers the generation of an implicit reference port at each when element. But the implicit reference ports take no effect because explicit ports always have priority. They regain effect when the explicit ports will be (also partitially) erased.

               
<xproc:pipeline name="pipe1" 
   xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
   xmlns:yax="http://opsdesign.eu/yax/1.0">
   <xproc:step name="trans1" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation1.xsl"/> 
   </xproc:step>
   <xproc:choose name="choose1" type="xproc:XSLT">
      <xproc:input port="ref" href="test/chooseInput0.xml"/>
      <xproc:when name="when1" test="/test1">
         <xproc:input port="ref" href="test/chooseInput1.xml"/>
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>
      </xproc:when>
      <xproc:when name="when2" test="/test2">
         <xproc:input port="ref" href="test/chooseInput2.xml"/>
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>            
      </xproc:when>
      <xproc:otherwise name="otherwise">
         <xproc:step name="trans2" type="xproc:XSLT">
            <xproc:input port="stylesheet" href="test/transformation2.xsl"/> 
         </xproc:step>
      </xproc:otherwise>
   </xproc:choose>
   <xproc:step name="trans3" type="xproc:XSLT">
      <xproc:input port="stylesheet" href="test/transformation3.xsl"/> 
   </xproc:step>
</xproc:pipeline>
                                             
            



            

You can use the <p:try>/<p:catch> construct either with only a general catch clause:


<xproc:pipeline name="pipe1" 
    xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
    xmlns:yax="http://opsdesign.eu/yax/1.0">
    <xproc:try name="try1">
        <xproc:group name="group1">
            <xproc:step name="group1step1" type="xproc:XSLT">
                <xproc:input port="stylesheet" href="examples/transformation2.xsl"/>
            </xproc:step>
        </xproc:group>
        <xproc:catch name="catch">
            <xproc:step name="catchstep2" type="xproc:XSLT">
                <xproc:input port="stylesheet" href="examples/transformation1.xsl"/>
            </xproc:step>
        </xproc:catch>
    </xproc:try>
</xproc:pipeline>
                                             
                  

or more sophiticated with additional differenciating catch clauses:


<xproc:pipeline name="pipe1" 
    xmlns:xproc="http://www.w3.org/TR/2006/xproc/1.0"
    xmlns:yax="http://opsdesign.eu/yax/1.0">
    <xproc:try name="try1">
        <xproc:group name="group1">
            <xproc:step name="group1step1" type="xproc:XSLT">
                <xproc:input port="stylesheet" href="examples/transformation2.xsl"/>
            </xproc:step>
        </xproc:group>
        <xproc:catch name="catch1" exception="EmptyResult">
            <xproc:step name="catch1step2" type="xproc:XSLT">
                <xproc:input port="stylesheet" href="examples/transformation1.xsl"/>
            </xproc:step>
        </xproc:catch>
        <xproc:catch name="catch2" exception="FileNotFound">
            <xproc:step name="catch2step2" type="xproc:XSLT">
                <xproc:input port="stylesheet" href="examples/transformation1.xsl"/>
            </xproc:step>
        </xproc:catch>
        <xproc:catch name="catch">
            <xproc:step name="catchstep2" type="xproc:XSLT">
                <xproc:input port="stylesheet" href="examples/transformation1.xsl"/>
            </xproc:step>
        </xproc:catch>
    </xproc:try>
</xproc:pipeline>
                                             
                  

How ever, each <p:try>/<p:catch> construct has to contain at least the general catch clause.

Description ToDo

This is an example with real data coming from the docbook.sml project. It collects all sections distributed over several files into the output file. Start yax with:

# java -classpath lib/yax-0.7.jar 
       net.sf.yax.Yax 
       -Dparam1=passedFromProgramStart 
       example7.xproc
       examples/xincludeArticle.xml
       test/output1.xml
         

Description ToDo

Software and documentation is released under the terms of the GNU LGPL license (see http://www.gnu.org/copyleft/lesser.html) and comes without a warranty of any kind.

Copyright © 2006 - 2008 joerg.moebius@opsdesign.de

sourceforge logo

sourceforge logo

sourceforge logo

sourceforge logo