XML和LINQ [英] XML & LINQ

查看:61
本文介绍了XML和LINQ的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<br />
<pre lang="xml"><?xml version="1.0" encoding="utf-8"?><br />
<Controllers><br />
  <PLC ConfigName="OP010"><br />
    <IPAddress>172.21.1.1</IPAddress><br />
    <SubnetMask>255.255.255.0</SubnetMask><br />
    <ENxT_Slot>1</ENxT_Slot><br />
    <CPU_Slot>0</CPU_Slot><br />
    <ProgName>OP010_ePRESS</ProgName><br />
    <CurveTag>Curve</CurveTag><br />
    <CommTimeOut>1000</CommTimeOut><br />
    <UpdateRate>250</UpdateRate><br />
  </PLC><br />
    <PLC ConfigName="OP020"><br />
    <IPAddress>172.21.1.2</IPAddress><br />
    <SubnetMask>255.255.254.0</SubnetMask><br />
    <ENxT_Slot>1</ENxT_Slot><br />
    <CPU_Slot>0</CPU_Slot><br />
    <ProgName>OP020_ePRESS</ProgName><br />
    <CurveTag>Curve</CurveTag><br />
    <CommTimeOut>1000</CommTimeOut><br />
    <UpdateRate>250</UpdateRate><br />
  </PLC><br />
</Controllers></pre><br />
<br />



我在VS2010和C#上使用XML在LINQ上大吃一惊.使用上面显示的XML,我得到了以下代码,以这种方式将XElements从XML中拉出



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 -

<br />
<pre lang="cs">var xmlElemList = from xmlElements in XElement.Load(@"configuration.xml").Elements("PLC") select xmlElements;<br />
<br />
      foreach (var xmlElem in xmlElemList)<br />
      {</pre><br />



我可以使用foreach遍历每个元素,也可以将内容打印到控制台.我可以从< plc configname ="OPxxx">中拉出该属性.我不知道该怎么做的是1)将数据映射到我拥有的具有相同名称属性的类对象中,或者至少2)分配每个< plc配置名称的后代... =">变量,而无需使用非常痛苦的过程(例如我在下面发布的过程).必须有一种更简单的方法.

以下是有效的方法(丑陋!!!)-

为每组数据创建一组定界符-



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 -

<br />
<pre lang="cs">String[] ip_addr_delim = new String[2] { "</IPAddress>", "<IPAddress>" };<br />
      String[] sub_net_delim = new String[2] { "<SubnetMask>", "</SubnetMask>" };<br />
      String[] comm_slot_delim = new String[2] { "<ENxT_Slot>", "</ENxT_Slot" };<br />
      String[] cpu_slot_delim = new String[2] { "<CPU_Slot>", "</CPU_Slot>" };<br />
      String[] prog_name_delim = new String[2] { "<ProgName>", "</ProgName>" };<br />
      String[] curve_tag_delim = new String[2] { "<CurveTag>", "</CurveTag>" };<br />
      String[] timeout_delim = new String[2] { "<CommTimeOut>", "</CommTimeOut>" };<br />
      String[] update_rate_delim = new String[2] { "<UpdateRate>", "</UpdateRate>" };</pre><br />



然后遍历它们,创建一个PLC类对象,分配值,然后添加..rinse并重复.我不敢相信没有比这更优雅的解决方案了.



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.

<br />
<pre lang="cs">// Execute the query<br />
      foreach (var xmlElem in xmlElemList)<br />
      {<br />
        string[] temp;<br />
<br />
        ActiveCfg.ConfigName = xmlElem.FirstAttribute.Value.ToString();<br />
<br />
        temp = xmlElem.ToString().Split(ip_addr_delim, StringSplitOptions.RemoveEmptyEntries);<br />
        ActiveCfg.IPAddress = temp[1];<br />
<br />
        temp = xmlElem.ToString().Split(sub_net_delim, StringSplitOptions.RemoveEmptyEntries);<br />
        ActiveCfg.SubnetMask = temp[1];<br />
<br />
        temp = xmlElem.ToString().Split(comm_slot_delim, StringSplitOptions.RemoveEmptyEntries);<br />
        ActiveCfg.ENxT_Slot = Convert.ToByte(temp[1]);<br />
<br />
        temp = xmlElem.ToString().Split(cpu_slot_delim, StringSplitOptions.RemoveEmptyEntries);<br />
        ActiveCfg.CPU_Slot = Convert.ToByte(temp[1]);<br />
<br />
        temp = xmlElem.ToString().Split(prog_name_delim, StringSplitOptions.RemoveEmptyEntries);<br />
        ActiveCfg.ProgName = temp[1];<br />
<br />
        temp = xmlElem.ToString().Split(curve_tag_delim, StringSplitOptions.RemoveEmptyEntries);<br />
        ActiveCfg.CurveTag = temp[1];<br />
<br />
        temp = xmlElem.ToString().Split(timeout_delim, StringSplitOptions.RemoveEmptyEntries);<br />
        ActiveCfg.CommTimeOut = Convert.ToInt32(temp[1]);<br />
<br />
        temp = xmlElem.ToString().Split(update_rate_delim, StringSplitOptions.RemoveEmptyEntries);<br />
        ActiveCfg.UpdateRate = Convert.ToInt32(temp[1]);<br />
<br />
        PLC_List.Add(this.ActiveCfg);<br />
<br />
      }</pre><br />



我应该补充一点,我可以自由更改.XML中的XML格式以适应我的需要,因此,如果在不违反XML规则的情况下使事情变得更容易,我可以接受.



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.

推荐答案

一个测试项目中的一些复制粘贴代码:
它既旧又丑,但是:看一下"Value"属性;)

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

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);
}



非常感谢!我只是通过将我在MSDN上看到的几件事放在一起,才发现这样做似乎是一种不错的方法.我知道我今天至少看过同一页5次...可能有一种更简洁的方法,但这似乎效果很好-

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 -

<br />
<pre lang="xml">// Create the query<br />
      var xmlElemList = from xmlElements<br />
                        in XElement.Load(@"configuration.xml").Elements("PLC")<br />
                        select xmlElements;<br />
<br />
      foreach (var xmlElem in xmlElemList.OfType<XElement>())<br />
      {<br />
        cPLC plc = new cPLC();<br />
        plc.ConfigName = (string)xmlElem.FirstAttribute.Value;<br />
        plc.IPAddress = (string)xmlElem.Element("IPAddress");<br />
        plc.SubnetMask = (string)xmlElem.Element("SubnetMask");<br />
        plc.CommSlot = (Int32)xmlElem.Element("CommSlot");<br />
        plc.CpuSlot = (Int32)xmlElem.Element("CpuSlot");<br />
        plc.ProgName = (string) xmlElem.Element("ProgName");<br />
        plc.CurveTag = (string) xmlElem.Element("CurveTag");<br />
        plc.CommTimeOut = (Int32) xmlElem.Element("CommTimeOut");<br />
        plc.UpdateRate = (Int32) xmlElem.Element("UpdateRate");<br />
        plcList.Add(plc);<br />
      }</pre><br />
<br />


有一种更简单的方法.

There is an easier way.

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.


这篇关于XML和LINQ的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆