life in a smart mob

social networking and other stuff

Xml Validation against a Schema and a DTD when namespaces come out to play

You ever do something that took far longer than it ever should have, but was an insanely small amount of effort had you just KNOWN how to do it right? (PLS. remember kids read these posts...). Anyway, if so read on ....

Today, a post on the MS Newsgroups asked how they could validate some Xml document that contains a reference to a DTD, uses namespaces and may be validated by an external Xml Schema. It's been a busy day, so near the end of it I opened a can of Scotland's cheapest, but drinkable, beer (well, since the Wrox thing it's beans, toast and cheap beer for me!) and got to thinking.

Although this sounds fairly simple, there is an important lesson you should remember before the same challenge poses you the same kind of problems. Consider the following Xml document:

<!DOCTYPE HeadCount SYSTEM "HeadCount.dtd" []>
<HeadCount>
  <Name First="Waldo" Last="Pepper">
    <Name First="Salt" Last="Pepper" Relation="spouse"/>
    <Name First="Red" Last="Pepper" Relation="child"/>
  </Name>
</HeadCount>


Fairly easy to validate against this right? Yep. ValidationType.DTD and ValidationType.Schema work like a gem and you get your validation errors as expected.

Now, however, imagine that you used namespaces in there (as well all do now of course). Easy, fire an xmlns attrib onto the HeadCount element so you get:

<HeadCount xmlns="urn:test">

So this time you go click your huge grey button (for some reason the buttons that DO stuff on test harnesses are always scaled up way out of proportion) on your validation app and you get an exception saying "What the hell is xmlns"??? (ok, in Scotland Windows is a little more direct...). Anyway, of course the DTD knows nothing about namespaces (certainly not semantically) so although your Schema is happy, you have to somehow tell your DTD that this xmlns attribute exists and is valid. When using a SYSTEM DTD you don't want to modify, the best way is to annotate, or add to, the definition within the Xml file. So you could do something like the following:

<!DOCTYPE HeadCount SYSTEM "HeadCount.dtd" [
 <!ATTLIST HeadCount xmlns CDATA #FIXED "urn:test">]>

Now you have told the DTD that an attibute exists called xmlns and always has the value urn:test - which just happens to be your namespace declaration! Run your validation tests again and all will work fine. Schema can still map the namespace to a targetNamespace and DTD doesn't fall over saying the "attribute" is invalid! Cool - unlike my now warm beer.

You can download the full working code sample from my web site :
http://stevenlivingstone.com/download/DTDSchemaValidation.zip

You see, not a lot to it, but it's just one of those little things that you can list in the "well boss, it was because..." excuse list when your project starts to run out of time. Anyone who ran into the cross-domain MSXML HTTP calls or the early days of running MSXML as a server component and making HTTP calls (doh!) will know just what i mean.

vtgo.net

Comments

TrackBack said:

# February 8, 2004 4:45 PM

TrackBack said:

# February 9, 2004 3:16 PM

TrackBack said:

# February 9, 2004 3:19 PM

Aaron Skonnard said:

This unfortunately won't work when namespace prefixes are used. Check out <a href="http://skonnard.com/archive/2004/02/09/245.aspx">this sample</a> for an example of dealing with namespace prefixes.
# February 9, 2004 8:26 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)