XML Streams Module User’s Guide : Chapter 6 XSLT Transformations : Creating the Objects and Streams
Creating the Objects and Streams
This section describes how to create objects and streams.
Defining a Transformation Object
This example creates a simple transformation object class and then uses the class in the creation of a new transformation object stream.
To insert a transformation into the object stream, use constructors and the corresponding make() functions in the example classes RWXsltObjectInputStreamImp and RWXsltObjectOutputStreamImp.
Each of these classes takes as an additional parameter an ifstream reference to an XSLT stylesheet. But first you need to define a transformation object.
If using Xalan, the transformation object looks like this.
 
#include <iostream.h>
#include <Include/PlatformDefinitions.hpp> // 1
#include <util/PlatformUtils.hpp>
#include <XalanTransformer/XalanTransformer.hpp>
 
 
template <class T>
class RWTXsltTransform
{
public:
RWTXsltTransform(std::basic_istream
<T,std::char_traits<T> >& script) // 2
: script_(script)
{}
 
void transform(std::basic_istream<T,std::char_traits<T> >& in,
std::basic_ostream<T,std::char_traits<T> >& out)
// 3
{
XalanTransformer transformer; // 4
 
try {
transformer.transform(&in,&script_,&out); // 5
}
catch(...)
{
throw RWExternalStreamException("RWTXsltTransform::transform():
Transform failed.",RWExternalStreamException::
invalidParameter);
}
private:
std::basic_istream<T,std::char_traits<T> >& script_; // 6
};
//1 Include the Xalan header files. If you are using another XSLT processor, your includes will be different.
//2 The constructor for the Xalan transformation object takes a stream reference from which the XSLT script can be read. This reference is stored in a member variable (To use a different XSLT processor you'll need to change this line).
//3 The transform() method of the transformation object takes an input stream and an output stream. The source document will be read from the input and the transformed document written to the output.
//4 Within the transform() method, you first create a Xalan transformation object, then
//5 Call the Xalan transformation object using the source document stream, the output document stream and the saved XSLT script stream. (To use an XSLT processor other than Xalan you'll also need to change these lines.)
//6 The member variable for holding the reference to the XSLT script.
This code can be found in buildspace\examples\xmlstreams\xsltTransform\RWTXsltTransform.h and buildspace\examples\xmlstreams\xsltTransform\RWTXsltTransform.ccp.
NOTE >> In order to support an XSLT processor other than Xalan, you need to change the lines identified by comments 1, 2, 4 and 5 above. The rest of the code in this example should be the same.
Defining a Character Transformation Stream
Next, define character transformation streams to go with this transform object.
These input and an output streams will be used to create your XSLT transformation stream.
Create the input stream.
typedef RWTTransformInputStreamImp<RWCharInputStream,
RWFilteredCharInputStreamImp,RWTXsltTransform<char> >
RWXsltCharInputStreamImp;
Create the output stream.
typedef
RWTTransformOutputStreamImp<RWCharOutputStream,
RWFilteredCharOutputStreamImp, RWTXsltTransform<char> >
RWXsltCharOutputStreamImp;
Defining an XSLT Transformation Stream
Finally define the XSLT transformation stream using the transform object and the character transformation stream. You’ll define an input XSLT transformation stream and an output XSLT transformation stream.
Defining the XSLT Transformation Input Stream
This code can be found in buildspace\ examples\xmlstreams\xsltTransform\-XsltObjectInputStreamImp.h.
 
class RWXsltObjectInputStreamImp : public RWXmlObjectInputStreamImp
{
protected:
RWXsltObjectInputStreamImp(std::istream& istr,
RWTXsltTransform<char> transformer,
bool escape) // 1
:
RWXmlObjectInputStreamImp(RWIstreamDataFromCharInputStreamImp::make(
RWXsltCharInputStreamImp::make(
RWCharFromStreambufInputStreamImp::make(
*(istr.rdbuf())),transformer)),escape) // 2
{;}
 
public:
static RWObjectInputStream make(std::istream& source,
std::istream& script, bool escape = true) // 3
{
return RWObjectInputStream(new
RWXsltObjectInputStreamImp(source,
RWTXsltTransform<char>(script,escape));
}
};
 
//1 The constructor for the transformation stream takes an input stream for the XML document to transform, a transformation object, and a flag to indicate whether or not the output should be escaped.
//2 Here you initialize the base class using the char transformation stream defined by the typedef above. Note that you
first create a character input stream,
then use that to create the Xalan transformation char input stream,
then use the Xalan char stream to create an Istream input stream,
and finally use that stream to create the base RWXmlObjectInputStreamImp. This is an example of chaining together streaming elements to create a new stream with specific functionality (in this case the ability to transform an XML document using XSLT).
//3 The static make() function produces an object stream handle by creating a Xalan transformation stream. Here you construct a transformation object and pass it to the constructor for the Xalan transformation stream.
Defining the XSLT Transformation Output Stream
Define the output stream in the same way.
This code can be found in buildspace\examples\xmlstreams\xsltTransform\RWXsltObjectOutputStreamImp.h.
 
class RWXsltObjectOutputStreamImp : public RWXmlObjectOutputStreamImp
{
protected:
 
RWXsltObjectOutputStreamImp(std::ostream& ostr,
RWTXsltTransform<char> transformer,
const RWCString& rootElementType,
bool escape)
:
RWXmlObjectOutputStreamImp(RWOstreamDataToCharOutputStreamImp::make(
RWXsltCharOutputStreamImp::make(
RWCharToStreambufOutputStreamImp::make(*(ostr.rdbuf())),
transformer)), rootElementType,escape)
{;}
 
public:
 
static RWObjectOutputStream make(std::ostream& sink,
std::istream& script,
const RWCString& rootElementType=nestedObjectTag,
bool escape = true)
{
return RWObjectOutputStream(new
RWXsltObjectOutputStreamImp(sink,
RWTXsltTransform<char>(script),
rootElementType,escape));
}
};
You now have everything you need to apply XSLT transformations to the XML input or output using the Xalan XSLT engine.
The next section describes how to use these objects to perform an actual transformation.