http://xml.apache.org/http://www.apache.org/http://www.w3.org/

Overview

Downloads
Getting Started

FAQs

Sample Apps
Command Line
Usage Patterns

C++ API

Extensions

Release Notes

Bug reporting

Introduction
 

Xalan-C++ takes as primary input an XML source document and an XSL stylesheet, both represented by instances of XSLTInputSource. These input objects may each take the form of a file or URL, a stream, or a DOM tree. The stylesheet may also take the form of a compiled stylesheet (an instance of StylesheetRoot.

NoteIf the XML source document contains a stylesheet Processing Instruction (PI), Xalan-C++ uses the stylesheet this PI points to and a separate stylesheet object is not required.

Xalan-C++ uses Xerces-C++ to parse text input, performs the transformation, and sends the output to an instance of XSLTResultTarget, which may be configured to write to a file, a stream, or a DOM tree.

For detailed API documentation, see Xalan-C++ API. For an overview of the command-line utility, see Command-Line Utility.


Basic procedure for performing an XSL transformation
 

When you are setting up your application to use XSL stylesheets to transform XML documents, you must do the following:

1. Include the required header files
 

Along with any required Xalan-C++ and other header files, include utils/PlatformUtils.hpp from the Xerces-C++ distribution.


2. Initialize Xalan and Xerces
 

Use the static initializers to initialize the Xalan-C++ and Xerces-C++ platforms. You only need to do this once per session.

XMLPlatformUtils::Initialize();
XSLTEngineImpl::Initialize();

3. Set up an XSLT processor with its support objects
 

The XSLT processor interacts with several support objects that you must set up before you can perform transformations.

// Create the support objects.
DOMSupportDefault          theDOMSupport;
XercesParserLiaison        theParserLiaison(theDOMSupport);
XPathSupportDefault        theXPathSupport(theDOMSupport);
XSLTProcessorEnvSupportDefault  theXSLTProcessorEnvSupport;
XObjectFactoryDefault      theXObjectFactory(theXSLTProcessorEnvSupport, 
                                             theXPathSupport);
XPathFactoryDefault        theXPathFactory;

// Create the processor.
XSLTEngineImpl  theProcessor(
          theParserLiaison,
          theXPathSupport,
          theXSLTProcessorEnvSupport,
          theXObjectFactory,
          theXPathFactory);

// Connect the processor to the environment support object.
theXSLTProcessorEnvSupport.setProcessor(&theProcessor);

4. Create context objects for the stylesheet
 

Use the processor and support objects to set up stylesheet construction context and execution context objects.

StylesheetConstructionContextDefault  theConstructionContext(
            theProcessor,
            theXSLTProcessorEnvSupport,
            theXObjectFactory,
            theXPathFactory);
StylesheetExecutionContextDefault      theExecutionContext(
            theProcessor,
            theXSLTProcessorEnvSupport,
            theXPathSupport,
            theXObjectFactory);

5. Set up input and output objects for a transformation
 

You must set up XSLTInputSource objects for the XML document and XSL stylesheet, and an XSLTResultTarget object to contain the transformation output.

Each of these objects may take the form of a file or URL, a stream, or a DOM tree. In the following fragment, the input and output are files:

// Use XalanDOMString to create a Unicode file name.
// The files are in the same directory as the application executable.
const XalanDOMString    theXMLFileName("foo.xml");
const XalanDOMString    theXSLFileName("foo.xsl");

// Create XSLTInputSource objects.
XSLTInputSource    theInputSource(c_wstr(theXMLFileName));
XSLTInputSource    theStylesheetSource(c_wstr(theXSLFileName));

// For the output, create an XSLTResultTarget object.
TextFileOutputStream  theOutputStream("foo.out");
XercesDOMPrintWriter  theResultWriter(theOutputStream);
XSLTResultTarget    theResultTarget(&theResultWriter);

For the other constructors you can use to set up input and output objects (with input and output streams, for example), see XSLTInputSource and XSLTResultTarget. See also Working with DOM input and output.


6. Perform the transformation
 

Use the XSLTEngineImpl process() method to perform the transformation.

theProcessor.process(
               theInputSource,
               theStylesheetSource,
               theResultTarget,
               theConstructionContext,
               theExecutionContext);

The XSLTResultTarget object receives the transformation output.

XSLTEngineImpl stores running state information, so it is not thread-safe. To perform multiple transformations, create a new instance for each transformation, or call the XSLTProcessor reset() method between each transformation.

If you are using the same stylesheet to perform multiple transformations, for efficiency you should compile the stylesheet and use the appropriate XSLTEngineImpl process() method. Compiled stylesheet (StylesheetRoot) objects are also thread-safe. A single StylesheetRoot object may be called concurrently from multiple threads. For more information, see Compiling stylesheets.

For a sample application that performs a transformation, see SimpleTransform.



Working with DOM input and output
 

You can set up an XSLTResultTarget to produce a DOM when you perform a transformation. You can also use a DOM as input for a transformation, either the DOM output of another transformation, or a DOM produced by the Xerces DOMParser.

The following code fragments illustrate the procedures for working with DOM input and output:


// Use the Xerces DOM parser to create a DOM_Document.
#include <parsers/DOMParser.hpp>
#include <dom/DOM_Node.hpp>

DOMParser  theParser;
theParser.parse("foo.xml");
const DOM_Document theDOM = theParser.getDocument();

// Set up a XercesParserLiaison and use it to wrap the DOM_Document
// in a XalanDocument.
DOMSupportDefault   theDOMSupport;
XercesParserLiaison	theParserLiaison(theDOMSupport);
XalanDocument* theDoc = theParserLiaison.createDocument(theDOM);

// Use the XalanDocument to create an XSLTInputSource object, which
// you can then use in a transformation.
XSLTInputSource		theInputSource(theDoc);
...
// If you want to produce DOM output, create an empty XalanDocument
// to contain the transformation output.
XalanDocument* docOut = theParserLiaison.createDocument();
XSLTResultTarget theDOMResultTarget(docOut);
...
// After you perform the transformation, the XalanDocument contains
// the output.
// You can also convert the XalanDocument to a Xerces DOM_Document.
DOM_Document domOut = theParserLiaison.mapXercesDocument(docOut)

Setting stylesheet parameters
 

An XSL stylesheet can include parameters that are set at run time before a transformation takes place. When we generate the HTML documents that make up the Xalan doc set, for example, we send the stylesheet an id parameter along with each XML source document. The id identifies that document and enables the stylesheet to integrate it into the overall doc set.

To set a stylesheet parameter, use one of the XSLTEngineImpl setStylesheetParam() methods. Both methods take two arguments: the parameter name (a XalanDOMstring) and the expression (a XalanDOMString or an XObject). The XObject option is useful when you are working with the XPath API. For example, you could use the XObject returned by an Xpath function to set a stylesheet parameter.

NoteIf the expression is a string and you are using XalanDOMString for the input parameter, enclose it in single quotes to make it a string expression.

You can include the -param flag with two arguments when you call the command line utility. The first argument is the parameter name or key, and the second argument is the string expression (in single quotes). For example:

TestXSLT -in foo.xml -xsl foo.xsl -param param1 'boo'

If the string expression includes spaces, first enclose the string in single quotes so it is interpreted as a string expression, and then enclose the resulting string in double quotes so it is interpreted as a single argument. For example:

TestXSLT -in foo.xml -xsl foo.xsl -param param1 "'hello there'"

The UseStylesheetParam sample application also uses a command-line parameter.


Compiling stylesheets
 

When Xalan-C++ performs a transformation with the XSLTEngineImpl process() method used above, it starts by compiling the stylesheet into a binary representation. If you intend to use the same stylesheet to perform multiple transformations, you can enhance efficiency by explicitly compiling the stylesheet and using another XSLTEngimeImpl process() method for each transformation. A compiled stylesheet (a StylesheetRoot object) thread safe, so it even supports concurrent access by multiple clients. If, for example, you are setting up a server application to perform transformations, you can improve performance by compiling any stylesheets the application repeatedly uses.

A compiled stylesheet requires its own XPath and XObject factory support objects, independent of the support objects for an XSLT processor. So after you have set up the XSLT processor with its support objects, set up other factory support objects and use them to create a construction context for the stylesheet:

// Set up the XSLT processor with its support objects
DOMSupportDefault          theDOMSupport;
XercesParserLiaison        theParserLiaison(theDOMSupport);
XPathSupportDefault        theXPathSupport(theDOMSupport);
XSLTProcessorEnvSupportDefault  theXSLTProcessorEnvSupport;
XObjectFactoryDefault      theXObjectFactory(theXSLTProcessorEnvSupport, 
                                             theXPathSupport);
XPathFactoryDefault        theXPathFactory;

// Create the processor and connect to the
// environment support object.
XSLTEngineImpl  theProcessor(
          theParserLiaison,
          theXPathSupport,
          theXSLTProcessorEnvSupport,
          theXObjectFactory,
          theXPathFactory);
theXSLTProcessorEnvSupport.setProcessor(&theProcessor);
...
// Create factory support objects for the stylesheet, so it will
// have its own factory-created XObject and XPath instances 
// (separate from the XSLT processor XObject and XPath objects).
XObjectFactoryDefault      theStylesheetXObjectFactory(
            theXSLTProcessorEnvSupport,
            theXPathSupport);
 XPathFactoryDefault        theStylesheetXPathFactory;

 // Use these factory support objects to create a stylesheet 
 // construction context.
 StylesheetConstructionContextDefault  theConstructionContext(
            theProcessor,
            theXSLTProcessorEnvSupport,
            theStylesheetXObjectFactory,
            theStylesheetXPathFactory);

 // The execution context uses the same factory support objects as
 // the processor.
 StylesheetExecutionContextDefault    theExecutionContext(
            theProcessor,
            theXSLTProcessorEnvSupport,
            theXPathSupport,
            theXObjectFactory);

Compile the stylesheet, add the StylesheetRoot object to the execution context, and start performing transformations. Use the XSLTEngineImpl process() method (see below) that takes advantage of the compiled stylesheet. Be sure to reset the processer and execution context between each transformation. For example:

// Compile the stylesheet.
StylesheetRoot* const	theStylesheetRoot =
          theProcessor.processStylesheet(
                theStylesheetSource,
                theConstructionContext);

// Set the execution context object to use the compiled stylesheet.
theExecutionContext.setStylesheetRoot(theStylesheetRoot)

// Set up an XSLTInputSource object (theInputSource)
// and an XSLTResultTarget object (theResultTarget).
...
// Do the transformation. This version of the process() method uses
// the StylesheetRoot object associated with the execution context.
theProcessor.process(
         theInputSource,
         theResultTarget,
         theExecutionContext);

// Reset the processor and the execution context
// so we can perform the next transformation.
theProcessor.reset();
theExecutionContext.reset();
theExecutionContext.setStylesheetRoot(theStylesheetRoot);

// Perform the next transformation.
....

For an example, see the CompileStylesheet sample.


Working with XPath expressions
 

XSL stylesheets use XPath expressions to select nodes, specify conditions, and generate text for the result tree. XPath provides an API that you can call directly. For example, you may want to select nodes programmatically and do your own processing without a stylesheet.

For an example that executes XPath expressions against XML source files, see XPathWrapper.


Using TraceListener
 

TraceListener is a debugging abstract base class implemented by TraceListenerDefault. You can use TraceListener to trace any combination of the folllowing:

  • Calls to templates
  • Calls to template children
  • Selection events
  • Result tree generation events

To construct a TraceListener with TraceListenerDefault, you need a PrintWriter and a boolean for each of these four tracing options. You can then use the XSLTEngimeImpl setTraceSelects and addTraceListener methods to add the TraceListener to an XSLTProcessor. See the TraceListen sample application.

The command-line utility (TextXSLT) and TraceListen both use TraceListenerDefault to write events to the screen.



Copyright © 2000 The Apache Software Foundation. All Rights Reserved.