<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Softimage Blog &#187; XML</title>
	<atom:link href="http://www.softimageblog.com/archives/category/xml/feed" rel="self" type="application/rss+xml" />
	<link>http://www.softimageblog.com</link>
	<description>People and thoughts behind Softimage in production...</description>
	<lastBuildDate>Mon, 21 Jun 2010 20:40:48 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>About exporting shaders</title>
		<link>http://www.softimageblog.com/archives/243#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=about-exporting-shaders</link>
		<comments>http://www.softimageblog.com/archives/243#comments</comments>
		<pubDate>Mon, 09 Jul 2007 01:33:00 +0000</pubDate>
		<dc:creator>Bernard Lebel</dc:creator>
				<category><![CDATA[Programming / Scripting]]></category>
		<category><![CDATA[Rendering]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.xsi-blog.com/archives/243</guid>
		<description><![CDATA[ABSTRACT
This article discusses some of the problems and solutions involved in exporting shaders from XSI, using custom tools and custom file formats.
THE INITIAL GOALS
At Big Bang I wanted the ability to write materials to XML files (and read them back, of course). This would serve two major purposes. First, it would offer a granular set [...]]]></description>
			<content:encoded><![CDATA[<p><strong>ABSTRACT</strong></p>
<p>This article discusses some of the problems and solutions involved in exporting shaders from XSI, using custom tools and custom file formats.</p>
<p><strong>THE INITIAL GOALS</strong></p>
<p>At Big Bang I wanted the ability to write materials to XML files (and read them back, of course). This would serve two major purposes. First, it would offer a granular set of data, which could be re-used in different contexts. I could have used preset file instead of a XML file, but the second major purpose of the project prevented that: I wanted to be able to not only read the file, but also to make modifications in it if there was ever such a need.</p>
<p>To be honest I was quite disappointed that after I spent so much time and effort into this project, it turned out I needed to make such edits to material files only for about 20 of them (as of this writing, there are about 3,800 such material files in the pipeline). I could have also used the XML file at other things, like building templates for standard materials, using it for the approval of shading tasks, etc. But in the end that did not happen. However, the work I did for exporting materials could be used for other things.</p>
<p><span id="more-243"></span><strong>THE CHALLENGES OF MATERIAL EXPORT</strong></p>
<p>It didn&#8217;t take too long until I felt that exporting materials can be a rocky business. At first glance it seems very straightforward: select an object, run a script to export its material. In the material file, I wanted not only the entire material described, but I also wanted to list the image clips and the image sources used by this material. Plus, I wanted to know which scene objects are using this material, including geometry, clusters, groups and partitions. So that when I import the material, I could re-create it, as well as its image clips and sources, and apply it to objects using it if they are in the scene.</p>
<p>Next, I wanted the code to handle inputs that consisted of more than one object. For instance, given an input of objects (either geometry, partitions, clusters, or even materials), the code had to figure out what to export and do it right. I didn&#8217;t want the script to attempt to export the material of a chain, for example. Given that input management allowed many objects to be visited, and that some of these objects could use the same material, I had to keep track of which material had already been exported.</p>
<p>On top of the material, the image sources, the image clips and the objects using this material, I had to write the actual shaders to the file. Afterall the goal was to be able to re-create the material from an XML file, so I needed the list of shaders. One may think that to write shaders to a file, all that is needed is to recursively walk down the material&#8217;s Render Tree and, well, write the shaders as they are visited.</p>
<p>Not quite. Some shaders are connected into several other inputs. Unaware recursive traversal of the Render Tree meant that entire branches could end up being written several times. That was a waste of space and CPU cycles. Plus, if many branches are being repeated, how would the importing code know that it&#8217;s actually the same branch?</p>
<p>So I had to find a way to organise shaders with a unique &#8220;key&#8221;. At first I considered using their FullName. I was in for a big surprise.</p>
<p>In the Explorer, switch to Scene Root scope. If you iterate the Properties/LocalProperties of an object, find a material, and print its FullName, it will return the name of the material with the object&#8217;s FullName prefixed. Same if you select the material under the object. However, switch the Explorer&#8217;s scope to Materials. If you select the same material and print its FullName, then you get the name of the material prefixed with the library&#8217;s FullName, which is garanteed to be unique.</p>
<p>I call this last one the material&#8217;s &#8220;AbsoluteName&#8221;. There might be better terms for this, however I thought of it as browsing the file system, where there can be no two absolute file name for the same file (well, it&#8217;s possible, but let&#8217;s not get carried away).</p>
<p>It&#8217;s easy to work out the AbsoluteName of a material, even when you get the material from the objects owning it instead of the library. But to my knowledge, it&#8217;s impossible to use the same approach for shaders under this material. The FullName of a shader changes depending on the parameter it is being read from. For example, if you have an Image shader connected into an input of a Blinn shader and the input of an another shader, logging the Image&#8217;s FullName when traversing the Render Tree will return ..Blinn.Image and &#8230;Image.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">xsi = Application
&nbsp;
<span style="color: #808080; font-style: italic;"># Get selected object</span>
oSel = xsi.<span style="color: black;">selection</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Get selected object's material</span>
oMat = oSel.<span style="color: black;">material</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> walk<span style="color: black;">&#40;</span> oShader <span style="color: black;">&#41;</span>:
	xsi.<span style="color: black;">logmessage</span><span style="color: black;">&#40;</span> oShader.<span style="color: black;">fullname</span> <span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #808080; font-style: italic;"># Iterate the shader parameters</span>
	<span style="color: #ff7700;font-weight:bold;">for</span> oParameter <span style="color: #ff7700;font-weight:bold;">in</span> oShader.<span style="color: black;">parameters</span>:
&nbsp;
		<span style="color: #808080; font-style: italic;"># Get the parameter source</span>
		oSource = oParameter.<span style="color: black;">source</span>
&nbsp;
		<span style="color: #808080; font-style: italic;"># Check if we got a source</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> oSource <span style="color: #66cc66;">!</span>= <span style="color: #008000;">None</span>:
&nbsp;
			<span style="color: #808080; font-style: italic;"># Get the classname of the source</span>
			sClassName = xsi.<span style="color: black;">classname</span><span style="color: black;">&#40;</span> oSource <span style="color: black;">&#41;</span>
&nbsp;
			<span style="color: #808080; font-style: italic;"># Check if the classname is a shader</span>
			<span style="color: #ff7700;font-weight:bold;">if</span> sClassName == <span style="color: #483d8b;">'Shader'</span> <span style="color: #ff7700;font-weight:bold;">or</span> sClassName == <span style="color: #483d8b;">'Texture'</span>:
				walk<span style="color: black;">&#40;</span> oSource <span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Loop over material parameters</span>
walk<span style="color: black;">&#40;</span> oMat <span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Prints:</p>
<pre># INFO : sphere.Material
# INFO : sphere.Material.Blinn
# INFO : sphere.Material.Blinn.Image
# INFO : sphere.Material.Blinn.Image
# INFO : sphere.Material.Blinn
# INFO : sphere.Material.Blinn.Image
# INFO : sphere.Material.Blinn.Image
# INFO : sphere.Material.Cell
# INFO : sphere.Material.Cell.Image</pre>
<p>So this means you can&#8217;t use the shader FullName as a unique key. If you can&#8217;t rely on the shader&#8217;s FullName, then how can you make sure that you have not visited this shader already? You could possibly use the shader&#8217;s Name. Afterall, in a material, all shaders have a unique name.</p>
<p>But instead of using the names as the key, I preferred to give them a unique ID number (unsigned integer). Image clips would also receive such an ID. When writing the shader parameters to the file, if they had a shader or an image clip connected, it would use the previously defined ID of the shader/image clip. This meant that before writing anything to the XML file, all shaders and image clips would need to be visited. Ultimately, a map of all shaders, based on their ID and their name, could be established.</p>
<p>This resulted in somewhat complex dictionaries and lists, which were hard to maintain and debug. Nonetheless, I managed to make the material export work reliably. It was slow (since it&#8217;s uncompiled code), but it was totally reliable.</p>
<p>I should add that handling parameters such as texture projection pointers posed a challenge worthy of talking about. Those parameters are not like other parameters, they require a different handling. Of course all that is needed is available in the SDK, still, I thought I&#8217;d mention it to those attempting at writing shaders to file.</p>
<p><strong>BEYOND MATERIALS</strong></p>
<p>All went smooth for many many months, until we started looking into lighting and rendering. Then it occured to me that I needed the ability to export passes, so they could be re-created later on. I thought that since I had code that could write shaders to file, then surely I could reuse this code for other things than materials: overrides and pass shader stacks. Well, that&#8217;s what I thought. But my code was built entirely around the material export, so I could hardly use it for overrides and pass stacks without making drastic modifications.</p>
<p><strong>Pass shader stacks</strong><br />
There are two major problems with pass shader stacks.</p>
<p>The first problem is that from all practical purposes, passes have the appearance of materials. If you select a pass and open the Render Tree, you&#8217;ll see the pass object being displayed as if it was a material. In reality, that is not quite right.</p>
<p>For instance, you can iterate the parameters of material, and effectively traverse the Render Tree from there. That is not happening with passes. First, passes do not have a Parameters property, and second, they do not expose shaders in any way. So the Render Tree display is highly misleading, and I had to write code to handle passes differently than materials. In short, I did not find any quick and easy way to get the stack shaders. This is illustrated by this stripped down method that collects the stack &#8220;root&#8221; shaders (see next paragraph):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> addpass<span style="color: black;">&#40;</span> <span style="color: #008000;">self</span>, oPass <span style="color: black;">&#41;</span>:
&nbsp;
	aStacks = <span style="color: black;">&#91;</span>
		<span style="color: #483d8b;">'Environment Shader Stack'</span>,
		<span style="color: #483d8b;">'Output Shader Stack'</span>,
		<span style="color: #483d8b;">'Volume Shader Stack'</span>
	<span style="color: black;">&#93;</span>
&nbsp;
	<span style="color: #808080; font-style: italic;"># Iterate pass stacks</span>
	<span style="color: #ff7700;font-weight:bold;">for</span> sStack <span style="color: #ff7700;font-weight:bold;">in</span> aStacks:
&nbsp;
		<span style="color: #808080; font-style: italic;"># Get the stack object</span>
		oStack = oPass.<span style="color: black;">nestedobjects</span><span style="color: black;">&#40;</span> sStack <span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;"># Check if the stack has shaders</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> oStack.<span style="color: black;">nestedobjects</span>.<span style="color: black;">count</span> <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">0</span>:
&nbsp;
			<span style="color: #808080; font-style: italic;"># Iterate root shaders of this stack</span>
			<span style="color: #ff7700;font-weight:bold;">for</span> oStackShader <span style="color: #ff7700;font-weight:bold;">in</span> oStack.<span style="color: black;">nestedobjects</span>:
&nbsp;
				<span style="color: #808080; font-style: italic;"># do something with shader</span></pre></td></tr></table></div>

<p>The second problem is that in a pass, there can be multiple shaders living at the top-level of a stack (which I shall call &#8220;root&#8221; shaders). For instance, if you apply two volume shaders to a pass and then open the Render Tree of that pass, you&#8217;ll only see the latest volume shader. That&#8217;s another misleading aspect of the pass&#8217;s Render Tree. So it can be assumed a pass shader stack can have multiple &#8220;root&#8221; shaders, and each of them is entirely valid and must be exported if you want to fully export the pass shader stacks. The upshot is that the pass object act as a name space, just as a material: among all the shader stacks of a pass, no two shaders can share the same name. This is great, but that doesn&#8217;t solve our problem of multiple root shaders for a same stack.</p>
<p>Also, when importing a pass shader stack, using the typical ways of creating shaders and plugging them afterward worked for all but the &#8220;root&#8221; shaders. To import pass shader stacks, each shader had to have a &#8220;stackroot&#8221; flag in the XML file. When meeting such a flag, the script would not simply create the shader and plug it later, it would have to run the command that creates root shaders in stacks. This command is the only way to not destroy other existing root shaders!</p>
<p><strong>Overrides</strong><br />
Overrides pose an entirely different set of problems.</p>
<p>They are not materials, and they are not pass shader stacks, yet they can host complex networks of shaders. There also can be more than one override per partition! An override could not be handled as a material nor a pass. Materials, in my framework, were meant to be exported as single files, overrides needed to be exported in a pass file, along the shader stacks, partitions and render options. An override doesn&#8217;t have things like the material&#8217;s UsedBy property, it is a partition property.</p>
<p>Also, overrides on partitions are visible only in the current pass. I thought that this was case only in the GUI, but found out that this extends to the scripting interface. If you iterate the properties of a partition not of the current pass, you&#8217;ll never catch that partition&#8217;s overrides. The only solution was to use a low-level command such as FindObjects() to collect all overrides, which works, and then organise them by pass and by partition, to later write them to file along the partition that&#8217;s being written.</p>
<p>Using FindObjects() to collect overrides returned a lot more overrides that what I expected. All these overrides were named VisibilityOverrideXX (&#8220;XX&#8221; being a number). I basically found out that group objects (groups, layers, partitions) implement the parameter inheritance via an override. This override is created when a parameter of the group object is not set to &#8220;no effect on members&#8221;, but remain invisible at all times, except to commands like FindObjects(). This can be tricky, because you don&#8217;t want to export this override. However you never know when a user will create an override to disable a parameter like &#8220;viewvis&#8221;, and name this override &#8220;VisibilityOverride&#8221;. The only solution when such an override name is encountered is to check that the partition parameters all set to &#8220;no effect on members&#8221;.</p>
<p>But the biggest problem with overrides came with the import. This article is not about shader import (which may be covered in another article), but few things are worth mentioning.</p>
<p>You can&#8217;t add a parameter to an override if the parameter cannot be found in the partition members. The only way to add a parameter to an override is to use SIAddEntryToOverride(), which requires a parameter FullName string. My solution was not very elegant, and is not garanteed. Basically the code tries to find the parameter among the partition members. If find its, then good, the entry can be added. Otherwise, you&#8217;re out of luck. Materials are also tricky because the override parameter name doesn&#8217;t exactly reflect the real shader parameter FullName that has to be overridden. With elaborate string manipulation this can all be worked out, but this is slow and like I said, not very reliable.</p>
<p>Another annoying thing is that an entry added to an override cannot be accessed right away via the object model. At least that was the case in XSI 5.11 (I tried in 6.01 and it seems to work). For instance, the following code would raise an error:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">xsi = Application
&nbsp;
<span style="color: #808080; font-style: italic;"># Get the selected override</span>
oOverride = xsi.<span style="color: black;">selection</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
sParameterName = <span style="color: #483d8b;">'viewvis'</span>
sParameterFullName = <span style="color: #483d8b;">'cube.visibility.%s'</span> <span style="color: #66cc66;">%</span> sParameterName
&nbsp;
xsi.<span style="color: black;">SIAddEntryToOverride</span><span style="color: black;">&#40;</span> oOverride, sParameterFullName <span style="color: black;">&#41;</span>
&nbsp;
oOverride.<span style="color: black;">parameters</span><span style="color: black;">&#40;</span> sParameterName <span style="color: black;">&#41;</span>.<span style="color: black;">value</span> = <span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>So to get back the added parameters I had to use strings.</p>
<p><strong>Cameras and lights</strong><br />
I have not talked about cameras and lights so far, simply because as the time of this writing, the need to export their shaders never arose.</p>
<p>In our pipeline, cameras and lights are exported as full-fledge models. Their importance is rather low compared to other models (like characters, for instance), so that exporting their network of shaders was not felt as a necessity. Also, cameras and lights are very light-weight compared to other models, so managing them always as models posed no particular problem.</p>
<p>My belief is that lights can be handled not too differently than materials. The catch word is &#8220;too&#8221;. The light primitive is a bit like a material, it has inputs for connecting shaders. But a light is not a material, and I&#8217;m affraid that handling lights would require yet another dedicated wrapper to hide the real nature of the light.</p>
<p>In the case of camera shaders, my guess is that they behave in a similar fashion as pass shader stacks do. The camera shader stack lives right under the camera primitive, and appears to be accessible only through the NestedObjects property. Just as a pass shader stack, the camera shader stacks accepts multiple shaders at its top level, but when you open the Render Tree, it shows only the first shader of the stack.</p>
<p><strong>THE SHADER NAME SPACE</strong></p>
<p>Obviously, trying to adapt the existing material export code to also export pass shader stacks and overrides turned out to be very tedious. So I had to make drastic changes to the framework, and implement a new interface: the shader name space.</p>
<p>I consider the material, the override and the pass shader stack to be shader name spaces. That is, a space where a collection of shader names live. A material, a pass and an override as all shader name spaces. Lights and cameras are also shader name spaces. As of this writing, however, my framework does not include anything to export and import lights and cameras.</p>
<p>The object used as the shader name space is not necessarily the &#8220;root&#8221; shader, that is, the shader of the tree where all others ultimately plug in. Materials and overrides are both name space and root, but in the case of pass shader stacks, each &#8220;root&#8221; shader of a stack is a shader name space root. So a shader name space can have multiple roots. In the shader name space, the exact nature of the name space is not really important, as it is hidden by the shader name space interface.</p>
<p>Treating data that way made things far more easier to work with. Low-level functions would write to file without knowing the context of use, while wrappers would handle all the specificities of the name space.</p>
<p><strong>PROPOSITION OF IMPROVEMENT FOR MATERIALS</strong></p>
<p>All of this hassle with shader export and shader name space made me think about how it could have been a lot easier. I had to write code to handle all types of shader name space, which resulted in significant amounts of code and increased opportunities for bugs to make it through. The shader name space is in fact an attempt at implementing something that, I believe, should be in XSI: new kinds of materials.</p>
<p>Lights, passes and cameras should implement a material. I don&#8217;t see any reason why not.</p>
<p>- Imagine if light, pass, and camera materials could be managed from the Explorer, just like other materials. Light materials could use an orange color, while pass materials could be green and camera materials could use a gray color. The color is not important, but this mean they could a lot easier to manage, especially in large amounts. They could be organised in libraries, exported, and referenced.</p>
<p>- The mess of pass and camera shader stacks would not be visible anymore.</p>
<p>- Sharing materials among lights, passes and cameras would be a breeze. Increased reusability.</p>
<p>- Programming-wise, they would make the process very homogenous. No matter if you select a light, geometry, or a pass, you can always use its Material property to access the material. Simple, straightforward and consistent.</p>
<p>I don&#8217;t really see where overrides would fit in this design. Perhaps they could be left as they are, but at least it&#8217;s only one special case to handle, not every case.</p>
<p>I&#8217;m strongly against the idea of having a &#8220;super&#8221; material. For instance this material could be applied to anything, however it would expose only parameters suitable for the context it&#8217;s being used in. When applied to different kinds of objects, I hardly see how it would be easy to work with. It would make scripting very inconsistent and require the same kind of tedious handling I have been discussing in this article.</p>
<p>Get a material and a passes file here: <a href='http://www.xsi-blog.com/userContent/upload/2007/07/xml.zip' title='Material and passes XML files'>Material and passes XML files</a></p>
<p><strong>ABOUT DATA INPUT MANAGEMENT IN MATERIAL EXPORT</strong></p>
<p>If you think that this section title sounds redundant, you are right. I have written an article on XSI-Blog about this very subject. I talk again about it because it really is during the development of this project that the importance of data input management struck me. I think that the data input management is one of the most fundamental aspects of any larger programming project.</p>
<p>I wanted the material export to be easy for the user. I wanted the interactive input to be simple and predictable. Users tend to favor the simplest ways of doing things. Given a model, they would expect to export everything related to this model. They don&#8217;t really care about the details, but they know that if all components of character lives under a unique model, then they have to be able to do things by simply handing the model to the script (via selection or picking, for example). However, exporting everything under a model can generate lots of data and take considerable time, so I wanted to give the users the ability to &#8220;focus&#8221; the export: given a selected object, it would export only the object&#8217;s material(s). Or the user could even select the material and export it. Painless, fast and predictable.</p>
<p>But giving the users various ways of exporting things meant that I had to write considerable code to manage the data input. The code that wrote to XML files was dumb, but lives below thick wrappers that would manage all the data input from the user. When the materials to export would reach the actual exporting functions, it would have to be guaranteed to be adequate.</p>
<p>Here is a little chart to show the framework design to cope with this task.</p>
<p>- call from the user<br />
    &#8211; user data input management (objects, materials&#8230;)<br />
        &#8211; final data input management (by type of data)<br />
            &#8211; export of shader name spaces<br />
                &#8211; fetch data from structures<br />
                    &#8211; write to file</p>
<p>The difference between &#8220;user data input management&#8221; and &#8220;final data input management&#8221; is that they used a different interface. Both interface would handle data, but with different purposes in mind. Ultimately, they would end up populating data structures that, too, served specific puroses.</p>
<p>The first layer of input management handled the data provided by the user to make sure it was acceptable for the export and/or the import. For example, it ould make sure that only materials, overrides and passes could make it through for an export. The interface used to perform this task is an interface used throughout the entire framework to take care of all initial data inputs.</p>
<p>That interface, that I called the &#8220;Chapter&#8221; (as in a chapter in the biker world) would know everything about the context: is the user exporting or importing, is he exporting/importing in a shot or in an element, things like that. Through a system of promotion and demotion, the Chapter would store &#8220;suitable&#8221; primary data into structures that could be later accessed by everyone else.</p>
<p>The second layer of input management, &#8220;final data input management&#8221;, as well as &#8220;fetch data from structures&#8221;, used a more specialized interface, dedicated to shader export. Its job would be to hide all the complexities in the differences that exist between materials, overrides and shader stacks.</p>
<p>In &#8220;final data input management&#8221;, it would extract the final data from the &#8220;suitable&#8221; primary data coming from the Chapter, and store it in data structures. In &#8220;fetch data from structures&#8221;, it would read this final data on-demand as the script goes on. The interface would make the storing and reading of that data completely homogenous, no matter if dealing with a material, a pass, or an override. While resulting in very long code (the entire interface is implemented as nested classes), it made the overall data handling incredibly easy.</p>
<img src="http://www.softimageblog.com/?ak_action=api_record_view&id=243&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.softimageblog.com/archives/243/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Using XML in scripting</title>
		<link>http://www.softimageblog.com/archives/42#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=using-xml-in-scripting</link>
		<comments>http://www.softimageblog.com/archives/42#comments</comments>
		<pubDate>Fri, 16 Sep 2005 13:16:44 +0000</pubDate>
		<dc:creator>Andy Nicholas</dc:creator>
				<category><![CDATA[Programming / Scripting]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.xsi-blog.com/?p=42</guid>
		<description><![CDATA[This article is intended to be a fast primer to understanding XML for anyone who hasn''t had the time to investigate its capabilities. XML is a text based file format that allows you to define your own structure within the conventions laid out by the XML format. What follows will hopefully show you the benefits of using XML and how you can use it to manipulate data with minimum effort. How you then apply this to your technical solutions inside and outside of XSI is up to you.

The first part of this article looks at the ideas and concepts behind XML data. The second half will show how easy it is to put it into practice in scripting and C++.]]></description>
			<content:encoded><![CDATA[<p>This article is intended to be a fast primer to understanding XML for anyone who hasn&#8217;t had the time to investigate its capabilities. XML is a text based file format that allows you to define your own structure within the conventions laid out by the XML format. What follows will hopefully show you the benefits of using XML and how you can use it to manipulate data with minimum effort. How you then apply this to your technical solutions inside and outside of XSI is up to you.</p>
<p>The first part of this article looks at the ideas and concepts behind XML data. The second half will show how easy it is to put it into practice in scripting and C++.<br />
<span id="more-42"></span></p>
<p><strong>Making sure you have the latest vesion</strong></p>
<p>Before we go on, you should make sure that you have the latest version of Microsoft&#8217;s XML support installed. Note that MSXML 4.0 sits on top of the previous versions of MSXML, and so it shouldn&#8217;t cause any conflicts with any other software.</p>
<p>To obtain the latest version, I&#8217;ve created a <a href="http://www.andynicholas.com/thezone/content/programming/html/InstallMSXML.html">web page</a> which should perform the installation quickly and easily through your web browser. Alternatively if you prefer, you can download it directly from Microsoft by visiting this web page <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=3144b72b-b4f2-46da-b4b6-c5d7485f2b42&#038;displaylang=en">here</a>.</p>
<p><strong>XML Basics</strong></p>
<p>Without further delay, let&#8217;s look at a very simple example of XML before we examine the benefits of using it:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>robot<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>c:\project\models\robot.emdl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>The first line is the declaration of the XML file type. At this stage, it&#8217;s not worth examining any further, except to say that this is how the file identifies itself as XML.</p>
<p>The second line declares an opening tag with &#8220;object&#8221; as the identifier. The last line then specifies the corresponding closing tag. All tags must have an open and close tag, unless it is a special XML tag (indicated by a &lt;?, see the first line) or if it contains no child data. If it contains no child data, then as a shortcut it can be written as &#8220;<code><object></object></code>&#8220;.</p>
<p>The nice indented layout of the example is optional. It wouldn&#8217;t matter at all if there were no new lines or white space between the tags. You should note however, that this doesn&#8217;t mean that XML ignores the white space. Many XML parsers have by default the option to store the white space as extra child nodes of the parent node, so be warned!</p>
<p>The big advantage of using XML as a file format is scalability. This piece of jargon basically just means that it&#8217;s easy to expand on, without needing to have to plan for every eventuality at the outset. For example, if we later decide that we need to store information about the animation of the object, we can just add in an extra set of nodes like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>robot<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>c:\project\models\robot.emdl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;animation<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #808080; font-style: italic;">&lt;!-- ...other data... --&gt;</span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/animation<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Imagine that we had written a script with a function to parse the original <code><object></object></code> node tree structure. If that old function had been written properly, it will now just ignore the new <code><animation></animation></code> nodes. If we update the function, we can tell it to read the new <code><animation></animation></code> nodes if they exist, or to use some predefined default values if they don&#8217;t.</p>
<p>We can also embed the <code><object></object></code> node tree into an entirely different XML tree. For example, we might have an XML file that describes a scene:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scene<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numobjects<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numobjects<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>c:\project\scenes\robotfight.scn<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;objectlist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>robot<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>c:\project\models\robot.emdl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;animation<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #808080; font-style: italic;">&lt;!-- ...other data... --&gt;</span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/animation<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/objectlist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scene<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>The point to note here is that we can still use our original function to parse the <code><object></object></code> node sub-tree, even though it&#8217;s located in an entirely different file format. This is why XML is so nice to use; it saves so much unnecessary work maintaining input/output (IO) routines.<br />
<!--more--></p>
<p><strong>Transforming XML with XSL Transforms</strong></p>
<p>Since the format of XML is standardised, it is possible for any application to read the data. Of course, it doesn&#8217;t necessarily mean that the application will know what to do with it or what the information means.</p>
<p>For example, if you double click on any valid XML document in Windows, Internet Explorer will start up and display the document, allowing you to expand and collapse the tree nodes by clicking on them. Internet Explorer doesn&#8217;t know what the XML data means, but that doesn&#8217;t stop it from presenting it to you in a convenient manner.</p>
<p>The way that Internet Explorer does this is by using what is known as a XML style sheet. These are themselves XML documents, but they also use a convention known as XSL. An XSL document has the ability to transform an XML document into another text based format. This new format can be anything of your choosing, but you&#8217;ll generally want it to be another XML document.</p>
<p>When Internet Explorer loads your XML file, it is using a default XSL document to transform it into XHTML (an HTML format that is compliant with XML standards). By writing your own XSL documents, you can easily edit and present your XML data with minimum effort.</p>
<p>Here&#8217;s an example based on the previous section. The XML file below has an extra XML tag at line 2 which specifies a default XSL document to transform it. This is only a recommendation to the application loading it, and does not mean that it cannot be transformed by a different XSL document.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;">&lt; ?xml-stylesheet <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/xsl&quot;</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;TabulateRobots.xslt&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scene<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;objectlist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>robot<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>c:\project\models\robot.emdl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>droid<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>c:\project\models\droid.emdl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>mech<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>c:\project\models\mech.emdl<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/objectlist<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scene<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Below is an XSL transform document that will process this XML, and turn it into an XHTML document that displays the data as a table.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :stylesheet <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">xmlns:xsl</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/1999/XSL/Transform&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :template <span style="color: #000066;">match</span>=<span style="color: #ff0000;">&quot;/scene/objectlist&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>   
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;table</span> <span style="color: #000066;">border</span>=<span style="color: #ff0000;">&quot;1&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;500&quot;</span> <span style="color: #000066;">cellpadding</span>=<span style="color: #ff0000;">&quot;5&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>      
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tr</span> <span style="color: #000066;">bgcolor</span>=<span style="color: #ff0000;">&quot;#cccccc&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
               <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;td</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;200&quot;</span> <span style="color: #000066;">align</span>=<span style="color: #ff0000;">&quot;center&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;b<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Model Name<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/b<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/td<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
               <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;td</span> <span style="color: #000066;">align</span>=<span style="color: #ff0000;">&quot;center&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;b<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>File Path<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/b<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/td<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/tr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>      
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :for-each <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;object&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
               <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;td<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :value-of <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;name&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/td<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
               <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;td<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :value-of <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;file&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/td<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/tr<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/table<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>If you copy and paste the examples into Robot.xml and TabulateRobots.xslt, then you can double click on Robot.xml to see the result, which should look something like this:</p>
<table align="center" border="1" cellpadding="5" width="500">
<tbody>
<tr bgcolor="#cccccc">
<td align="center" width="200">Model Name</td>
<td align="center">File Path</td>
</tr>
<tr>
<td>robot</td>
<td>c:\project\models\robot.emdl</td>
</tr>
<tr>
<td>droid</td>
<td>c:\project\models\droid.emdl</td>
</tr>
<tr>
<td>mech</td>
<td>c:\project\models\mech.emdl</td>
</tr>
</tbody>
</table>
<p>This hopefully illustrates how easy it is to manipulate XML using XSL. In the above example, we chose to transform the data into XHTML. In fact, it&#8217;s possible to transform it into any text based format we choose by using &#8220;CDATA&#8221; tags. We could even create a script from an XML document like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :stylesheet <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">xmlns:xsl</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/1999/XSL/Transform&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :output omit-xml-declaration = <span style="color: #ff0000;">&quot;yes&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :template <span style="color: #000066;">match</span>=<span style="color: #ff0000;">&quot;/scene/objectlist&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;">&lt; !<span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span>Class Robot   </span>
<span style="color: #009900;">      Public name</span>
<span style="color: #009900;">      Public file</span>
<span style="color: #009900;">      End Class</span>
<span style="color: #009900;">      Sub PrintRobots</span>
<span style="color: #009900;">      <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;">&lt; !<span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span>Dim robotArray<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :value-of <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;count(object)&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span>&lt; !<span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#41;</span></span>
<span style="color: #009900;">      <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :for-each <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;object&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
         <span style="color: #009900;">&lt; !<span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span>Set curRobot =  new Robot</span>
<span style="color: #009900;">         curRobot.name = <span style="color: #ff0000;">&quot;]]&gt;&lt;xsl :value-of select=&quot;</span>name<span style="color: #ff0000;">&quot;/&gt;&lt; ![CDATA[&quot;</span></span>
<span style="color: #009900;">         curRobot.file = <span style="color: #ff0000;">&quot;]]&gt;&lt;xsl :value-of select=&quot;</span>file<span style="color: #ff0000;">&quot;/&gt;&lt; ![CDATA[&quot;</span></span>
<span style="color: #009900;">         Set robotArray<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :value-of <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;position()-1&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span>&lt; !<span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#41;</span> = curRobot</span>
<span style="color: #009900;">         <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>   
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/xsl<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
         <span style="color: #009900;">&lt; !<span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span>For i = 0 To <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;xsl</span> :value-of <span style="color: #000066;">select</span>=<span style="color: #ff0000;">&quot;count(object)-1&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
         <span style="color: #009900;">&lt; !<span style="color: #66cc66;">&#91;</span>CDATA<span style="color: #66cc66;">&#91;</span></span>
<span style="color: #009900;">         Msgbox robotArray<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span>.name +<span style="color: #ff0000;">&quot; : &quot;</span>+ robotArray<span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">&#41;</span>.file</span>
<span style="color: #009900;">         Next</span>
<span style="color: #009900;">         End Sub<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span></pre></td></tr></table></div>

<p>The above XSL transform will generate the following VBScript code:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="vb" style="font-family:monospace;">Class Robot
   <span style="color: #000080;">Public</span> name
   <span style="color: #000080;">Public</span> file
<span style="color: #000080;">End</span> Class 
&nbsp;
<span style="color: #000080;">Sub</span> PrintRobots
   <span style="color: #000080;">Dim</span> robotArray(3)
   <span style="color: #000080;">Set</span> curRobot = <span style="color: #000080;">new</span> Robot
   curRobot.name = <span style="color: #800000;">&quot;robot&quot;</span>
   curRobot.file = <span style="color: #800000;">&quot;c:\project\models\robot.emdl&quot;</span>
   <span style="color: #000080;">Set</span> robotArray(0) = curRobot
   <span style="color: #000080;">Set</span> curRobot = <span style="color: #000080;">new</span> Robot
   curRobot.name = <span style="color: #800000;">&quot;droid&quot;</span>
   curRobot.file = <span style="color: #800000;">&quot;c:\project\models\droid.emdl&quot;</span>
   <span style="color: #000080;">Set</span> robotArray(1) = curRobot
   <span style="color: #000080;">Set</span> curRobot = <span style="color: #000080;">new</span> Robot
   curRobot.name = <span style="color: #800000;">&quot;mech&quot;</span>
   curRobot.file = <span style="color: #800000;">&quot;c:\project\models\mech.emdl&quot;</span>
   <span style="color: #000080;">Set</span> robotArray(2) = curRobot
   <span style="color: #000080;">For</span> i = 0 <span style="color: #000080;">To</span> 2
      Msgbox robotArray(i).name +<span style="color: #800000;">&quot; : &quot;</span>+ robotArray(i).file
   <span style="color: #000080;">Next</span> 
<span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span></pre></td></tr></table></div>

<p>A few things to note: Firstly, I&#8217;ve manually tidied up the formatting of the code (good luck trying to get it to look that neat straight from XSL). Generally it shouldn&#8217;t be a problem, unless of course you&#8217;re trying to generate Python code.</p>
<p>Secondly, it&#8217;s not hard to see that it doesn&#8217;t look like a particularly efficient way of doing things. For example, what happens if I have 12000 robots? That&#8217;d be one big VBScript!</p>
<p>Thirdly; great, so now we&#8217;ve got this script. How can we actually use it? Well, one easy way is to embed the script into HTML and let Internet Explorer run it. A better way though is to call it from your own scripts. That&#8217;s where the second half of this article begins.</p>
<p>Lastly, I should point out that generating a script from an XML document is not a particularly common thing to do. Usually, you will be generating a different XML structure, such as XHTML. This example is only to illustrate the flexability of using XML with XSL tranforms.</p>
<p>If you didn&#8217;t before, you should now have some sort of understanding of what XML is all about, and how it can be used to store and manipulate data. In the next section, I&#8217;ll be showing you how you can easily use it from VBScript and C++ without having to write your own XML parser.<br />
<!--more--></p>
<p><strong>XML and VBScript</strong></p>
<p>You may be wondering why I&#8217;m using VBScript in this article. The main reason is that I experienced a few problems at work with JScript returning me the wrong interface from the COM object. I&#8217;ve since tested JScript successfully at home, and have come to the conclusion that it must be a problem with the machine at work. I still don&#8217;t know what the cause of this is, but until I do, I&#8217;m sticking with VBScript for any work with XML.</p>
<p>With the amount of people using XML in web applications, it shouldn&#8217;t come as any surprise that Microsoft support the use of XML in the form of COM objects (also known as ActiveX objects). This means that we can use these objects in scripts and let them do all the hard work.</p>
<p>Let&#8217;s go straight to an example. Save the VBScript XSL document example above as &#8220;VBSScriptRobots.xslt&#8221;, and then copy and paste the code below into a new text document and rename it &#8220;GenerateScript.vbs&#8221;.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">set</span> xmlDoc = CreateObject(<span style="color: #800000;">&quot;Msxml2.DOMDocument.4.0&quot;</span>)
xmlDoc.async=<span style="color: #000080;">false</span>    
xmlDoc.load <span style="color: #800000;">&quot;Robots.xml&quot;</span>
&nbsp;
<span style="color: #000080;">set</span> xslDoc= CreateObject(<span style="color: #800000;">&quot;Msxml2.DOMDocument.4.0&quot;</span>)
xslDoc.async = <span style="color: #000080;">false</span>
xslDoc.load <span style="color: #800000;">&quot;VBSScriptRobots.xslt&quot;</span>
&nbsp;
funcStr = xmlDoc.transformNode(xslDoc)
&nbsp;
msgbox funcStr
execute funcStr
PrintRobots</pre></td></tr></table></div>

<p>If you now run the script, it will display the generated code in a message box, and then it will run the function and present you with three message boxes displaying the XML data records.</p>
<p>I&#8217;m sure you&#8217;ll still be concerned about the fact that we generated the script with the robot names and filenames hard-coded into the generated function (if not, you should be!). A much better way of going about this task, would be to use the XML document object model to iterate through the XML tree structure, like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Set</span> xmlDoc = CreateObject(<span style="color: #800000;">&quot;Msxml2.DOMDocument.4.0&quot;</span>)
xmlDoc.async = <span style="color: #000080;">False</span>
xmlDoc.load <span style="color: #800000;">&quot;Robots.xml&quot;</span>
&nbsp;
<span style="color: #000080;">Set</span> sceneNode = xmlDoc.documentElement
<span style="color: #000080;">Set</span> objListNode = sceneNode.firstChild
<span style="color: #000080;">Set</span> objectListNode = objListNode.childNodes
&nbsp;
<span style="color: #000080;">For</span> i=0 <span style="color: #000080;">To</span> objectListNode.length-1
   <span style="color: #000080;">Set</span> objectNode = objectListNode.item(i)
   <span style="color: #000080;">set</span> nameNode = objectNode.firstChild
   <span style="color: #000080;">set</span> fileNode = nameNode.nextSibling
   msgbox nameNode.text &amp;<span style="color: #800000;">&quot; : &quot;</span>&amp; fileNode.text
<span style="color: #000080;">Next</span></pre></td></tr></table></div>

<p>This script doesn&#8217;t even need an XSL document. It simply traverses the XML node tree and iterates through each <code><object></object></code> node, displaying the name and file as it goes.</p>
<p>When writing a function to parse an XML node, we should generally make sure it does the following:</p>
<table>
<tbody>
<tr>
<td valign="top">1)</td>
<td valign="top">Ignore any extra nodes that it doesn&#8217;t expect to encounter.</td>
</tr>
<tr>
<td valign="top">2)</td>
<td valign="top">Use default data when non-critical data is missing.</td>
</tr>
<tr>
<td valign="top">3)</td>
<td valign="top">If critical data is missing, attempt to continue to read the rest of the node wherever possible, and at the very least, log the error and make sure it is reported to the user. (There will of course be circumstances where it cannot continue reading data, and the function will have to return an error immediately.)</td>
</tr>
<tr>
<td valign="top">4)</td>
<td valign="top">Unless there is good reason, only parse the current level in the tree for each function. This will mean that you can chop and change your XML structure around easily and just change the order that the functions are being called. It also allows for easier code reuse.</td>
</tr>
</tbody>
</table>
<p>The following code does exactly the same job as the code you&#8217;ve just seen, but it also implements the above points. While the code is much larger (and slightly slower), it is definitely more robust and is capable of withstanding most syntactical errors in the <code><scene></scene></code> format. It also provides helpful error messages should anything go wrong by encapsulating the output data inside a resusable class that stores the error information.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
</pre></td><td class="code"><pre class="vb" style="font-family:monospace;">Class SceneData
   <span style="color: #000080;">Private</span> <span style="color: #000080;">Sub</span> Class_Initialize
      <span style="color: #000080;">Set</span> objectsDict = CreateObject(<span style="color: #800000;">&quot;Scripting.Dictionary&quot;</span>)
   <span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span>
   <span style="color: #000080;">Public</span> objectsDict
<span style="color: #000080;">End</span> Class
&nbsp;
Class XMLDataWrapper
   <span style="color: #000080;">Private</span> <span style="color: #000080;">Sub</span> Class_Initialize
      <span style="color: #000080;">Set</span> dataObject = <span style="color: #000080;">Nothing</span>
      errNum=0
      errMsg=<span style="color: #800000;">&quot;&quot;</span>
   <span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span>
&nbsp;
   <span style="color: #000080;">public</span> dataObject
&nbsp;
   <span style="color: #000080;">Public</span> errNum
   <span style="color: #000080;">Public</span> errMsg
<span style="color: #000080;">End</span> Class
&nbsp;
LoadSceneXMLDoc <span style="color: #800000;">&quot;Robots.xml&quot;</span>
&nbsp;
<span style="color: #000080;">Function</span> LoadSceneXMLDoc(filename)
   <span style="color: #000080;">Set</span> xmlDoc = CreateObject(<span style="color: #800000;">&quot;Msxml2.DOMDocument.4.0&quot;</span>)
   xmlDoc.async = <span style="color: #000080;">False</span>
   xmlDoc.load filename
&nbsp;
   <span style="color: #000080;">Set</span> errObj = xmlDoc.parseError
   <span style="color: #000080;">If</span> (errObj.errorCode &lt;&gt; 0) <span style="color: #000080;">Then</span>     
        Msgbox <span style="color: #800000;">&quot;XML Load Error:&quot;</span>&amp; vbCrLf &amp; errObj.reason
        LoadSceneXMLDoc=<span style="color: #000080;">False</span>
        <span style="color: #000080;">Exit</span> <span style="color: #000080;">Function</span>
   <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
&nbsp;
   <span style="color: #000080;">Set</span> XMLDataObj = <span style="color: #000080;">new</span> XMLDataWrapper
   <span style="color: #000080;">Set</span> XMLDataObj.dataObject = <span style="color: #000080;">new</span> SceneData
&nbsp;
   <span style="color: #000080;">If</span> LoadSceneNode(xmlDoc.documentElement, XMLDataObj)=<span style="color: #000080;">True</span> <span style="color: #000080;">Then</span>
      keysArr = XMLDataObj.dataObject.objectsDict.keys
      dataArr = XMLDataObj.dataObject.objectsDict.items
      num = XMLDataObj.dataObject.objectsDict.count
      <span style="color: #000080;">For</span> i = 0 <span style="color: #000080;">to</span> num-1
         Msgbox keysArr(i) &amp;<span style="color: #800000;">&quot; : &quot;</span>&amp; dataArr(i)
      <span style="color: #000080;">Next</span>
      LoadSceneXMLDoc=<span style="color: #000080;">True</span>
   <span style="color: #000080;">Else</span>
      Msgbox <span style="color: #800000;">&quot;XML Load Error (&quot;</span>&amp;XMLDataObj.errNum&amp;<span style="color: #800000;">&quot;):&quot;</span>&amp; vbCrLf &amp; XMLDataObj.errMsg
      LoadSceneXMLDoc=<span style="color: #000080;">False</span>
   <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span>
&nbsp;
<span style="color: #000080;">Function</span> LoadSceneNode(sceneNode, XMLDataObj)
   <span style="color: #000080;">Set</span> objListNode = sceneNode.selectSingleNode(<span style="color: #800000;">&quot;objectlist&quot;</span>)   
   <span style="color: #000080;">If</span> <span style="color: #000080;">Not</span> objListNode <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span>
      LoadSceneNode = LoadObjectListNode(objListNode, XMLDataObj)
   <span style="color: #000080;">Else</span>
      XMLDataObj.errNum=1
      XMLDataObj.errMsg=<span style="color: #800000;">&quot;Can't find &lt;objectlist&gt; node&quot;</span>
      LoadSceneNode = <span style="color: #000080;">False</span>
   <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span>
&nbsp;
<span style="color: #000080;">Function</span> LoadObjectListNode(objListNode, XMLDataObj)
   <span style="color: #000080;">Set</span> objList = objListNode.selectNodes(<span style="color: #800000;">&quot;object&quot;</span>)   
   <span style="color: #000080;">If</span> <span style="color: #000080;">Not</span> objList <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span>   
      <span style="color: #000080;">For</span> i=0 <span style="color: #000080;">To</span> objList.length-1
         <span style="color: #000080;">If</span> LoadObjectNode(objList.item(i), XMLDataObj) <span style="color: #000080;">Then</span>
            LoadObjectListNode = <span style="color: #000080;">True</span>
         <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
      <span style="color: #000080;">Next</span>
      <span style="color: #000080;">If</span> LoadObjectListNode=<span style="color: #000080;">False</span> <span style="color: #000080;">Then</span>
         XMLDataObj.errNum=2
         XMLDataObj.errMsg=<span style="color: #800000;">&quot;Could not load any &lt;object&gt; nodes correctly&quot;</span>   
      <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
   <span style="color: #000080;">Else</span>
      XMLDataObj.errNum=1
      XMLDataObj.errMsg=<span style="color: #800000;">&quot;Can't find any &lt;/object&gt;&lt;object&gt; nodes&quot;</span>
      LoadObjectListNode = <span style="color: #000080;">False</span>
   <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
<span style="color: #000080;">End</span> <span style="color: #000080;">Function</span>
&nbsp;
<span style="color: #000080;">Function</span> LoadObjectNode(objNode, XMLDataObj)
   <span style="color: #000080;">Set</span> nameNode = objNode.selectSingleNode(<span style="color: #800000;">&quot;name&quot;</span>)   
   <span style="color: #000080;">If</span> <span style="color: #000080;">Not</span> nameNode <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span>
      <span style="color: #000080;">Set</span> fileNode = objNode.selectSingleNode(<span style="color: #800000;">&quot;file&quot;</span>)   
      <span style="color: #000080;">If</span> <span style="color: #000080;">Not</span> fileNode <span style="color: #000080;">Is</span> <span style="color: #000080;">Nothing</span> <span style="color: #000080;">Then</span>
         XMLDataObj.dataObject.objectsDict.Add nameNode.text, fileNode.text
         LoadObjectNode=<span style="color: #000080;">True</span>
      <span style="color: #000080;">Else</span>
         XMLDataObj.errNum=1
         XMLDataObj.errMsg=<span style="color: #800000;">&quot;Can't find &lt;file&gt; node for &quot;</span>&amp;nameNode.text
         LoadObjectNode = <span style="color: #000080;">False</span>
      <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
   <span style="color: #000080;">Else</span>
      XMLDataObj.errNum=1
      XMLDataObj.errMsg=<span style="color: #800000;">&quot;Can't find &lt;name&gt; node&quot;</span>
      LoadObjectNode = <span style="color: #000080;">False</span>
   <span style="color: #000080;">End</span> <span style="color: #000080;">If</span>
<span style="color: #000080;">End</span> Function&lt;/name&gt;&lt;/file&gt;&lt;/object&gt;&lt;/objectlist&gt;</pre></td></tr></table></div>

<p>If you look at the node loading functions, you should see that they are all quite similar. This means that writing them isn&#8217;t that much extra work, since once you&#8217;ve written one, you can duplicate alot of the functionality in the others. It also gives rise to an interesting thought; why not try using XSL to automatically generate the code for your XML loader? (That&#8217;s left as an exercise to the reader!)</p>
<p>Following these guidelines will generally mean that XML IO routines are well behaved, expandable, and should mean minimal effort when updating their functionality.</p>
<p>To this end, a good idea is to use XML attributes to specify the version of a node. For example, we could rewrite the object node as follows:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;object</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/object<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>This would mean that we could easily tell which version of the scene structure we are loading, and know in advance which child nodes are to be expected.<br />
<!--more--></p>
<p><strong>Finding the documentation</strong></p>
<p>You may have been wondering where you can find the documentation on the various objects that we&#8217;re using. For example, how do we find out what properties and methods our XML document object has? The first step is to enter the following code:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Set</span> xmlDoc = CreateObject(<span style="color: #800000;">&quot;Msxml2.DOMDocument.4.0&quot;</span>)
MsgBox(typename(xmlDoc))</pre></td></tr></table></div>

<p>You should get a message box with the word &#8220;DOMDocument&#8221; in it. If you now go to <a href="http://msdn.microsoft.com/">msdn.microsoft.com</a> and do a search in the MSDN library for DOMDocument, click on the first result and you should see a list of properties, methods, and events.</p>
<p>The encompassing area that you need to be looking under is MSXML which can be found <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/b24aafc2-bf1b-4702-bf1c-b7ae3597eb0c.asp">here</a>. Of course, you can also find this information in the MSDN documentation that comes with any version of Visual Studio .NET.</p>
<p><strong>Moving on to C++</strong></p>
<p>Although it helps, you don&#8217;t really have to know that much about COM to be able to use MSXML objects in your C++ code.</p>
<p>The first thing to do is to use the <strong>#import</strong> statement. This pre-processor directive automatically creates and includes two header files which contain the necessary information for using the MSXML COM interfaces. We use this statement to include the <strong>msxml4.dll</strong> file which contains the necessary type information to generate the headers. This statement should be placed in a suitable header file to be included by any source files that need to use any of the MSXML interfaces.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#import &quot;msxml4.dll&quot;</span></pre></td></tr></table></div>

<p>Once you&#8217;ve done that, you can go ahead and create your DOMDocument object. To create the object, you do something like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">MSXML2<span style="color: #008080;">::</span><span style="color: #007788;">IXMLDOMDocument2</span> <span style="color: #000040;">*</span> xmlDoc<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
&nbsp;
HRESULT hr <span style="color: #000080;">=</span> CoCreateInstance<span style="color: #008000;">&#40;</span>__uuidof<span style="color: #008000;">&#40;</span>MSXML2<span style="color: #008080;">::</span><span style="color: #007788;">DOMDocument40</span><span style="color: #008000;">&#41;</span>,
                      <span style="color: #0000dd;">0</span>,
                      CLSCTX_INPROC_SERVER,
                      __uuidof<span style="color: #008000;">&#40;</span>MSXML2<span style="color: #008080;">::</span><span style="color: #007788;">IXMLDOMDocument2</span><span style="color: #008000;">&#41;</span>,
                      <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">**</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">&amp;</span>xmlDoc<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>SUCCEEDED<span style="color: #008000;">&#40;</span>hr<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
   <span style="color: #666666;">//etc.</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Now that we have a pointer to the IXMLDOMDocument2 interface of the DOMDocument40 object, we can then proceed to use its methods and properties.</p>
<p>To save yourself a lot of grief when using COM interfaces, make sure you check out the Compiler COM Support classes:</p>
<table align="center" cellpadding="2" width="500">
<tbody>
<tr bgcolor="#999999">
<td width="100"><b>Class</b></td>
<td><b>Purpose</b></td>
</tr>
<tr>
<td bgcolor="#acacac" width="100">_bstr_t</td>
<td>Wraps the <b>BSTR</b> type to provide useful operators and<br />
                  methods</td>
</tr>
<tr>
<td bgcolor="#acacac" width="100">_com_ptr_t</td>
<td>Encapsulates COM interface pointers, and automates the<br />
                  required calls to <b>AddRef</b>, <b>Release</b>, and<br />
                  <b>QueryInterface</b>.</td>
</tr>
<tr>
<td bgcolor="#acacac" width="100">_variant_t</td>
<td>Wraps the <b>VARIANT</b> type to provide useful operators<br />
                  and methods.</td>
</tr>
<tr></tr>
</tbody>
</table>
<p>That should hopefully be enough to get you started with using XML in C++. I&#8217;ll save a more detailed XML C++tutorial for a future article.</p>
<img src="http://www.softimageblog.com/?ak_action=api_record_view&id=42&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.softimageblog.com/archives/42/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>XML- SceneToc vs. dotXSI</title>
		<link>http://www.softimageblog.com/archives/15#utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=xml-scenetoc-vs-dotxsi</link>
		<comments>http://www.softimageblog.com/archives/15#comments</comments>
		<pubDate>Tue, 15 Mar 2005 20:05:03 +0000</pubDate>
		<dc:creator>Helge Mathee</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.xsi-blog.com/?p=15</guid>
		<description><![CDATA[XML is going to be the next standard for 3d scene descriptions, is it not?]]></description>
			<content:encoded><![CDATA[<p>A lot of companies are going XML lately. As Sony announced at the Alias User Event in Los Angeles (December 3rd, 2004), XML was used for storing a lot of different types of assets for the production of Spiderman and Spiderman 2. Omation spoke up at the Softimage XSI usergroup meeting in Los Angeles (March 10th, 2005), letting the community know how Omation&#8217;s pipeline is built on XML to store scene/model information. Just to name two.</p>
<p>XML (Extensible Markup Language) was originally developed for web documents. Designers can create their own tags to store custom data in an organized way to transfer information between applications using XML. Softimage started to support the standard for the ScnToc files, which store a summary of the scene elements in a XML file. With these files, production facilities e. g. are able to switch the reference models used in a scene without opening the scenefile, but by changing ASCII text instead, which is much faster, and even more importantly batchable throughout a whole sequence of scenes.</p>
<p>Furthermore Softimage&#8217;s XSI now supports XML as the standard for all layout/view related files. Layouts, views and the new relational views are all based of the ASCII standard. Also this feature enables large production to deal much more flexibly with their interface and generate new relational content on the fly.</p>
<p>dotXSI, Softimage&#8217;s own interactive media format, which supports export as ASCII or Binary compressed files, already stores a huge amount of scene-data, including geometry data, animation, camera information, lights etc&#8230;.constraints, XSI specific operators (ala cluster shape combine), and Animation Mixer relevant data are not supported yet. Softimage took an amazing step by implementing the dotXSI standard, giving the users the ability to store model data in ASCII and enabling them to modify the information externaly of XSI. More than that: There are plugins for the major 3D packages to import/export dotXSI files, Softimage provides an external 3d viewer for dotXSI files, all major conversion programs support dotXSI by now!</p>
<p>Sounding like the ultimate solution for 3D data storage, dotXSI became more and more popular. From a non-linear pipeline point of view though, dotXSI, as well as the binary EMDL and SCN file solution are only partially applicable.</p>
<p>Working with static data such as EMDLs of dotXSI files, the only way to transport information from one model to another one is copying. Practically that means: Open a scene, import two models, copy the UVs from one model to the next, as an example. Considering the size of nowadays productions, the amount of rigs/models they are dealing with and the fact that schedules become tighter and even tighter, the process of copying is simply too slow and inefficient. dotXSI is a great feature of the non-linear package XSI, though the standard itself is totally linear.</p>
<p>That raises the question for alternatives&#8230; Here&#8217;s the idea (which is already in use here at Omation): Using XML for custom storage of scene/model information, which enables the users to reuse the data without  importing the whole dataset.</p>
<p><em><a id="p159" href="/userContent/upload/2007/01/cube.zip">Description of a cube in XML 1.0</a> (IE 5.0 or higher)</em><br />
<em><a id="p158" href="/userContent/upload/2007/01/camera.zip">Description of a camera in XML 1.0</a> (IE 5.0 or higher)</em><br />
<em><a id="p160" href="/userContent/upload/2007/01/light.zip">Description of a light in XML 1.0</a> (IE 5.0 or higher)</em></p>
<p>Example:</p>
<p>XML description of a &#8220;texture-asset&#8221; including Geometry, Clusters, UVs, Rendertrees, Expressions. There could be custom tools which read the whole dataset and generate a model with geometry, applied UVs, materials etc. There can also be a custom tool which only reads the UV information, one which only reads cluster information and applies this information to an existing model in the scene, or even better, a XML description of a model, so you never have to open an EMDL file to actually apply these changes. Furthermore, all these processes would be batchable, so e.g. to get the current UVs on a bunch of models is not a problem, and can be executed by a CRON job on a server on a schedule-basis. The advantage over dotXSI/ScnToc is the non-linearity in a pipeline point of view. Models/Assets/Scenes can be broken up in discreet units for different departments/people to work on, and can be merged together on a per-unit level basis. So e.g. as soon as the texture part of the model is ready all related models get the most current UVs/materials.</p>
<p>This way of dealing with data changes the process of &#8220;copying&#8221; to a process of &#8220;applying&#8221; changes in an incremental way. And this is possible on a per model/per sequence/per show basis.</p>
<img src="http://www.softimageblog.com/?ak_action=api_record_view&id=15&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://www.softimageblog.com/archives/15/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>
