Vamos a continuar mostrando algo más de la relación que XML tiene con ADO.NET.
En la publicación anterior, mostramos la forma más simple de obtener documentos en formato XML o de enlazar un componente de interfaz de usuario con un documento XML.
Ahora vamos a mostrar las posibilidades que XML nos brinda cuando de relaciones se trata; para ello vamos a volver a utilizar las tablas de otras publicaciones, en este caso utilizaremos Provincias y Departamentos donde sabemos que existe un relación de uno a muchos.
El ejercicio consiste en generar un documento XML que muestre la información de las provincias y sus departamentos. Para ello vamos a modificar el formulario desarrollado en la publicación anterior de manera que quede así:

Ahora el formulario tiene un CheckBox que utilizaremos para modificar el comportamiento de la generación del documento XML, el resto son botones para controlar la ejecución del programa. El código es el siguiente:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm6.aspx.cs" Inherits="ADO2.WebForm6" ValidateRequest="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Panel ID="pnlProvincias" runat="server" GroupingText="Provincias">
<div style="float:left; width:25%; padding-right:10px;">
<asp:GridView ID="gvProvincias" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID"
EmptyDataText="There are no data records to display.">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True"
SortExpression="ID" />
<asp:BoundField DataField="Nombre" HeaderText="Nombre"
SortExpression="Nombre" />
</Columns>
</asp:GridView>
</div>
<div>
<div style="float:left; padding-right:10px">
<asp:TextBox ID="txtXML" runat="server" Width="40%" Height="300px" TextMode="MultiLine" ></asp:TextBox>
</div>
<div>
<asp:GridView ID="gvXML" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID"
EmptyDataText="There are no data records to display.">
<Columns>
<asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True"
SortExpression="ID" />
<asp:BoundField DataField="Nombre" HeaderText="Nombre"
SortExpression="Nombre" />
</Columns>
</asp:GridView>
</div>
</div>
<div style="clear:both;">
<br />
<asp:CheckBox ID="cbRelationNested" runat="server" Text="Fijar Relaciones" TextAlign="Left" />
<asp:Button ID="btnGenerateXML" runat="server" Text="Generar XML"
onclick="btnGenerateXML_Click" />
<asp:Button ID="btnSaveXML" runat="server" Text="Grabar XML (ProvinciaDepartamento.xml)"
onclick="btnSaveXML_Click" />
<asp:Button ID="btnLoadXML" runat="server" Text="Cargar desde XML (ProvinciaDepartamento.xml)"
onclick="btnLoadXML_Click" />
</div>
</asp:Panel>
</div>
</form>
</body>
</html>
Veamos el código asociado a este formulario web, como en el ejemplo anterior los métodos para controlar los eventos son estos:
#region Eventos del formulario
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
MyDataBind();
}
}
protected void btnGenerateXML_Click(object sender, EventArgs e)
{
GenerateXML();
}
protected void btnSaveXML_Click(object sender, EventArgs e)
{
SaveXML();
}
protected void btnLoadXML_Click(object sender, EventArgs e)
{
LoadXML();
}
#endregion
En los métodos para enlazar el primer GridView vamos a crear un objeto DataSet con relaciones de acuerdo al siguiente código:
/// <summary>
/// Enlaza los datos con los controles de la interfaz de usuario
/// </summary>
protected void MyDataBind()
{
gvProvincias.DataSource = MyDataLoad();
gvProvincias.DataBind();
}
/// <summary>
/// Carga los datos de la base de datos en un DataSet
/// </summary>
/// <returns>DataSet</returns>
protected DataSet MyDataLoad()
{
SqlConnection mySqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["Postal"].ConnectionString);
SqlCommand mySqlCommand = new SqlCommand();
mySqlCommand.Connection = mySqlConnection;
DataSet myDataSet = new DataSet();
SqlDataAdapter mySqlDataAdapter;
mySqlCommand.CommandText = "SELECT [ID], [Nombre] FROM [Provincia]";
mySqlCommand.CommandType = CommandType.Text;
mySqlDataAdapter = new SqlDataAdapter(mySqlCommand);
mySqlDataAdapter.Fill(myDataSet, "Provincia");
mySqlCommand.CommandText = "SELECT [ID], [idProvincia], [Nombre] FROM [Departamento]";
mySqlCommand.CommandType = CommandType.Text;
mySqlDataAdapter = new SqlDataAdapter(mySqlCommand);
mySqlDataAdapter.Fill(myDataSet, "Departamento");
DataColumn myParentColumn = myDataSet.Tables["Provincia"].Columns["ID"];
DataColumn myChildColumn = myDataSet.Tables["Departamento"].Columns["idProvincia"];
DataRelation myRealtion = new DataRelation("Provincia_Departamento", myParentColumn, myChildColumn);
myRealtion.Nested = cbRelationNested.Checked;
myDataSet.Relations.Add(myRealtion);
return myDataSet;
}
Observen que la propiedad "Nested" de la relación se fija de acuerdo al valor del CheckBox, esto nos permite "jugar" con la forma en que se genera el documento XML.
Los botones invocan a los siguientes métodos:
/// <summary>
/// Genera una cadena (string) con el contenido del DataSet
/// el formato de la cadena es XML
/// </summary>
protected void GenerateXML()
{
DataSet myDataSet = MyDataLoad();
String temp = myDataSet.GetXml();
txtXML.Text = temp;
}
/// <summary>
/// Graba el contenido del DataSet en un archivo
/// el formato del archivo es XML con XSD
/// </summary>
protected void SaveXML()
{
DataSet myDataSet = MyDataLoad();
String fileName = Server.MapPath("~/ProvinciaDepartamento.xml");
myDataSet.WriteXml(fileName, XmlWriteMode.WriteSchema);
// Es posible grabar solamente la definición del esquema
fileName = Server.MapPath("~/ProvinciaDepartamento.xsd");
myDataSet.WriteXmlSchema(fileName);
}
/// <summary>
/// Carga un DataSet desde un archivo en formato XML
/// el formato ademas puede incluir la definicion del esquema
/// </summary>
protected void LoadXML()
{
DataSet myDataSet = new DataSet();
String fileName = Server.MapPath("~/ProvinciaDepartamento.xml");
if (System.IO.File.Exists(fileName))
{
myDataSet.ReadXml(fileName, XmlReadMode.ReadSchema);
}
// Enlaza el DataSet con un componente de interfaz de usuario
gvXML.DataSource = myDataSet;
gvXML.DataBind();
}
Salvo los nombres de los archivos, es el mismo código que en el ejercicio anterior.
Hay que ejecutarlo y ver como se genera el documento XML, 
Para leer fuera de línea: XML y ADO NET - parte 2.pdf (137,06 kb)