Can I add the xml-transform processing instruction to the xml returned from a wcf service contract
I have a restful wcf service that returns xml. I had the idea to add an xsl-transform processing instruction to the xml in order to beutify the data when viewed through a web browser.
Mission objective #1:
add <?xml-stylesheet type="text/xsl" href="style.xsl"?> to returned xml
I tried out the following method; http://shevaspace.blogspot.com/2009/01/include-xml-declaration-in-wcf-restful.html
The recommended way to add the xml-s开发者_开发技巧tylesheet tag to xml documents seem to be the WriteProcessingInstruction
method, but System.Xml.XmlDictionaryWriter
doesn't allow any calls to WriteProcessingInstruction( string name, string text )
with the name parameter being anythin other than "xml". WriteRaw
isn't allowed either, since it can only write data within the xml root node.
Is there a way to attach the xml-stylesheet tag to the returned xml from a wcf service?
I accomplished this by implementing my own XmlWriter that writes out the processing instruction. (In my case, only for responses in selected namespaces):
public class StylesheetXmlTextWriter : XmlTextWriter
{
private readonly string _filename;
private readonly string[] _namespaces;
private bool firstElement = true;
public StylesheetXmlTextWriter(Stream stream, Encoding encoding, string filename, params string[] namespaces) : base(stream, encoding)
{
_filename = filename;
_namespaces = namespaces;
}
public override void WriteStartElement(string prefix, string localName, string ns)
{
if (firstElement && (_namespaces.Length == 0 || _namespaces.Contains(ns)))
WriteProcessingInstruction("xml-stylesheet", string.Format("type=\"text/xsl\" href=\"{0}\"", _filename));
base.WriteStartElement(prefix, localName, ns);
firstElement = false;
}
}
Of course, in typical WCF fashion the hardest part of the exercise is to get WCF to use this. For me, this involved:
- Implementing a custom WebServiceHost and WebServiceHostFactory
- Replacing the WebMessageEncodingBindingElement of the ServiceEndpoints with a custom MessageEncodingBindingElement
- Overriding MessageEncodingBindingElement.CreateMessageEncoderFactory to return a custom MessageEncoderFactory
- Implementing a custom MessageEncoderFactory that returns a custom MessageEncoder on the Encoder property
- Implementing a custom MessageEncoder that uses the StylesheetXmlTextWriter in its WriteMessage implementations
精彩评论