Windows Live Agents: XML Normalization


Buddyscript is capable of managing xmls with ease, and accessing external databases for example with a web service.

But sometimes we may need to have non-trivial xmls locally, and those xmls may have complex structures not so easy to handle.

This is the graphical representation of a sample xml that may not be easy to read:

This is a possible xml content:

<?xml version="1.0" encoding="utf-8"?>
<fields>
<field>
<field1>1</field1>
<field2>
<value>121</value>
<value>122</value>
<value>123</value>
</field2>
<field3>13</field3>
</field>
<field>
<field1>2</field1>
<field2>
<value>221</value>
<value>222</value>
<value>223</value>
</field2>
<field3>23</field3>
</field>
</fields>

The buddyscript code to read this xml you could incorrectly think that it might be something like this:

datasource Table1XMLFileLoader() => Field1, Field2, Field3
file
table1.xml
simple xml
fields
field {loop=content}
field1
field2
value {loop=content}
field3

The problem is that if you execute this code, the agent can incorrectly loop the values, because it doesn't supports multiple anidated loops. This gets worse with three or more "looping fields". The XML should only have one looping tag/element.

So, how to fix this limitation? Well, I do it applying what I call xml normalization: Like with a DB normalization, re-estructure your xml in multiple files, splitted so that each sub-table now only has as simple 1-1 relations (but they can be repeated as many times as wanted, that'sd the trick ;)

This is the graphical representation of the normalized xmls:

This are our normalized xmls:

Table1_1.xml

<?xml version="1.0" encoding="utf-8"?>
<fields>
<field>
<field1>1</field1>
<field2>121</field2>
</field>
<field>
<field1>1</field1>
<field2>122</field2>
</field>
<field>
<field1>1</field1>
<field2>123</field2>
</field>
<field>
<field1>2</field1>
<field2>221</field2>
</field>
<field>
<field1>2</field1>
<field2>222</field2>
</field>
<field>
<field1>2</field1>
<field2>223</field2>
</field>
</fields>

Table2_2.xml

<?xml version="1.0" encoding="utf-8"?>
<fields>
<field>
<field1>1</field1>
<field3>13</field3>
</field>
<field>
<field1>2</field1>
<field3>23</field3>
</field>
</fields>

And finally the buddyscript code to read them, this time correctly:

datasource Table1_1XMLFileLoader() => Field1, Field2
file
table1.xml
simple xml
fields
field {loop=content}
field1
field2

datasource Table1_2XMLFileLoader() => Field1, Field3
file
table1.xml
simple xml
fields
field {loop=content}
field1
field3

We can now do simple querys against each of the sub-tables and cross the results (with <field1>) to obtain one or more registers (original Table1 <field>) with multiple subfields (origintal Table1 <field2>).

Comments?

Posted by Kartones on 2008-03-24