Transforming your XML Documents
This section describes how to transform your XML documents.
Overview of the Transformation Process
The following sections illustrate how to perform both character-based and element-based transformations, using an object book.
The steps included in this section include:
• adding serialization support (for more information, see
Chapter 3 )
• creating a book object and serializing it to a file using an XML stream that applies a transformation to make the resulting XML more readable
• reading the file back in and restoring the book object using an XML stream that applies a transformation to restore the original XML format
• printing out both the original XML streams data for the book object and its more readable, transformed version
Adding Serialization Support
The object book holds an author name and a book title.
First, you will instantiate book, and add serialization support. This process is identical for both transformations.
class book
{
public:
book ();
book (const RWCString& title, const RWCString& author);
private:
RWCString title_;
RWCString author_;
};
As described in the example in
Chapter 5 , you must add macros to the header and implementation files to prepare the object for serialization.
• To the header file, add the macro RW_DECLARE_VIRTUAL_STREAM_FNS(), which defines the streamContents() member function:
class book
{
RW_DECLARE_VIRTUAL_STREAM_FNS(book)
public:
book ();
book (const RWCString& title, const RWCString& author);
private:
RWCString title_;
RWCString author_;
};
Add to the header file:
// Add serialization support
RW_DECLARE_STREAMABLE_AS_SELF(book)
RW_DECLARE_STREAMABLE_POINTER(book)
• To the implementation file, first add macros that define insertion and extraction operators for the class members:
// Define how book will be serialized
RW_BEGIN_STREAM_CONTENTS(book)
RW_STREAM_ATTR_MEMBER(title,title_)
RW_STREAM_ATTR_MEMBER(author,author_)
RW_END_STREAM_CONTENTS
Then add macros that allow the book object itself to be serialized as a pointer reference:
// Allow a reference to a book to be serialized
RW_DEFINE_STREAMABLE_POINTER(book)
RW_DEFINE_STREAMABLE_AS_SELF(book)
Serializing the book Object to a File
Next, you serialize your book object out to a file. Because the XML format generated by XML streams is difficult to read, transform the output stream into a more readable format.
Each of the following sections considers first a character-based C++ transformation, followed by an element-based C++ transformation.
For a Character-based C++ Transformation
int main()
{
using std::ofstream; //1
using std::ifstream;
using std::cout;
using std::endl;
book book1("To Love and Be Wise","Josephine Tey"); //2
book book2;
MyInStreamTransform inTransform; //3
MyOutStreamTransform outTransform; //4
{
ofstream fout("book.xml"); //5
RWObjectOutputStream out = //6
RWTTransformObjectOutputStreamImp<MyOutStreamTransform>
::make(fout,outTransform);
out << book1; //7
out.flush(); //8
}
For an Element-based C++ Transformation
int main()
{
using std::ofstream; //1
using std::ifstream;
using std::cout;
using std::endl;
book book1("To Love and Be Wise","Josephine Tey"); //2
book book2;
MyInParsedTransform inTransform; //3
MyOutParsedTransform outTransform; //4
{
ofstream fout("book.xml"); //5
RWObjectOutputStream out = //6
RWTParsedObjectOutputStreamImp<MyOutParsedTransform>
::make(fout,outTransform);
out << book1; //7
out.flush(); //8
}
Restoring the book Object
At this point you have written the book object XML data to the file book.xml. Next you are ready to restore the object, which involves:
• reading in the file book.xml
• transforming the XML back to the form required by XML streams
• restoring the object as book2
For a Character-based C++ Transformation
{
ifstream fin("book.xml"); //1
RWObjectInputStream in = //2
RWTTransformObjectInputStreamImp<MyInStreamTransform>
::make(fin,inTransform);
in >> book2; //3
}
For an Element-based C++ Transformation
{
ifstream fin("book.xml"); //1
RWObjectInputStream in = //2
RWTParsedObjectInputStreamImp<MyInParsedTransform>
::make(fin,inTransform);
in >> book2; //3
}
Examining the XML Output
Finally, the example writes to standard out two forms of the serialized object:
• the transformed, more readable version
• the form created by the XML serialization and expected by XML streams when the object is restored
For a Character-based C++ Transformation
{
RWObjectOutputStream out = //1
RWTTransformObjectOutputStreamImp<MyOutStreamTransform>
::make(cout,outTransform);
out << book2; //2
}
cout << endl;
{
RWObjectOutputStream out = //3
RWXmlObjectOutputStreamImp::make(cout);
out << book2; //4
}
return 0;
}
Here is the resulting output:
With transformation:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <rw:nested_object rw:class="book"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:rw="http://www.roguewave.com/xmlstream">
<rw:member rw:name="title" xsi:type="xsd:string">To Love
and Be Wise</rw:member>
<rw:member rw:name="author" xsi:type="xsd:string">
Josephine Tey</rw:member></rw:nested_object>
Without transformation:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rw:nested_object rw:class="book"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:rw="http://www.roguewave.com/xmlstream">
<rw:member rw:name="title" xsi:type="xsd:string">To Love and Be
Wise</rw:member>
<rw:member rw:name="author" xsi:type="xsd:string">Josephine
Tey</rw:member></rw:nested_object>
For an Element-based C++ Transformation
{
RWObjectOutputStream out = //1
RWTParsedObjectOutputStreamImp<MyOutParsedTransform>
::make(cout,outTransform);
out << book2; //2
}
cout << endl;
{
RWObjectOutputStream out = //3
RWXmlObjectOutputStreamImp::make(cout);
out << book2; //4
}
return 0;
}
Here is the resulting output:
With transformation:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<book xmlns:rw="http://www.roguewave.com/xmlstream"
xsi:type="book"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<title xsi:type="xsd:string">To Love and Be Wise</title>
<author xsi:type="xsd:string">Josephine Tey</author>
</book>
Without transformation:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>>
<rw:nested_object rw:class="book"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:rw="http://www.roguewave.com/xmlstream">
<rw:member rw:name="title" xsi:type="xsd:string">To Love and Be
Wise</rw:member>
<rw:member rw:name="author" xsi:type="xsd:string">Josephine
Tey</rw:member></rw:nested_object>