Click here to Skip to main content
16,015,594 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
XML
<?xml version="1.0" encoding="utf-8"?>
<Controllers>
  <PLC ConfigName="OP010">
    <IPAddress>172.21.1.1</IPAddress>
    <SubnetMask>255.255.255.0</SubnetMask>
    <ENxT_Slot>1</ENxT_Slot>
    <CPU_Slot>0</CPU_Slot>
    <ProgName>OP010_ePRESS</ProgName>
    <CurveTag>Curve</CurveTag>
    <CommTimeOut>1000</CommTimeOut>
    <UpdateRate>250</UpdateRate>
  </PLC>
    <PLC ConfigName="OP020">
    <IPAddress>172.21.1.2</IPAddress>
    <SubnetMask>255.255.254.0</SubnetMask>
    <ENxT_Slot>1</ENxT_Slot>
    <CPU_Slot>0</CPU_Slot>
    <ProgName>OP020_ePRESS</ProgName>
    <CurveTag>Curve</CurveTag>
    <CommTimeOut>1000</CommTimeOut>
    <UpdateRate>250</UpdateRate>
  </PLC>
</Controllers>


I'm taking a swag at LINQ with XML with VS2010 and C#. Using the XML shown above, I've got the following code to pull the XElements out of the XML this way -

C#
var xmlElemList = from xmlElements in XElement.Load(@"configuration.xml").Elements("PLC") select xmlElements;

      foreach (var xmlElem in xmlElemList)
      {


I can iterate through each element with a foreach, I can print the contents to the console. I can pull out the attribute from the <plc configname="OPxxx">. What I can't figure out how to do is either 1) Map the data into a class object I have with properties of the same name, or at the very least 2) assign the descendants of each <plc configname...=""> to variables without using a very painful process such as what I post below. There has got to be an easier way.

What does work (UGLY!!!) is the following -

Create a set of delimiters for each set of data -
C#
String[] ip_addr_delim = new String[2] { "</IPAddress>", "<IPAddress>" };
      String[] sub_net_delim = new String[2] { "<SubnetMask>", "</SubnetMask>" };
      String[] comm_slot_delim = new String[2] { "<ENxT_Slot>", "</ENxT_Slot" };
      String[] cpu_slot_delim = new String[2] { "<CPU_Slot>", "</CPU_Slot>" };
      String[] prog_name_delim = new String[2] { "<ProgName>", "</ProgName>" };
      String[] curve_tag_delim = new String[2] { "<CurveTag>", "</CurveTag>" };
      String[] timeout_delim = new String[2] { "<CommTimeOut>", "</CommTimeOut>" };
      String[] update_rate_delim = new String[2] { "<UpdateRate>", "</UpdateRate>" };


Then iterate through them all, creating a PLC class object, assigning values, then adding..rinse and repeat. I can't believe there isn't a much more elegant solution.

C#
// Execute the query
      foreach (var xmlElem in xmlElemList)
      {
        string[] temp;

        ActiveCfg.ConfigName = xmlElem.FirstAttribute.Value.ToString();

        temp = xmlElem.ToString().Split(ip_addr_delim, StringSplitOptions.RemoveEmptyEntries);
        ActiveCfg.IPAddress = temp[1];

        temp = xmlElem.ToString().Split(sub_net_delim, StringSplitOptions.RemoveEmptyEntries);
        ActiveCfg.SubnetMask = temp[1];

        temp = xmlElem.ToString().Split(comm_slot_delim, StringSplitOptions.RemoveEmptyEntries);
        ActiveCfg.ENxT_Slot = Convert.ToByte(temp[1]);

        temp = xmlElem.ToString().Split(cpu_slot_delim, StringSplitOptions.RemoveEmptyEntries);
        ActiveCfg.CPU_Slot = Convert.ToByte(temp[1]);

        temp = xmlElem.ToString().Split(prog_name_delim, StringSplitOptions.RemoveEmptyEntries);
        ActiveCfg.ProgName = temp[1];

        temp = xmlElem.ToString().Split(curve_tag_delim, StringSplitOptions.RemoveEmptyEntries);
        ActiveCfg.CurveTag = temp[1];

        temp = xmlElem.ToString().Split(timeout_delim, StringSplitOptions.RemoveEmptyEntries);
        ActiveCfg.CommTimeOut = Convert.ToInt32(temp[1]);

        temp = xmlElem.ToString().Split(update_rate_delim, StringSplitOptions.RemoveEmptyEntries);
        ActiveCfg.UpdateRate = Convert.ToInt32(temp[1]);

        PLC_List.Add(this.ActiveCfg);

      }


I should add that I am free to change the XML format in the .XML to fit my needs so if that makes something easier without breaking rules of XML, I'm open to it.
Posted
Updated 24-Jan-11 10:43am
v4

some copy paste code from a test project:
it's old and ugly, but: Have a look at the "Value" property ;)

C#
XDocument xmlDoc = XDocument.Load(fileName);
try
{
    //
    //
    // get origins from project file
    var Origins = from Origin in xmlDoc.Descendants("Origin")
        select new
        {
            name = Origin.Element("Name").Value,
            tx = Origin.Element("X").Value,
            ty = Origin.Element("Y").Value,
            tz = Origin.Element("Z").Value,
            id = Origin.Element("ID").Value,
        };

    foreach (var tmp in Origins)
    {
        // create new origin object
        OriginObject origin = new OriginObject();
        origin.X = double.Parse(tmp.tx);
        origin.Y = double.Parse(tmp.ty);
        origin.Z = double.Parse(tmp.tz);
        origin.ID = int.Parse(tmp.id);
        origin.Name = tmp.name;
        // add the origin to the collection
        this.OriginsCollection.Add(origin.Name, origin);
    }
}
catch(Exception e)
{
    System.Diagnostics.Debug.Print(
        "Error while reading:{0}\n{1}", e.Message, e.StackTrace);
}

 
Share this answer
 
v2
Thanks much for the answer! I just figured out what appears to be a nice way to do it by putting together a couple of things I saw on MSDN. I know I looked at the same page at least 5 times today... There may be a cleaner way, but this seems to work well -

XML
// Create the query
      var xmlElemList = from xmlElements
                        in XElement.Load(@"configuration.xml").Elements("PLC")
                        select xmlElements;

      foreach (var xmlElem in xmlElemList.OfType<XElement>())
      {
        cPLC plc = new cPLC();
        plc.ConfigName = (string)xmlElem.FirstAttribute.Value;
        plc.IPAddress = (string)xmlElem.Element("IPAddress");
        plc.SubnetMask = (string)xmlElem.Element("SubnetMask");
        plc.CommSlot = (Int32)xmlElem.Element("CommSlot");
        plc.CpuSlot = (Int32)xmlElem.Element("CpuSlot");
        plc.ProgName = (string) xmlElem.Element("ProgName");
        plc.CurveTag = (string) xmlElem.Element("CurveTag");
        plc.CommTimeOut = (Int32) xmlElem.Element("CommTimeOut");
        plc.UpdateRate = (Int32) xmlElem.Element("UpdateRate");
        plcList.Add(plc);
      }
 
Share this answer
 
v2
Comments
Christian Graus 24-Jan-11 19:46pm    
Please don't push 'answer' to add a comment. Use 'comment'.
There is an easier way.

C#
XDocument xmlDoc = XDocument.Load(path);
var videos = from video in xmlDoc.Descendants("video")
             select new
             {
                 FilePath = video.Attribute("filepath").Value,
                 ThumbPath = video.Attribute("thumbpath").Value,
                 RolloverPath = video.Attribute("rolloverimage").Value,
                 Index = Convert.ToInt32(video.Attribute("index").Value),
                 Title = video.Attribute("title").Value,
                 IsDog = Convert.ToBoolean(video.Attribute("isdog").Value),
                 IsCat = Convert.ToBoolean(video.Attribute("iscat").Value),
                 IsHorse = Convert.ToBoolean(video.Attribute("ishorse").Value)
             };


This code will create a collection of objects with the properties I name. Now I can iterate over that and use it to set the values of my strongly typed/named class in my code.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900