On Making XML Namespaced On The Fly

| 2 Comments | 1 TrackBack

This interesting trick has been discussed in microsoft.public.dotnet.xml newsgroup recently. When one has a no-namespaced XML document, such as

<?xml version="1.0"?>
<foo>
    <bar>Blah</bar>    
</foo>
there is a trick in .NET, which allows to read such document as if it has some default namespace:
<?xml version="1.0"?>
<foo xmlns="http://foo.com">
    <bar>Blah</bar>    
</foo>

Actually I have no idea when this could be useful, but people keep asking if this can be done (I presume they are neglecting namespaces in fact, but still I think there are real use cases for such functionality). And while it's probably not 100% clean architecturally, there is an effectieve and simple way. The crux is to read XML document not as standalone document, but as XML fragment, providing XmlNamespaceManager with default namespace set up. Here is the code:

string xml = 
@"<?xml version=""1.0""?>
  <foo>
    <bar>Blah</bar>    
  </foo>";
XmlNameTable nt = new NameTable();
XmlNamespaceManager nsm = new XmlNamespaceManager(nt);
nsm.AddNamespace(String.Empty, "http://foo.com");
XmlParserContext ctx = new XmlParserContext(nt, nsm, null, XmlSpace.Default);
XmlTextReader r = new XmlTextReader(xml, XmlNodeType.Document, ctx);
//Read it to XmlDocument to test
XmlDocument doc = new XmlDocument();
doc.Load(r);
doc.Save(Console.Out);
The result is
<?xml version="1.0"?>
<foo xmlns="http://foo.com">
  <bar>Blah</bar>
</foo>

I was quite surprised to see it works even when XML fragment type is XmlNodeType.Document, IMO it should work only for XmlNodeType.Element typed XML fragment. With XmlNodeType.Document it looks like inter-document namespace definition nonsense, but anyway, nice and effective trick.

Read more about reading XML fragments with XmlTextReader in MSDN.

Related Blog Posts

1 TrackBack

TrackBack URL: http://www.tkachenko.com/cgi-bin/mt-tb.cgi/159

The daily list of stuff I found interesting while blogreading. Read More

2 Comments

Terry, there are several options:

1. Make your XSLT namespace-agnostic - use "*[local-name='foo']" everywhere instaed of "foo".
2. Make your XSLT dynamic - update namespace in the stylesheet before loading or make XSLT generated (it's very easy in XSLT)
3. Create custom XmlReader that reads any XML as it it had one predefined namespace.

etc...

I have a similar issue. We have 'shared' Xslt files that need to process data that is in 'similiar' structure coming from different SQL 2K5 databases (Xml data type). Each client has it's own namespace/schema defined with it, but we need some generic Xslt files to work against any schema. Is there a way to dynamically set a 'default namespace' or is there some other method I should be looking into?

Leave a comment