Why is xml-script called XML-script?
In the last days i've been intrigued by the name the team decided to give to the new declarative style (that is, if I may call it that) used in ATLAS client programming.
well, at first sight, it really resembles XML and it stops working when you try to use invalid XML. On the other hand, there's something that has been bothering me from the start: namespaces. Let me explain with a simple example. Have you noticed how all the samples have a similar declaration to this one:
<script type="text/xml-script">
<page xmlns:script="http://schemas......">
....
</page>
</script>
The first question is: wtf? why are we using a prefix called script? Since all the elements normally presented inside the page element should be declared on the same namespace, then i really think that the script prefix should be dropped. In fact, it isn't used anywhere, so why not drop it (in fact, dropping it really didn't hurt so I've done that in my pages without even thinking about it :D). In the past, I've asked about this on the ATLAS forum and the best answer i could get was that it looked like the prefix was important for validation. That got me curious, but time went by and I never had the chance to take a look at what's was happening...at least, not until today!
Today I've built a class with my beloved ATLAS OO extensions and decided that it should be usable from xml-script. Well, it seemed so easy: I just had to implement the Sys.ITypeDescriptorProvider interface (the getDescriptor introduced by the interface method is used for defining the properties, methods and events which can be used from xml-script) and add a static parseFromMarkup method to the class. This last method is really important since it's responsible for creating an instance of the element that is being parsed. For instance, Sys._Application implements it so that there's only a Sys.Application object in the page. Sys.Component implements it so that each component that is found inside the components element originates a new Sys.Component object. After performing these steps, i decided to test my code.
The first problem was: where can I put my custom element? You see, most of the time, xml-script is used with controls and components and, to be honest, it's really great in many scenarios. In those cases, you just put everything inside the <components> element and you're ready to go. In my case, this just didn't seem right, so i decided to put an entry as a direct child of the page element. It simply didn't do anything (ie, my parseFromMarkup method simply wasn't called). I know that there are some objects (ex.: Sys.Application) which aren't components and are usable from xml-script...after searching for examples and speaking with Garbin, it was clear that the <application> element (used to represent a Sys.Application object in xml-script) is placed inside the <components> element...another wtf because Sys._Application really doesn't inherit from Sys.Component...hum, so let's try putting my object inside the <components> element...and yes, it worked.
This made me even more curious...if you think about it, there really isn't any logic in having to put my object inside the <components> section because it simply isn't a component! I may be absolutly wrong, but when I see a component section, I expect that everything inside it to be a component (or a component derived object). So i just had to check the code and the processDocumentScripts method (Sys.MarkupParser class) really tells the story. well, what does it do? It's really simple: it gets an array of xml-script nodes and sees if the current node is a components element or a references element. If it's none of these, then nothing happens. In other words, it's hard-coded and it only understands those elements. The <references> element uses a script loader object to load all the javascript proxies; the components' child nodes are parsed by using the parseNodes method.
If you put anything outside of those elements, you won't get an error, but it will not work either! hum...it's smeally, right? and note that I've got a cold right now and can't really smeall anything :)
ok, so I decided to peak a little more and guess what? remember the 1st code snipper I've shown? Yes, the one that has the page element as it's top element...now, let's do a simple experiment, shall we? try opening a simple page an replace that element with this one:
<script type="text/xml-script">
<microsoftThisSucksButItStillWorks xmlns:script="http://schemas......">
....
</microsoftThisSucksButItStillWorks>
</script>
And yes, we've got a touchdown...it works without any complaints whatsoever! And why is that? well, it's because the parser really doesn't interpret the top level element; it simply get's it and discards it without even checking its name. Quick, but also lets you opened to this type of hack :)
So let's recap: we've got a script prefix which really isn't used for anything; elements are only interpreted if they're placed inside the components element or inside the references element; and finally, you're really free to call whatever name you want to your top level element. That's what I call liberal XML :) (unless you also take into account the components/references element thing, where things aren't really so liberal...).
When I thought there were no more revelations, I decided to fire an old project which used an early version of the toolkit controls. the main thing about this project is that I'm just using the client portion of the controls and, therefore, I'm able to write my xml-script. Initially, I had the following:
<script type="text/xml-script">
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005" xmlns:atlascontroltoolkit="atlascontroltoolkit">
<components>
<label id="info">
<behaviors>
<script:opacity value="0.75" />
<atlascontroltoolkit:alwaysVisibleControlBehavior
HorizontalOffset="10"
VerticalOffset="10"
HorizontalSide="Left" />
</behaviors>
</label>
</components>
</page>
</script>
And it worked great (btw, the atlascontroltoolkit value that is used as a namespace uri was used as the default namespace value of the controls introduced by the tookit (that is, if i'm not mistaken). So, what happens if i change the namespace to test:
xmlns:atlascontroltoolkit="test"
Guess what? it still works. ok, let me say this again: it works! How about changing the prefix name: nop, it doesn't work. You get a validation error! Well, in my opinion, this behavior really sucks: that's not what namespaces are about...I should be able to change the prefix name to whatever I want and it should work assuming that my prefix points to the same uri. Though I'm not really a XML guy, I really think that this is not an acceptable behavior...specially if you think that ms xml parser is able to preform the correct validation. Speaking about validation, it would be nice to have a schema to validate the contents of xml-script.
So, it's true that xml-script must be well formed xml (which is really the only requisite for being xml) for it to get preocessed...but the namespace thing really really really (have i said enough reallys already?) sucks big time (not to speak about having to put an item inside the componets element so that it gets a chance of being correctly parsed). To me, namespaces are probably one of most important things that happened to XML. Why use this ridiculous parsing rule where you perform the validation based on the prefix name instead of using the namespace uri? This kind of behavior really makes me wonder why they have called xml-script XML-script...