Using XSLT files with the new XMLDataSource control
VS 2005 RTM (.net framework 2.0)
Target:
Intermediate Developers
Consider you have an XML file like this:
<Employees>
<Employee
FirstName="Tom"
LastName="Jones" CustomerId="1" />
<Employee
FirstName="John"
LastName="Doe" CustomerId="2" />
</Employees>
You wish to display the data in a DropDownList with the DataTextField set to the FirstName and the DataValueField set to the CustomerId..
..and you do not want to write any code ;-)
Here is how you do it.
Drag and
drop an
XmlDataSource
and DropDownList
control on to your page. Set their properties like so:
<asp:XmlDataSource
ID="XmlDataSource1"
runat="server"
DataFile="~/Employees.xml"></asp:XmlDataSource>
<asp:DropDownList
ID="DropDownList1"
runat="server"
DataSourceID="XmlDataSource1"
DataTextField="FirstName"
DataValueField="CustomerId">
</asp:DropDownList>
Run the page.
The DropDownList will get rendered like so:
<select name="DropDownList1"
id="DropDownList1">
<option value="1">Tom</option>
<option value="2">John</option>
</select>
What if the XML file were like this (where
the values were elements instead of attributes)?
<Employees>
<Employee>
<FirstName>Tom</FirstName>
<LastName>Jones</LastName>
<CustomerId>1</CustomerId>
</Employee>
<Employee>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<CustomerId>2</CustomerId>
</Employee>
</Employees>
Our page will fail with the following error:
DataBinding:
'System.Web.UI.WebControls.XmlDataSourceNodeDescriptor'
does not contain a property with the name
'FirstName'.
The reason is that attributes of XML elements are
promoted to properties and exposed through the XmlDataSource
during databinding. In our case, FirstName
is an element instead of an attribute which leads to the
error.
So what can we do about this? Easy, we have to figure out
how to transform the FirstName, CustomerId
so that they become attributes of the parent node - Employee. In other words, we need to transform the second XML
file so that it looks like the first XML file. This is
were XSLTs come in. Explaining XLSTs is beyond the scope
of this post. Please use your search engine to learn more
J
XSLT Reference
The XmlDataSource
allows you to specify an XSLT file where you can define a
transformation that will be applied to the DataFile you specified.
Add an XSL file to your project and enter the following (In brief, the XSLT below will transform the XML file resulting in the FirstName, CustomerId elements becoming attributes of the Employee node)
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template
match="Employees">
<Employees>
<xsl:apply-templates
select="Employee"/>
</Employees>
</xsl:template>
<xsl:template
match="Employee">
<Employee>
<xsl:attribute
name="FirstName">
<xsl:value-of
select="FirstName"/>
</xsl:attribute>
<xsl:attribute
name="CustomerId">
<xsl:value-of
select="CustomerId"/>
</xsl:attribute>
</Employee>
</xsl:template>
</xsl:stylesheet>
Set the XmlDataSource’s
TransformFile property to point to this XSL file. Our page will look
like this:
<asp:XmlDataSource
ID="XmlDataSource1"
runat="server"
DataFile="~/Employees.xml"
TransformFile="~/XSLTFile.xsl"></asp:XmlDataSource>
<asp:DropDownList
ID="DropDownList1"
runat="server"
DataSourceID="XmlDataSource1"
DataTextField="FirstName"
DataValueField="CustomerId">
</asp:DropDownList>
The DropDownList will now get rendered like so:
<select name="DropDownList1"
id="DropDownList1">
<option value="1">Tom</option>
<option value="2">John</option>
</select>
What if you wanted to display the FirstName,
LastName in the DataTextField separated by a comma?
Easy! Change the XSL
file to this:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template
match="Employees">
<Employees>
<xsl:apply-templates
select="Employee"/>
</Employees>
</xsl:template>
<xsl:template
match="Employee">
<Employee>
<xsl:attribute
name="FullName">
<xsl:value-of
select="FirstName"/>
<xsl:text
xml:space="preserve">, </xsl:text>
<xsl:value-of
select="LastName"/>
</xsl:attribute>
<xsl:attribute
name="CustomerId">
<xsl:value-of
select="CustomerId"/>
</xsl:attribute>
</Employee>
</xsl:template>
</xsl:stylesheet>
Note that we changed the attribute name to
FullName.
Note also the xml:space attribute which specifies that
the space after the comma should be preserved.
Now change the page to this:
<asp:XmlDataSource
ID="XmlDataSource1"
runat="server"
DataFile="~/Employees.xml"
TransformFile="~/XSLTFile.xsl"></asp:XmlDataSource>
<asp:DropDownList
ID="DropDownList1"
runat="server"
DataSourceID="XmlDataSource1"
DataTextField="FullName"
DataValueField="CustomerId">
</asp:DropDownList>
The DropDownList will get rendered like this:
<select name="DropDownList1"
id="DropDownList1">
<option
value="1">Tom, Jones</option>
<option
value="2">John, Doe</option>
</select>
All this without writing a single line of code (if you exclude the xsl file you wrote)!
Time to get rid of the custom DropDownList control I wrote in v 1.1 that specifically did this!