473,401 Members | 2,127 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,401 software developers and data experts.

WriteXml to include xslt reference statement - how?

Hi,

I'm new to using xml/xslt and although I can create an xml document
using the dataset.WriteXml statement, and I have created an xslt to
transform the xml into the output I want, I have to manually add the
xsl reference statement to the xml file.

i.e.
<?xml version="1.0" standalone="yes"?>
<?xml:stylesheet type="text/xsl" href="Questions.xsl"?> --> I have to
add this
<NewDataSet>
<Questions>
<ID>1</ID>
Nov 12 '05 #1
3 4814
"Gordon Moore" <go***********@operamail.com> wrote in message news:eb**************************@posting.google.c om...
I'm new to using xml/xslt and although I can create an xml document
using the dataset.WriteXml statement, and I have created an xslt to
transform the xml into the output I want, I have to manually add the : : <?xml:stylesheet type="text/xsl" href="Questions.xsl"?>


I think the processing instruction you're meaning to write is xml-stylesheet
(with a dash, not xml:stylesheet with a colon), per the recommendation
described here,

http://www.w3.org/TR/xml-stylesheet/

Back to answering your original question, yes, it is possible to get WriteXml( )
to emit this processing instruction automatically. The design necessary involves
intercepting calls to the XmlWriter (or TextWriter, or Stream) and injecting the
processing instruction immediately after the XML declaration (alternately, before
the document element). This interception technique is applicable to any of the
TextWriter or a Stream overloads for WriteXml( ), but to keep this all in the
XML family, let's use the XmlWriter overload, OK? :-)

At first, I wasn't sure which overload of WriteXml( ) you were using since you
were getting an XML declaration with a standalone attribute. I've since learned
that WriteXml( ) has a quirk in it, and I now think I know which overload you're
using. Needless to say, I'll demonstrate how to easily overcome this quirk, so
you can use the XmlWriter solution as well.

First, let's create an XmlTextWriter subclass that you can include in your project.
It's a relatively simple matter to wrap a TextWriter around a FileStream using the
string filename I think you were using in the call to WriteXml( ). I'll explain how
this all works together momentarily, but here's the code:

- - - MagnumWriter.cs
using System;
using System.IO;
using System.Xml;

/// <summary>
/// Magnum Writer injects an xml-stylesheet processing instruction (PI) into the
/// XML serialization from any method that accepts an XmlWriter argument.
/// </summary>
public class MagnumWriter : XmlTextWriter
{
private string xslStylesheetFilename;
private bool xmlDeclWritten;

public MagnumWriter( TextWriter writer, string stylesheetFilename) : base( writer)
{
xslStylesheetFilename = stylesheetFilename;
xmlDeclWritten = false;
}

public override void WriteStartDocument( bool standalone)
{
xmlDeclWritten = true;
base.WriteStartDocument( standalone);
base.WriteProcessingInstruction( "xml-stylesheet", String.Format( "type=\"text/xsl\" href=\"{0}\"",
xslStylesheetFilename) );
}

public override void WriteStartElement( string prefix, string localName, string nsUri)
{
if ( !xmlDeclWritten )
this.WriteStartDocument( true);
base.WriteStartElement( prefix, localName, nsUri);
}
}
- - -

The constructor creates a MagnumWriter, which is really just an XmlTextWriter that
I've overriden a few methods on. In order to create an XmlTextWriter that will send
XML content someplace, I need my constructor to at least support a parameter that
the XmlTextWriter's constructor can accept. In this case, that's the writer argument,
which gets passed to my base( ) (MyBase( writer) for those following along in VB.NET)
and does all the initializations underneath in the XmlTextWriter base class I've derived
from. Additionally, since MagnumWriter is "adding value," it needs to accept the
file name or URL you want to have appear in the href pseudo attribute, so that's the
second argument to it's constructor which gets saved into the xslStylesheetFilename
field for when I write the processing instruction later.

Next is WriteStartDocument( ). Normally when there are a number of overloads and
you're asking yourself which one should you override to get the most bang-for-the-buck,
the answer will be the overload with the most parameters. WriteStartDocument( ) would
just call the more specific WriteStartDocument( bool) anyway, so I only have to override
it once and not override both of them.

WriteStartDocument( ) is normally the place you want to be in most XmlWriter applications
that need supplementary processing instructions added up in the document's prolog, although
processing instructions may also appear anyplace within the document as well (they aren't
restricted to preceding the start element, although in xml-stylesheet's case it does).

As I've implemented WriteStartDocument( ), first I call the base class' WriteStartDocument( )
so it can go ahead with writing the XML declaration, and then I call the WriteProcessing-
Instruction( ) to immediately succeed it with our xml-stylesheet PI.

This might ordinarily be enough, but there's a quirk in some of the WriteXml( ) methods of
DataSet by which they won't necessarily call WriteStartDocument( ). It only writes out the
XML declaration (calling WriteStartDocument( )) when it knows it's writing out an entire
document: start, middle and end. This is the case with the WriteXml( ) overload taking a
string filename, but is not presumed with many of the other overloads. This is probably to
support writing multiple data sets out within the context of a larger containing document
element -- but for this solution it's a quirk that I'll show you how to overcome.

The solution is where the xmlDeclWritten field comes into the picture. Whenever a call
is made to WriteStartDocument( ), this flag is raised and remains raised for the duration.
If the DataSet::WriteXml( ) instead calls WriteStartElement( ) first, instead of WriteStart-
Document( ), meaning that we're going ahead without an XML declaration, then what
I've implemented for WriteStartElement( ) checks the xmlDeclWritten flag to see if it
hasn't been raised yet, and if it hasn't I call WriteStartDocument( ) to raise it (and thereby
inject an XML declaration and the xml-stylesheet PI into the stream).

WriteStartElement( ) then does what any good intercepter method should do, it calls
it's base method implementation as if it weren't even there.

I know any client that produces XML through an XmlWriter will use either WriteStart-
Document( ) or WriteStartElement( ) first, so this ensures that whichever path the code
takes you have an XML declaration and PI emitted when you pipe it through Magnum-
Writer.

- - - InjectingProcInstDemo.cs (except)
using System;
using System.Data;
using System.IO;
using System.Xml;

// . . .

TextWriter streamToFile = new StreamWriter( xmlFilename);
MagnumWriter magnumPI = new MagnumWriter( streamToFile, "Questions.xsl");
magnumPI.Formatting = Formatting.Indented; // optionally set indented formatting of output here..
dataSet1.WriteXml( magnumPI);
magnumPI.Flush( );
magnumPI.Close( ); // close underlying file stream, forgetting this may leave exclusive locks on the file..

// . . .
- - -

This final piece of code demonstrates, for completeness, how you can use a TextWriter
instead of a file name, so that you can call the overload of WriteXml( ) on your DataSet
that accepts XmlWriter-subclasses like the MagnumWriter.
Derek Harmon
Nov 12 '05 #2
Derek - you are a star.

Thank you very much for your informative response. The code works a
treat.

It is really wonderful when people like yourself take so much time and
effort to respond in such a complete way to queries - thanks again.

Thanks for the correction on the correct syntax on xml-stylesheet. I
picked up the ":" version from an online tutorial!

Regards

Gordon

"Derek Harmon" <lo*******@msn.com> wrote in message news:<un*************@TK2MSFTNGP12.phx.gbl>...
"Gordon Moore" <go***********@operamail.com> wrote in message news:eb**************************@posting.google.c om...
I'm new to using xml/xslt and although I can create an xml document
using the dataset.WriteXml statement, and I have created an xslt to
transform the xml into the output I want, I have to manually add the

: :
<?xml:stylesheet type="text/xsl" href="Questions.xsl"?>


I think the processing instruction you're meaning to write is xml-stylesheet
(with a dash, not xml:stylesheet with a colon), per the recommendation
described here,

http://www.w3.org/TR/xml-stylesheet/

Back to answering your original question, yes, it is possible to get WriteXml( )
to emit this processing instruction automatically. The design necessary involves
intercepting calls to the XmlWriter (or TextWriter, or Stream) and injecting the
processing instruction immediately after the XML declaration (alternately, before
the document element). This interception technique is applicable to any of the
TextWriter or a Stream overloads for WriteXml( ), but to keep this all in the
XML family, let's use the XmlWriter overload, OK? :-)

At first, I wasn't sure which overload of WriteXml( ) you were using since you
were getting an XML declaration with a standalone attribute. I've since learned
that WriteXml( ) has a quirk in it, and I now think I know which overload you're
using. Needless to say, I'll demonstrate how to easily overcome this quirk, so
you can use the XmlWriter solution as well.

First, let's create an XmlTextWriter subclass that you can include in your project.
It's a relatively simple matter to wrap a TextWriter around a FileStream using the
string filename I think you were using in the call to WriteXml( ). I'll explain how
this all works together momentarily, but here's the code:

- - - MagnumWriter.cs
using System;
using System.IO;
using System.Xml;

/// <summary>
/// Magnum Writer injects an xml-stylesheet processing instruction (PI) into the
/// XML serialization from any method that accepts an XmlWriter argument.
/// </summary>
public class MagnumWriter : XmlTextWriter
{
private string xslStylesheetFilename;
private bool xmlDeclWritten;

public MagnumWriter( TextWriter writer, string stylesheetFilename) : base( writer)
{
xslStylesheetFilename = stylesheetFilename;
xmlDeclWritten = false;
}

public override void WriteStartDocument( bool standalone)
{
xmlDeclWritten = true;
base.WriteStartDocument( standalone);
base.WriteProcessingInstruction( "xml-stylesheet", String.Format( "type=\"text/xsl\" href=\"{0}\"",
xslStylesheetFilename) );
}

public override void WriteStartElement( string prefix, string localName, string nsUri)
{
if ( !xmlDeclWritten )
this.WriteStartDocument( true);
base.WriteStartElement( prefix, localName, nsUri);
}
}
- - -

The constructor creates a MagnumWriter, which is really just an XmlTextWriter that
I've overriden a few methods on. In order to create an XmlTextWriter that will send
XML content someplace, I need my constructor to at least support a parameter that
the XmlTextWriter's constructor can accept. In this case, that's the writer argument,
which gets passed to my base( ) (MyBase( writer) for those following along in VB.NET)
and does all the initializations underneath in the XmlTextWriter base class I've derived
from. Additionally, since MagnumWriter is "adding value," it needs to accept the
file name or URL you want to have appear in the href pseudo attribute, so that's the
second argument to it's constructor which gets saved into the xslStylesheetFilename
field for when I write the processing instruction later.

Next is WriteStartDocument( ). Normally when there are a number of overloads and
you're asking yourself which one should you override to get the most bang-for-the-buck,
the answer will be the overload with the most parameters. WriteStartDocument( ) would
just call the more specific WriteStartDocument( bool) anyway, so I only have to override
it once and not override both of them.

WriteStartDocument( ) is normally the place you want to be in most XmlWriter applications
that need supplementary processing instructions added up in the document's prolog, although
processing instructions may also appear anyplace within the document as well (they aren't
restricted to preceding the start element, although in xml-stylesheet's case it does).

As I've implemented WriteStartDocument( ), first I call the base class' WriteStartDocument( )
so it can go ahead with writing the XML declaration, and then I call the WriteProcessing-
Instruction( ) to immediately succeed it with our xml-stylesheet PI.

This might ordinarily be enough, but there's a quirk in some of the WriteXml( ) methods of
DataSet by which they won't necessarily call WriteStartDocument( ). It only writes out the
XML declaration (calling WriteStartDocument( )) when it knows it's writing out an entire
document: start, middle and end. This is the case with the WriteXml( ) overload taking a
string filename, but is not presumed with many of the other overloads. This is probably to
support writing multiple data sets out within the context of a larger containing document
element -- but for this solution it's a quirk that I'll show you how to overcome.

The solution is where the xmlDeclWritten field comes into the picture. Whenever a call
is made to WriteStartDocument( ), this flag is raised and remains raised for the duration.
If the DataSet::WriteXml( ) instead calls WriteStartElement( ) first, instead of WriteStart-
Document( ), meaning that we're going ahead without an XML declaration, then what
I've implemented for WriteStartElement( ) checks the xmlDeclWritten flag to see if it
hasn't been raised yet, and if it hasn't I call WriteStartDocument( ) to raise it (and thereby
inject an XML declaration and the xml-stylesheet PI into the stream).

WriteStartElement( ) then does what any good intercepter method should do, it calls
it's base method implementation as if it weren't even there.

I know any client that produces XML through an XmlWriter will use either WriteStart-
Document( ) or WriteStartElement( ) first, so this ensures that whichever path the code
takes you have an XML declaration and PI emitted when you pipe it through Magnum-
Writer.

- - - InjectingProcInstDemo.cs (except)
using System;
using System.Data;
using System.IO;
using System.Xml;

// . . .

TextWriter streamToFile = new StreamWriter( xmlFilename);
MagnumWriter magnumPI = new MagnumWriter( streamToFile, "Questions.xsl");
magnumPI.Formatting = Formatting.Indented; // optionally set indented formatting of output here..
dataSet1.WriteXml( magnumPI);
magnumPI.Flush( );
magnumPI.Close( ); // close underlying file stream, forgetting this may leave exclusive locks on the file..

// . . .
- - -

This final piece of code demonstrates, for completeness, how you can use a TextWriter
instead of a file name, so that you can call the overload of WriteXml( ) on your DataSet
that accepts XmlWriter-subclasses like the MagnumWriter.
Derek Harmon

Nov 12 '05 #3
Ahhh, the syntax error was mine after all. Clearly I can't read...

Gordon
go***********@operamail.com (Gordon Moore) wrote in message news:<eb**************************@posting.google. com>...
Derek - you are a star.

Thank you very much for your informative response. The code works a
treat.

It is really wonderful when people like yourself take so much time and
effort to respond in such a complete way to queries - thanks again.

Thanks for the correction on the correct syntax on xml-stylesheet. I
picked up the ":" version from an online tutorial!

Regards

Gordon

"Derek Harmon" <lo*******@msn.com> wrote in message news:<un*************@TK2MSFTNGP12.phx.gbl>...
"Gordon Moore" <go***********@operamail.com> wrote in message news:eb**************************@posting.google.c om...
I'm new to using xml/xslt and although I can create an xml document
using the dataset.WriteXml statement, and I have created an xslt to
transform the xml into the output I want, I have to manually add the

: :
<?xml:stylesheet type="text/xsl" href="Questions.xsl"?>


I think the processing instruction you're meaning to write is xml-stylesheet
(with a dash, not xml:stylesheet with a colon), per the recommendation
described here,

http://www.w3.org/TR/xml-stylesheet/

Back to answering your original question, yes, it is possible to get WriteXml( )
to emit this processing instruction automatically. The design necessary involves
intercepting calls to the XmlWriter (or TextWriter, or Stream) and injecting the
processing instruction immediately after the XML declaration (alternately, before
the document element). This interception technique is applicable to any of the
TextWriter or a Stream overloads for WriteXml( ), but to keep this all in the
XML family, let's use the XmlWriter overload, OK? :-)

At first, I wasn't sure which overload of WriteXml( ) you were using since you
were getting an XML declaration with a standalone attribute. I've since learned
that WriteXml( ) has a quirk in it, and I now think I know which overload you're
using. Needless to say, I'll demonstrate how to easily overcome this quirk, so
you can use the XmlWriter solution as well.

First, let's create an XmlTextWriter subclass that you can include in your project.
It's a relatively simple matter to wrap a TextWriter around a FileStream using the
string filename I think you were using in the call to WriteXml( ). I'll explain how
this all works together momentarily, but here's the code:

- - - MagnumWriter.cs
using System;
using System.IO;
using System.Xml;

/// <summary>
/// Magnum Writer injects an xml-stylesheet processing instruction (PI) into the
/// XML serialization from any method that accepts an XmlWriter argument.
/// </summary>
public class MagnumWriter : XmlTextWriter
{
private string xslStylesheetFilename;
private bool xmlDeclWritten;

public MagnumWriter( TextWriter writer, string stylesheetFilename) : base( writer)
{
xslStylesheetFilename = stylesheetFilename;
xmlDeclWritten = false;
}

public override void WriteStartDocument( bool standalone)
{
xmlDeclWritten = true;
base.WriteStartDocument( standalone);
base.WriteProcessingInstruction( "xml-stylesheet", String.Format( "type=\"text/xsl\" href=\"{0}\"",
xslStylesheetFilename) );
}

public override void WriteStartElement( string prefix, string localName, string nsUri)
{
if ( !xmlDeclWritten )
this.WriteStartDocument( true);
base.WriteStartElement( prefix, localName, nsUri);
}
}
- - -

The constructor creates a MagnumWriter, which is really just an XmlTextWriter that
I've overriden a few methods on. In order to create an XmlTextWriter that will send
XML content someplace, I need my constructor to at least support a parameter that
the XmlTextWriter's constructor can accept. In this case, that's the writer argument,
which gets passed to my base( ) (MyBase( writer) for those following along in VB.NET)
and does all the initializations underneath in the XmlTextWriter base class I've derived
from. Additionally, since MagnumWriter is "adding value," it needs to accept the
file name or URL you want to have appear in the href pseudo attribute, so that's the
second argument to it's constructor which gets saved into the xslStylesheetFilename
field for when I write the processing instruction later.

Next is WriteStartDocument( ). Normally when there are a number of overloads and
you're asking yourself which one should you override to get the most bang-for-the-buck,
the answer will be the overload with the most parameters. WriteStartDocument( ) would
just call the more specific WriteStartDocument( bool) anyway, so I only have to override
it once and not override both of them.

WriteStartDocument( ) is normally the place you want to be in most XmlWriter applications
that need supplementary processing instructions added up in the document's prolog, although
processing instructions may also appear anyplace within the document as well (they aren't
restricted to preceding the start element, although in xml-stylesheet's case it does).

As I've implemented WriteStartDocument( ), first I call the base class' WriteStartDocument( )
so it can go ahead with writing the XML declaration, and then I call the WriteProcessing-
Instruction( ) to immediately succeed it with our xml-stylesheet PI.

This might ordinarily be enough, but there's a quirk in some of the WriteXml( ) methods of
DataSet by which they won't necessarily call WriteStartDocument( ). It only writes out the
XML declaration (calling WriteStartDocument( )) when it knows it's writing out an entire
document: start, middle and end. This is the case with the WriteXml( ) overload taking a
string filename, but is not presumed with many of the other overloads. This is probably to
support writing multiple data sets out within the context of a larger containing document
element -- but for this solution it's a quirk that I'll show you how to overcome.

The solution is where the xmlDeclWritten field comes into the picture. Whenever a call
is made to WriteStartDocument( ), this flag is raised and remains raised for the duration.
If the DataSet::WriteXml( ) instead calls WriteStartElement( ) first, instead of WriteStart-
Document( ), meaning that we're going ahead without an XML declaration, then what
I've implemented for WriteStartElement( ) checks the xmlDeclWritten flag to see if it
hasn't been raised yet, and if it hasn't I call WriteStartDocument( ) to raise it (and thereby
inject an XML declaration and the xml-stylesheet PI into the stream).

WriteStartElement( ) then does what any good intercepter method should do, it calls
it's base method implementation as if it weren't even there.

I know any client that produces XML through an XmlWriter will use either WriteStart-
Document( ) or WriteStartElement( ) first, so this ensures that whichever path the code
takes you have an XML declaration and PI emitted when you pipe it through Magnum-
Writer.

- - - InjectingProcInstDemo.cs (except)
using System;
using System.Data;
using System.IO;
using System.Xml;

// . . .

TextWriter streamToFile = new StreamWriter( xmlFilename);
MagnumWriter magnumPI = new MagnumWriter( streamToFile, "Questions.xsl");
magnumPI.Formatting = Formatting.Indented; // optionally set indented formatting of output here..
dataSet1.WriteXml( magnumPI);
magnumPI.Flush( );
magnumPI.Close( ); // close underlying file stream, forgetting this may leave exclusive locks on the file..

// . . .
- - -

This final piece of code demonstrates, for completeness, how you can use a TextWriter
instead of a file name, so that you can call the overload of WriteXml( ) on your DataSet
that accepts XmlWriter-subclasses like the MagnumWriter.
Derek Harmon

Nov 12 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Adi Schwarz | last post by:
I was asking myself what solution is better considering performance. I want to create some classes depending on a varable (for different languages). Of course, if the classes are huge I write...
5
by: Brett conklin | last post by:
I would like to not use the google groups as a crutch in my XSLT journey. What is the best xslt reference out there? Is it a book? Is it a web site? I am finding that I can come up with nearly...
2
by: Jon Shemitz | last post by:
Once, I happened on a fairly complete set of xsl: language element docs in VS.2003. I can't find it again - can anyone tell me how to navigate to it from either the Contents or the Index? -- ...
3
by: Peter Row | last post by:
Hi, I have 2 XML files and 1 XSLT file. The second XML file has the following declarative 1st line: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> ....the 1st one (the one to be...
4
by: Lord0 | last post by:
Hi there, Is the following possible with XSLT? Given the following example XML docs: <!-- doc 1--> <user> <username>myUsername</username> <password></password> <phone>12345</phone>
6
by: Puzzled | last post by:
http://www.biglist.com/lists/xsl-list/archives/200303/msg01242.html purports to show how xslt can be used to copy all of an xhtml file & selectively transform certain nodes. The copy works fine on...
0
by: Vince Filby | last post by:
Should WriteXml include the tags that encompass the object? Take a Phone class for example, should WriteXml() emit this: <Phone> <Description>text</Description> <Number>1-222-333-1234</Number>...
2
jkmyoung
by: jkmyoung | last post by:
Here's a short list of useful xslt general tricks that aren't taught at w3schools. Attribute Value Template Official W3C explanation and example This is when you want to put dynamic values...
3
by: Simon Brooke | last post by:
I'm trying to do internationalisation by using xsl:include to include a different file depending on the locale setting, and I'm completely failing. I've tried several different approaches: ...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.