Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
swdev:dotnet:using_xml [2010/10/18 15:01]
smayr
swdev:dotnet:using_xml [2011/11/02 16:13] (current)
smayr
Line 1: Line 1:
-== Using XML ==+= Using XML =
  
 Editing XML Editing XML
  
-Normally, binding a ListView to a datasource (the xml) and let WPF databinding handle the update of the XML data automatically. To do this you could create a [[http://msdn.microsoft.com/en-us/library/84sxtbxh(VS.80).aspx|DataSet from your XML]] and then bind that using ListView.ItemsSource. You would then create a DataTemplate to define the visual representation of a record in your xml. This could be input controls that'd allow you do directly edit the record within your listview. If you prefer a master-detail style view you would bing the detail view to the current item of your listview (e.g. UserControl.DataContext={Binding CurrentItem, ElementName=myListView}). The rest will be handled by WPF. UPDATE: Here is an [[http://msdn.microsoft.com/en-us/library/cc165615.aspx|example]] how you could even bind direcly to your XDocument, so so you do not necessarily have to use DataSets. (Source: [[http://stackoverflow.com/questions/1659734/wpf-and-c-gridview-row-selection-and-xml-datasource-how-to-make-the-connecti|bitbonk on StackOverflow.com]])+Normally, binding a ListView to a datasource (the xml) and let WPF databinding handle the update of the XML data automatically. To do this you could create a [[http://msdn.microsoft.com/en-us/library/84sxtbxh(VS.80).aspx|DataSet from your XML]] and then bind that using ListView.ItemsSource. You would then create a DataTemplate to define the visual representation of a record in your xml. This could be input controls that'd allow you do directly edit the record within your listview. If you prefer a master-detail style view you would bing the detail view to the current item of your listview (e.g. UserControl.DataContext={Binding CurrentItem, ElementName=myListView}). The rest will be handled by WPF. UPDATE: Here is an [[http://msdn.microsoft.com/en-us/library/cc165615.aspx|example]] how you could even bind directly to your XDocument, so so you do not necessarily have to use DataSets. (Source: [[http://stackoverflow.com/questions/1659734/wpf-and-c-gridview-row-selection-and-xml-datasource-how-to-make-the-connecti|bitbonk on StackOverflow.com]])
    
-=== Parsing XML ===+== Parsing XML ==
  
 Example (Source: [[http://stackoverflow.com/questions/55828/best-practices-to-parse-xml-files|Lukas Šalkauskas]]): Example (Source: [[http://stackoverflow.com/questions/55828/best-practices-to-parse-xml-files|Lukas Šalkauskas]]):
Line 38: Line 38:
   * [[http://msdn.microsoft.com/en-us/library/bb387098.aspx|LINQ to XML]]   * [[http://msdn.microsoft.com/en-us/library/bb387098.aspx|LINQ to XML]]
   * [[http://msdn.microsoft.com/en-us/library/182eeyhh.aspx|Intro to XML Serialization]]   * [[http://msdn.microsoft.com/en-us/library/182eeyhh.aspx|Intro to XML Serialization]]
-=== Using LINQ with XML === 
  
-Example: (Source: [[http://stackoverflow.com/questions/1659734/wpf-and-c-gridview-row-selection-and-xml-datasource-how-to-make-the-connecti|Will]]+== Using LINQ with XML == 
 + 
 +Example: (Source: [[http://stackoverflow.com/questions/1659734/wpf-and-c-gridview-row-selection-and-xml-datasource-how-to-make-the-connecti|StackOverflow.com]])
 <code csharp> <code csharp>
 XDocument xml = XDocument.Load(@"D:\devel\VS\pchart\charts.xml"); XDocument xml = XDocument.Load(@"D:\devel\VS\pchart\charts.xml");
Line 49: Line 50:
 { {
   chartListView.Items.Add(new {    chartListView.Items.Add(new { 
-    Name = record.Attribute("Name").Value,  +      Name = record.Attribute("Name").Value,  
-    Type = record.Attribute("Type").Value,  +      Type = record.Attribute("Type").Value,  
-    defaultFontName = record.Attribute("defaultFontName").Value,  +      defaultFontName = record.Attribute("defaultFontName").Value,  
-    defaultFontSize = record.Attribute("defaultFontSize").Value,  +      defaultFontSize = record.Attribute("defaultFontSize").Value,  
-    ID = record.Attribute("ID").Value +      ID = record.Attribute("ID").Value 
     }     }
   );   );
Line 79: Line 80:
 Source: [[http://stackoverflow.com/questions/472669/c-freely-convert-between-listt-and-ienumerablet|David B, Frederik Gheysels]] Source: [[http://stackoverflow.com/questions/472669/c-freely-convert-between-listt-and-ienumerablet|David B, Frederik Gheysels]]
  
-== References ==+Examples = 
 +== Loading and Parsing an XML File into a Data Structure == 
 + 
 +For an XML file like this: 
 +<code xml> 
 +<?xml version="1.0"?> 
 +<Workshops xmlns=""> 
 +  <Workshop> 
 +    <Name>Acme's 12th Annual Continuing Education Workshop</Name> 
 +    <RecID>12</RecID> 
 +    <WorkshopID>AcmeWorkshop12</WorkshopID> 
 +    <VenueInfo> 
 +      <Organization>Orlando Marriott Lake Mary</Organization> 
 +      <AddressLn1>1501 International Parkway</AddressLn1> 
 +      <City>Lake Mary</City> 
 +      <StateProv>FL</StateProv> 
 +      <PostalCode>32746</PostalCode> 
 +      <PhoneHome>407.995.1100</PhoneHome> 
 +      <PhoneWork>800.380.7724</PhoneWork> 
 +      <Fax>407.995.1101</Fax> 
 +      <Website>www.marriotthotels.com</Website> 
 +    </VenueInfo> 
 +    <Days> 
 +      <DateTime>2008-06-11</DateTime> 
 +      <DateTime>2008-06-12</DateTime> 
 +    </Days> 
 +    <PricingDailyPackages> 
 +      <PricingPackage> 
 +        <Name>Premium</Name> 
 +        <Pricing>100</Pricing> 
 +      </PricingPackage> 
 +      <PricingPackage> 
 +        <Name>Standard</Name> 
 +        <Pricing>200</Pricing> 
 +      </PricingPackage> 
 +      <PricingPackage> 
 +        <Name>Other</Name> 
 +        <Pricing>200</Pricing> 
 +      </PricingPackage> 
 +    </PricingDailyPackages> 
 +  </Workshop> 
 +  <Workshop> 
 +    <Name>Acme's 13th Annual Continuing Education Workshop</Name> 
 +    <RecID>13</RecID> 
 +    <WorkshopID>AcmeWorkshop13</WorkshopID> 
 +    <VenueInfo> 
 +      <Organization>Orlando Marriott Lake Mary</Organization> 
 +      <AddressLn1>1501 International Parkway</AddressLn1> 
 +      <City>Lake Mary</City> 
 +      <StateProv>FL</StateProv> 
 +      <PostalCode>32746</PostalCode> 
 +      <PhoneHome>407.995.1100</PhoneHome> 
 +      <PhoneWork>800.380.7724</PhoneWork> 
 +      <Fax>407.995.1101</Fax> 
 +      <Website>www.marriotthotels.com</Website> 
 +    </VenueInfo> 
 +    <Days> 
 +      <DateTime>2009-06-15</DateTime> 
 +      <DateTime>2009-06-16</DateTime> 
 +    </Days> 
 +    <PricingDailyPackages> 
 +      <PricingPackage> 
 +        <Name>Premium</Name> 
 +        <Pricing>100</Pricing> 
 +      </PricingPackage> 
 +      <PricingPackage> 
 +        <Name>Standard</Name> 
 +        <Pricing>200</Pricing> 
 +      </PricingPackage> 
 +      <PricingPackage> 
 +        <Name>Other</Name> 
 +        <Pricing>200</Pricing> 
 +      </PricingPackage> 
 +    </PricingDailyPackages> 
 +  </Workshop> 
 +</Workshops> 
 +</code> 
 + 
 +To format XML content to fit in a data structure like this: 
 +<code csharp> 
 +    //======================================================================== 
 +    // Class TWorkshop 
 +    //======================================================================== 
 +    public class TWorkshop 
 +    { 
 +        public int RecID                          { get; set; } 
 +        public string WorkshopID                  { get; set; } 
 +        public string Name                        { get; set; } 
 +        public TContactInfo VenueInfo             { get; set; } 
 +        public List<DateTime> Days                { get; set; } 
 +        public List<TPricingPackage> PricingDailyPackages  { get; set; } 
 +        public string CancellationPolicy          { get; set; } 
 +        public string Instructions                { get; set; } 
 +        public string HotelAccommodations         { get; set; } 
 +  } 
 +</code> 
 + 
 +We can implement the logic in a function like this: 
 +<code csharp> 
 +//----------------------------------------------------------------------------------------- 
 +/// <summary> 
 +/// Load data from an XML file. 
 +/// </summary> 
 +/// <param name="AFilename">Filename of XML file to load</param> 
 +/// <returns>true if success, false if not</returns> 
 +//----------------------------------------------------------------------------------------- 
 +public bool LoadFromXmlFile(string AFilename) 
 +
 + if (System.IO.File.Exists(AFilename)) 
 +
 + xmldoc = XDocument.Load(AFilename); 
 + if (xmldoc != null) 
 +
 + // parse xml data and load into TWorkshopList object 
 + List<XElement> xmldata = new List<XElement>(); 
 + xmldata = xmldoc.Root.Elements("Workshop").ToList<XElement>(); 
 + 
 + foreach (XElement el in xmldata) 
 +
 + // create TWorkshop record 
 + TWorkshop currec = new TWorkshop(); 
 + 
 + // Parse xml record, and add it 
 + currec.VenueInfo.Clear(); 
 + currec.Name                         = el.Element("Name").Value; 
 + currec.WorkshopID                   = el.Element("WorkshopID").Value; 
 + currec.RecID                        = Convert.ToInt32(el.Element("RecID").Value); 
 + currec.VenueInfo.Organization       = el.Element("VenueInfo").Element("Organization").Value; 
 + currec.VenueInfo.Address.AddressLn1 = el.Element("VenueInfo").Element("AddressLn1").Value; 
 + currec.VenueInfo.Address.City       = el.Element("VenueInfo").Element("City").Value; 
 + currec.VenueInfo.Address.StateProv  = el.Element("VenueInfo").Element("StateProv").Value; 
 + currec.VenueInfo.Address.PostalCode = el.Element("VenueInfo").Element("PostalCode").Value; 
 + currec.VenueInfo.PhoneHome          = el.Element("VenueInfo").Element("PhoneHome").Value; 
 + currec.VenueInfo.PhoneWork          = el.Element("VenueInfo").Element("PhoneWork").Value; 
 + currec.VenueInfo.Fax                = el.Element("VenueInfo").Element("Fax").Value; 
 + currec.VenueInfo.Website            = el.Element("VenueInfo").Element("Website").Value; 
 + currec.CancellationPolicy           = el.Element("CancellationPolicy").Value; 
 + currec.Instructions                 = el.Element("Instructions").Value; 
 + currec.HotelAccommodations          = el.Element("HotelAccommodations").Value; 
 + 
 + // Days: extra processing 
 + currec.Days.Clear(); 
 + List<XElement> elDays = el.Element("Days").Elements("DateTime").ToList<XElement>(); 
 + foreach (XElement elDay in elDays) 
 +
 + string DateInInvariantCultureStrFmt = elDay.Value; 
 + DateTime DateLocalized = new DateTime(); 
 + try 
 +
 + DateLocalized = DateTime.Parse(DateInInvariantCultureStrFmt,  
 + System.Globalization.CultureInfo.InvariantCulture,  
 + System.Globalization.DateTimeStyles.None); 
 +
 + catch(FormatException exc) 
 +
 + throw new FormatException(string.Format("'{0}' is not in an acceptable format. [{1}]", DateInInvariantCultureStrFmt, exc.Message)); 
 +
 + currec.Days.Add(DateLocalized); 
 +
 + 
 + // PricingDailyPackages: extra processing 
 + currec.PricingDailyPackages.Clear(); 
 + List<XElement> elPkgs = el.Element("PricingDailyPackages").Elements("PricingPackage").ToList<XElement>(); 
 + foreach (XElement elPkg in elPkgs) 
 +
 + TPricingPackage pkg = new TPricingPackage(); 
 + pkg.Name    = elPkg.Element("Name").Value; 
 + pkg.Pricing = Convert.ToInt32(elPkg.Element("Pricing").Value); 
 + currec.PricingDailyPackages.Add(pkg); 
 +
 +  
 + // add TWorkshop record 
 + this.Add(currec); 
 +
 + 
 + // Success 
 + return true; 
 +
 + else  
 +
 + // Failed to load data from file 
 + return false; 
 +
 + 
 +
 + else 
 +
 + // Failed. File not found. 
 + return false; 
 +
 +}   
 +</code> 
 + 
 +== Example using XmlDocument, XmlElement, XmlNodeList == 
 + 
 +Sample Data: 
 +<code xml> 
 +<FittingSession> 
 +  <Instruments> 
 +    <Instrument Name="Cue" ProductCode="PROD_CUE" EarSide="0" MaxMemories="5"> 
 +      <AutofitEnvironments> 
 +        <AutofitEnvironment Name="Undefined" Index="0" Memory="0" /> 
 +        <AutofitEnvironment Name="Undefined" Index="0" Memory="1" /> 
 +        <AutofitEnvironment Name="Undefined" Index="0" Memory="2" /> 
 +        <AutofitEnvironment Name="Undefined" Index="0" Memory="3" /> 
 +      </AutofitEnvironments> 
 +      <ParametersConfig> 
 +        <Param Name="number_of_programs" Value="0" /> 
 +        <Param Name="program_switch_mode" Value="0" /> 
 +        . . . 
 +      </ParametersConfig> 
 +      <ParametersCustom> 
 +        . . . 
 +      </ParametersCustom> 
 +      <ParametersMemory> 
 +        <Memory Number="0"> 
 +          <Param Name="Input_mux" Value="0" /> 
 +          <Param Name="Preamp_gain0" Value="4" /> 
 +          . . . 
 +        </Memory> 
 +        <Memory Number="1"> 
 +          . . . 
 +        </Memory> 
 +        <Memory Number="2"> 
 +          . . . 
 +        </Memory> 
 +        <Memory Number="3"> 
 +          . . . 
 +        </Memory> 
 +      </ParametersMemory> 
 +    </Instrument> 
 +     
 +    <Instrument Name="Cue" ProductCode="PROD_CUE" EarSide="1" MaxMemories="5"> 
 +      . . . 
 +    </Instrument> 
 +     
 +  </Instruments> 
 +</FittingSession> 
 +</code> 
 + 
 +Code to load Xml document: 
 +<code csharp> 
 +///---------------------------------------------------------------------------------------- 
 +/// <summary> 
 +/// Load data from XML file. 
 +/// </summary> 
 +/// <param name="FileName"></param> 
 +///---------------------------------------------------------------------------------------- 
 +public void LoadFromXml(string FileName) 
 +
 +    // using System.Xml; 
 +    XmlDocument xmlDoc = new XmlDocument();  // create an xml document object. 
 +    xmlDoc.Load(FileName);                   // load the XML document from the specified file. 
 + 
 +    try 
 +    { 
 +        for (int side = 0; side < 2; side++) 
 +        { 
 +            // Get elements. 
 +            //XmlNodeList ParamConfigLst = xmlDoc["FittingSession"]["Instruments"]["Instrument"]["ParametersConfig"].GetElementsByTagName("Param"); 
 +            //XmlNodeList ParamMemoryLst = xmlDoc["FittingSession"]["Instruments"]["Instrument"]["ParametersMemory"].GetElementsByTagName("Param"); 
 +            //XmlNodeList ParamCustomLst = xmlDoc["FittingSession"]["Instruments"]["Instrument"]["ParametersCustom"].GetElementsByTagName("Param"); 
 +            XmlNodeList HI = xmlDoc["FittingSession"]["Instruments"].GetElementsByTagName("Instrument"); 
 +            XmlNodeList AutofitEnv = HI[side].ChildNodes[0].ChildNodes; 
 +            XmlNodeList ParamConfigLst = HI[side].ChildNodes[1].ChildNodes; 
 +            XmlNodeList ParamCustomLst = HI[side].ChildNodes[2].ChildNodes; 
 +            XmlNodeList ParamMemoryLst = HI[side].ChildNodes[3].ChildNodes; 
 + 
 +            // load data into package 
 +            LoadXmlNodeListToIntArray(AutofitEnv, m_InstrumentParams[side].AutofitEnvironments); 
 +            LoadXmlNodeListToDevParamList(ParamConfigLst, m_InstrumentParams[side].ParametersConfig); 
 +            LoadXmlNodeListToDevParamList(ParamCustomLst, m_InstrumentParams[side].ParametersCustom); 
 +            LoadXmlNodeListParamMemToDevParamList(ParamMemoryLst, m_InstrumentParams[side].ParametersMemory); 
 +        } 
 +    } 
 +    catch (Exception exc) 
 +    { 
 +        TAppLog.LogException("TFittingSession.LoadFromXml", exc); 
 +    } 
 +
 + 
 +///---------------------------------------------------------------------------------------- 
 +/// <summary> 
 +/// Load Xml node list to Device Parameter list. 
 +/// </summary> 
 +/// <param name="srcParamDataLst"></param> 
 +/// <param name="dstParamDataLst"></param> 
 +///---------------------------------------------------------------------------------------- 
 +private void LoadXmlNodeListToIntArray(XmlNodeList srcParamDataLst, int[] dstIntArray) 
 +
 +    int CurAutofitEnvMemIdx = 0; 
 +    for (int i = 0; i < srcParamDataLst.Count; i++) 
 +    { 
 +        CurAutofitEnvMemIdx              = Convert.ToInt32(srcParamDataLst[i].Attributes["Memory"].InnerText); 
 +        dstIntArray[CurAutofitEnvMemIdx] = Convert.ToInt32(srcParamDataLst[i].Attributes["Index"].InnerText); 
 +    } 
 +
 + 
 +///---------------------------------------------------------------------------------------- 
 +/// <summary> 
 +/// Load Xml node list to Device Parameter list. 
 +/// </summary> 
 +/// <param name="srcParamDataLst"></param> 
 +/// <param name="dstParamDataLst"></param> 
 +///---------------------------------------------------------------------------------------- 
 +private void LoadXmlNodeListToDevParamList(XmlNodeList srcParamDataLst, TDevParamList dstParamDataLst) 
 +
 +    for (int i = 0; i < srcParamDataLst.Count; i++) 
 +    { 
 +        dstParamDataLst.Add(new TDevParam() 
 +        { 
 +            Name = srcParamDataLst[i].Attributes["Name"].InnerText, 
 +            Value = Convert.ToInt32(srcParamDataLst[i].Attributes["Value"].InnerText) 
 +        }); 
 +    } 
 +
 + 
 +///---------------------------------------------------------------------------------------- 
 +/// <summary> 
 +/// Load Xml node list to Device Parameter list. 
 +/// </summary> 
 +/// <param name="srcParamMemLst"></param> 
 +/// <param name="dstParamMemLst"></param> 
 +///---------------------------------------------------------------------------------------- 
 +private void LoadXmlNodeListParamMemToDevParamList(XmlNodeList srcParamMemLst, TDevParamList[] dstParamMemLst) 
 +
 +    // Format: 
 +    //   <ParametersMemory> 
 +    //     <Memory Number='0'><Param...><Param...>...</Memory> 
 +    //     <Memory Number='1'>...</Memory> 
 +    //     <Memory Number='2'>...</Memory> 
 +    //     <Memory Number='3'>...</Memory> 
 +    //   </ParametersMemory> 
 +    XmlNodeList[] MemParams = new XmlNodeList[srcParamMemLst.Count]; 
 +    for (int mem = 0; mem < MemParams.Length; mem++) 
 +    { 
 +        MemParams[mem] = srcParamMemLst.Item(mem).ChildNodes;  
 + 
 +        for (int paramidx = 0; paramidx < MemParams[mem].Count; paramidx++) 
 +        { 
 +            dstParamMemLst[mem].Add(new TDevParam() 
 +            { 
 +                Name = MemParams[mem][paramidx].Attributes["Name"].InnerText, 
 +                Value = Convert.ToInt32(MemParams[mem][paramidx].Attributes["Value"].InnerText) 
 +            }); 
 +        } 
 +    } 
 +
 + 
 +///---------------------------------------------------------------------------------------- 
 +/// <summary> 
 +/// Get the Xml node list of requested tag name for the given Xml document section. 
 +/// </summary> 
 +/// <param name="xmlDoc"></param> 
 +/// <param name="SectionName"></param> 
 +/// <param name="ElementTagName"></param> 
 +/// <returns></returns> 
 +///---------------------------------------------------------------------------------------- 
 +private XmlNodeList GetElements(XmlDocument xmlDoc, string SectionName, string ElementTagName) 
 +
 +    //XmlNode xmlnodeSection = xmlDoc.GetElementsByTagName(SectionName)[0];  // get section tree (eg: Data3) 
 +    XmlNode xmlnodeSection = xmlDoc.GetElementsByTagName(SectionName)[0];  // get section tree (eg: Data3) 
 + 
 +    // Convert Section xmlnode into Section xmldoc 
 +    // 1. Create empty xmldoc 
 +    // 2. Import Section xmlnode into it. 
 +    XmlDocument xmldocSection = new XmlDocument(); 
 +    xmldocSection.LoadXml("<FittingSession></FittingSession>");              // load DocumentType 
 +    XmlNode xn = xmldocSection.ImportNode(xmlnodeSection, true /* deep */);  // import node 
 +    xmldocSection.DocumentElement.AppendChild(xn);                           // associate imported node into correct hierarchy position 
 + 
 +    // Search for requested Elements in this Section 
 +    return xmldocSection.GetElementsByTagName(ElementTagName);               // search for child nodes == Param 
 +
 +</code> 
 + 
 += References =
   * [[http://msdn.microsoft.com/en-us/library/cc165615.aspx|MSDN: How To: Bind to XDocument, XElement, or LINQ for XML Query Results]]   * [[http://msdn.microsoft.com/en-us/library/cc165615.aspx|MSDN: How To: Bind to XDocument, XElement, or LINQ for XML Query Results]]
   * [[http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.aspx|MSDN: XElement Class]]   * [[http://msdn.microsoft.com/en-us/library/system.xml.linq.xelement.aspx|MSDN: XElement Class]]