Home > Articles > Programming > Windows Programming

  • Print
  • + Share This
Like this article? We recommend

Generating XML

Now that we have explored parsing XML data, we will discuss how to create DataSet content and generate XML output. The same heuristics apply for generate XML as they do for parsing it with the DataSet. Create a table for each element, a column for each attribute or element with simple textual content, and a column for the foreign-key relationship between the tables. Listing 4 is the code for build a DataSet that mirrors the PO.xml document.

Listing 4: DataSet XML Generation

using System;
using System.Data;

namespace XmlDotNet
{
  
public class DataSetCreateDemo
{

public static void Main()
{
  // call a routine to build the PO structure
  DataSet ds = BuildPO();

  // link the tables in the PO
  BuildTableRelationships(ds);

  // add the data
  AddData(ds);

  // print out the XML schema document
  Console.WriteLine("PO schema document");
  Console.WriteLine("-----------------------------------------");
  Console.WriteLine(ds.GetXmlSchema());
  Console.WriteLine();

  // print out the XML instance document
  Console.WriteLine("PO instance document");
  Console.WriteLine("-----------------------------------------");
  Console.WriteLine(ds.GetXml());

}

public static DataSet BuildPO()
{
  // create the DataSet
  DataSet ds = new DataSet("PoDS");
     
     
  // Create the Purchase Order element
  // as a DataTable
  DataTable po = BuildPOTable(); 
  ds.Tables.Add(po);
     

  // Create the BillToAddress element
  // as a DataTable
  DataTable billto = BuildAddressTable("BillToAddress"); 
  ds.Tables.Add(billto);
   
  // Create the ShipToAddress element
  // as a DataTable
  DataTable shipto = BuildAddressTable("ShipToAddress"); 
  ds.Tables.Add(shipto);
   
  // Create the LineItem elements
  // as a DataTable
  DataTable item = BuildLineItemTable(); 
  ds.Tables.Add(item);
   

  return ds;
}

public static DataTable BuildPOTable()
{
  // Create the PO element
  // as a DataTable
  DataTable po = new DataTable("PurchaseOrder");
     
  // add the attributes to the PO element through
  // DataColumns
  po.Columns.Add("Number",typeof(string));
  po.Columns.Add("OrderDate",typeof(string));
     
  // add the hidden (from XML output) foreign key column
  DataColumn col =
  po.Columns.Add("PurchaseOrder_ID",typeof(string));
  col.ColumnMapping = MappingType.Hidden; 


  return po;
}

public static DataTable BuildAddressTable(string name)
{
  // Create the Address element
  // as a DataTable
  DataTable addr = new DataTable(name);
  addr.Columns.Add("Street",typeof(string));
  addr.Columns.Add("City",typeof(string));
  addr.Columns.Add("State",typeof(string));
  addr.Columns.Add("ZipCode",typeof(string));
     
  // add the hidden (from XML output) foreign key column
  DataColumn col =
  addr.Columns.Add("PurchaseOrder_ID",typeof(string));
  col.ColumnMapping = MappingType.Hidden; 
     
  return addr;
}

public static DataTable BuildLineItemTable()
{
  // Create the LineItem element
  // as a DataTable
  DataTable item = new DataTable("LineItem");
  
  // add each column with a mapping to XML attribute display
  DataColumn col = item.Columns.Add("Name",typeof(string));
  col.ColumnMapping = MappingType.Attribute; 
  col = item.Columns.Add("Description",typeof(string));
  col.ColumnMapping = MappingType.Attribute; 
  col = item.Columns.Add("SKU",typeof(string));
  col.ColumnMapping = MappingType.Attribute; 
  col = item.Columns.Add("Price",typeof(decimal));
  col.ColumnMapping = MappingType.Attribute; 
  col = item.Columns.Add("Qty",typeof(int));
  col.ColumnMapping = MappingType.Attribute; 
     
  // add the hidden (from XML output) foreign key column
  col = item.Columns.Add("PurchaseOrder_ID",typeof(string));
  col.ColumnMapping = MappingType.Hidden; 

  return item;
}

public static void BuildTableRelationships(DataSet ds)
{
  // create relationship between BillToAddress element
  // and PurchaseOrder element, and make it nested elements
  // in XML output
  DataRelation dr = new DataRelation("POBillTo",
  ds.Tables["PurchaseOrder"].Columns["PurchaseOrder_ID"],
  ds.Tables["BillToAddress"].Columns["PurchaseOrder_ID"],
  true);
  dr.Nested = true;
  ds.Relations.Add(dr);

  // create relationship between ShipToAddress element
  // and PurchaseOrder element, and make it nested elements
  // in XML output
  dr = new DataRelation("POShipTo",      
    ds.Tables["PurchaseOrder"].Columns["PurchaseOrder_ID"],
  ds.Tables["ShipToAddress"].Columns["PurchaseOrder_ID"],
  true);
  dr.Nested = true;
  ds.Relations.Add(dr);

  // create relationship between LineItem elements
  // and PurchaseOrder element, and make it nested elements
  // in XML output
  dr = new DataRelation("POLineItem",
      ds.Tables["PurchaseOrder"].Columns["PurchaseOrder_ID"],
  ds.Tables["LineItem"].Columns["PurchaseOrder_ID"],
  true);
  dr.Nested = true;
  ds.Relations.Add(dr);

}

public static void AddData(DataSet ds)
{
     
  // add root PurchaseOrder element
  DataTable po = ds.Tables["PurchaseOrder"];
  po.Rows.Add(new object[] {"1001","1/2/01", "0"});

  // add BillToAddress element 
  DataTable billto = ds.Tables["BillToAddress"];
  billto.Rows.Add(new object[] {"101 Main Street",
   "Charlotte","NC","28273","0"});
   
  // add ShipToAddress element 
  DataTable shipto = ds.Tables["ShipToAddress"];
  shipto.Rows.Add(new object[] {"101 Main Street",
   "Charlotte","NC","28273","0"});

  // add LineItem elements
  DataTable item = ds.Tables["LineItem"];
  item.Rows.Add(new object[] {"Computer Desk", 
   "Wood desk for computer","12345A123",
   "499.99", "1","0"});
  item.Rows.Add(new object[] {"Monitor",
   "Computer Monitor 19-Inch","19A123",
   "299.99","1","0"});
  item.Rows.Add(new object[] {"Computer",
   "Pentium 4 Computer","411111","999.99",
   "1","0"});
  item.Rows.Add(new object[] {"Mouse",
   "Computer Mouse","233B1","49.99","1","0"});

}


}
}

The content generation begins with building the DataTable and DataColumn structure for each of the elements in the purchase order documents. Creating columns is fairly simple if you want to accept the default mapping to an XML element with textual content represented by the ColumnMapping property of the DataColumn set to Element. For columns that you want to display as XML attributes, change the ColumnMapping property of the DataColumn to Attribute. For the key columns that you create to link tables, use the Hidden enum for the ColumnMapping so that no XML output is generated. After you define the tables, link them using the DataRelation object. Pass in the parent and child columns and pass true as the last parameter to create the foreign key and unique constraints in the DataTable. Also set the Nested property to true so that the XML child elements are displayed underneath their parents.

The final step is to add in the data. Notice the aggregated load used to fill in an object array and pass it directly in the row. After you have created your DataSet, display the XML by calling for an XML string or its schema and its data contents with the GetXml and GetXmlSchema calls. (See Listing 5.)

Listing 5: DataSet XML-Generation Output

PO schema document
--------------------------------------------
<?xml version="1.0" encoding="utf-16"?>
<xs:schema id="PoDS" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:
msdata="urn:schemas-microsoft-com:xml-msdata">
 <xs:element name="PoDS" msdata:IsDataSet="true">
  <xs:complexType>
   <xs:choice maxOccurs="unbounded">
    <xs:element name="PurchaseOrder">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="Number" 
        type="xs:string" minOccurs="0" 
        msdata:Ordinal="0" />

       <xs:element name="OrderDate" type="xs:string"[ccc] 
        minOccurs="0"[ccc]
        msdata:Ordinal="1" />
       <xs:element name="BillToAddress" minOccurs="0"[ccc] 
        maxOccurs="unbounded">
        <xs:complexType>
         <xs:sequence>
          <xs:element name="Street" type="xs:string"[ccc] 
           minOccurs="0" msdata:Ordinal="0" />
          <xs:element name="City" type="xs:string"[ccc] 
           minOccurs="0" msdata:Ordinal="1" />
          <xs:element name="State" type="xs:string"[ccc] 
           minOccurs="0" msdata:Ordinal="2" />
          <xs:element name="ZipCode" type="xs:string"[ccc]
           minOccurs="0" msdata:Ordinal="3" />
         </xs:sequence>
         <xs:attribute name="PurchaseOrder_ID"[ccc] 
          type="xs:string" use="prohibited" />
        </xs:complexType>
       </xs:element>
       <xs:element name="ShipToAddress" minOccurs="0"[ccc] 
        maxOccurs="unbounded">
        <xs:complexType>
         <xs:sequence>
          <xs:element name="Street" type="xs:string"[ccc]
           minOccurs="0" msdata:Ordinal="0" />
          <xs:element name="City" type="xs:string"[ccc]
           minOccurs="0" msdata:Ordinal="1" />
          <xs:element name="State" type="xs:string"[ccc] 
           minOccurs="0" msdata:Ordinal="2" />
          <xs:element name="ZipCode" type="xs:string"[ccc] 
           minOccurs="0" msdata:Ordinal="3" />
         </xs:sequence>
         <xs:attribute name="PurchaseOrder_ID"[ccc] 
          type="xs:string" use="prohibited" />
        </xs:complexType>
       </xs:element>
       <xs:element name="LineItem" minOccurs="0"[ccc] 
        maxOccurs="unbounded">
        <xs:complexType>
         <xs:attribute name="Name" type="xs:string" />
         <xs:attribute name="Description" type="xs:string" />
         <xs:attribute name="SKU" type="xs:string" />
         <xs:attribute name="Price" type="xs:decimal" />
         <xs:attribute name="Qty" type="xs:int" />
         <xs:attribute name="PurchaseOrder_ID"[ccc] 
          type="xs:string" use="prohibited" />
        </xs:complexType>
       </xs:element>
      </xs:sequence>
      <xs:attribute name="PurchaseOrder_ID"[ccc] 
       type="xs:string" use="prohibited" />
     </xs:complexType>
    </xs:element>
   </xs:choice>
  </xs:complexType>
  <xs:unique name="Constraint1">
   <xs:selector xpath=".//PurchaseOrder" />
   <xs:field xpath="@PurchaseOrder_ID" />
  </xs:unique>
  <xs:keyref name="POLineItem" refer="Constraint1"[ccc] 
   msdata:IsNested="true">
   <xs:selector xpath=".//LineItem" />
   <xs:field xpath="@PurchaseOrder_ID" />
  </xs:keyref>
  <xs:keyref name="POShipTo" refer="Constraint1"[ccc] 
   msdata:IsNested="true">
   <xs:selector xpath=".//ShipToAddress" />
   <xs:field xpath="@PurchaseOrder_ID" />
  </xs:keyref>
  <xs:keyref name="POBillTo" refer="Constraint1"[ccc] 
   msdata:IsNested="true">
   <xs:selector xpath=".//BillToAddress" />
   <xs:field xpath="@PurchaseOrder_ID" />
  </xs:keyref>
 </xs:element>
</xs:schema>

PO instance document
--------------------------------------------
<PoDS>
 <PurchaseOrder>
  <Number>1001</Number>
  <OrderDate>1/2/01</OrderDate>
  <BillToAddress>
   <Street>101 Main Street</Street>
   <City>Charlotte</City>
   <State>NC</State>
   <ZipCode>28273</ZipCode>
  </BillToAddress>
  <ShipToAddress>
   <Street>101 Main Street</Street>
   <City>Charlotte</City>
   <State>NC</State>
   <ZipCode>28273</ZipCode>
  </ShipToAddress>
  <LineItem Name="Computer Desk"[ccc] 
   Description="Wood desk for computer"[ccc] 
   SKU="123 45A123" Price="499.99" Qty="1" />
  <LineItem Name="Monitor"[ccc] 
   Description="Computer Monitor 19-Inch"[ccc] 
   SKU="19A123" Price="299.99" Qty="1" />
  <LineItem Name="Computer"[ccc] 
   Description="Pentium 4 Computer"[ccc] 
   SKU="411111" Price="999.99" Qty="1" />
  <LineItem Name="Mouse"[ccc] 
   Description="Computer Mouse"[ccc] 
   SKU="233B1" Price="49.99" Qty="1" />
 </PurchaseOrder>
</PoDS>
  • + Share This
  • 🔖 Save To Your Account