Lots of folks have asked me how to add various XMLism like XML Namespace prefixes
to the serialized output of a SyndicationFeed. This is actually easy
to do once you know the trick but it's admittedly not the most obvious thing in the
world.
The thing to remember is that the System.Xml stack treats prefix declarations as special
kinds of attributes. If you want to emit an XML namespace declaration of xmlns:contoso=http://schemas.contoso.com you
need to emit attribute whose name is the prefix you're declaring (e.g. "contoso"),
whose value is the namespace URI that corresponds to the prefix (e.g. 'http://schemas.contoso.com').
This attribute needs to be in the special XML namespace declaration namespace (!)
of http://www.w3.org/2000/xmlns/
Since SyndicationFeed supports additional XML attributes through the AttributeExtensions
property, you can do this on SyndicationFeed as follows (using the C# 3.0 collection
initializer syntax, natch):
SyndicationFeed feed = new SyndicationFeed()
{
AttributeExtensions =
{
{ new XmlQualifiedName("contoso", "http://www.w3.org/2000/xmlns/"),
"http://schemas.constoso.com" }
}
};
If you like syntactic sugar, here are a few extension methods that add a helper function
to all of the OM constructs that support attribute extensibility:
using System;
using System.Xml;
using System.ServiceModel.Syndication;
namespace Samples
{
public static class SyndicationExtensions
{
public static void DeclareNamespace(this
SyndicationFeed feed, string prefix, string nsUri)
{
feed.AttributeExtensions.Add(new
XmlQualifiedName( prefix, "http://www.w3.org/2000/xmlns/" ),
nsUri);
}
public static void
DeclareNamespace(this SyndicationItem item, string prefix, string nsUri)
{
item.AttributeExtensions.Add(new
XmlQualifiedName(prefix, "http://www.w3.org/2000/xmlns/"),
nsUri);
}
public static void
DeclareNamespace(this SyndicationCategory category, string prefix, string nsUri)
{
category.AttributeExtensions.Add(new
XmlQualifiedName(prefix, "http://www.w3.org/2000/xmlns/"),
nsUri);
}
public static void
DeclareNamespace(this SyndicationLink link, string prefix, string nsUri)
{
link.AttributeExtensions.Add(new
XmlQualifiedName(prefix, "http://www.w3.org/2000/xmlns/"),
nsUri);
}
public static void
DeclareNamespace(this SyndicationPerson person, string prefix, string nsUri)
{
person.AttributeExtensions.Add(new
XmlQualifiedName(prefix, "http://www.w3.org/2000/xmlns/"),
nsUri);
}
}
}
On a side note, I'm becoming a huge fan of extension methods. They are not perfect,
but I expect that their existence will have a pretty substantial impact on the way
the internals of the framework get factored in future versions...