在xml中选择特定的子节点?

时间:2015-06-26 13:28:29

标签: c# .net xml winforms linq

我有一些看起来像这样的XML

    <SolutionString>
  <Solutions>
    <Solution>
      <ID>1</ID>
      <Property>
        <Name>DriverSheave</Name>
        <Value>1VP34</Value>
      </Property>
      <Property>
        <Name>DriverBushing</Name>
        <Value>
        </Value>
      </Property>
      <Property>
        <Name>DrivenSheave</Name>
        <Value>AK49</Value>
      </Property>
      <Property>
        <Name>DrivenBushing</Name>
        <Value>
        </Value>
      </Property>
      <Property>
        <Name>Belt</Name>
        <Value>AX30</Value>
      </Property>
      <Property>
        <Name>BeltQty</Name>
        <Value>1</Value>
      </Property>
      <Property>
        <Name>ActualCenterDistance</Name>
        <Value>9.88</Value>
      </Property>
     <Property>
        <Name>ActualServiceFactor</Name>
        <Value>1.71</Value>
      </Property>
     <Property>
        <Name>ActualDrivenShaftSpeed</Name>
        <Value>745/1117</Value>
      </Property>
     <Property>
        <Name>Cost</Name>
        <Value>32.65</Value>
      </Property>
      <TechSpecs>
        <TurnsOpen>2.5/4.0</TurnsOpen>
        <HubLoad>55 lb. 'running' Hub Load</HubLoad>
        <Tension>1.93 lb. should deflect belt 0.15 in.</Tension>
      </TechSpecs>
      <Property>
        <Name>Comment1</Name>
        <Value>If Driver is 2.5 turns open Driven RPM=931 and CD=10.25 in. If Driver is 4.0 turns open Driven RPM=819 and CD=10.47 in.</Value>
      </Property>
      <Property>
        <Name>Comment2</Name>
        <Value>Correct tension for this drive (1.93 lb. should deflect belt 0.15 in.) will have 55 lb. 'running' Hub Load</Value>
      </Property>
      <Interchanges>
        <Interchange>
          <DriverSheave />
          <DriverBushing />
          <DrivenSheave>BK55X7/8</DrivenSheave>
          <DrivenBushing>
          </DrivenBushing>
        </Interchange>
        <Interchange>
          <DriverSheave />
          <DriverBushing />
          <DrivenSheave>AK49H</DrivenSheave>
          <DrivenBushing>H</DrivenBushing>
        </Interchange>
        <Interchange>
          <DriverSheave />
          <DriverBushing />
          <DrivenSheave>BK55H</DrivenSheave>
          <DrivenBushing>H</DrivenBushing>
        </Interchange>
      </Interchanges>
    </Solution>
    <Solution>

对于属性列表值2,它选择两者,

<Property>
    <Name>DrivenSheave</Name>
    <Value>AK49</Value>
  </Property>

以及

 <Property>
    <Name>Comment2</Name>
    <Value>Correct tension for this drive (1.93 lb. should deflect belt 0.15 in.) will have 55 lb. 'running' Hub Load</Value>
  </Property>

我相信它是因为<techspecs>

的属性中断了

我使用这样的代码将每个ID及其属性加载到这样的组合框中。

 var cat = solutions
    .Descendants("Solution")
    .Select(x => new
    {
        ID = (string)x.Element("ID"),
        Properties = x.Elements("Property").Select(p => new
        {
            Name = (string) p.Element("Name"),
            Value = (string) p.Element("Value")
        }).ToList()
    });

var items = cat
    .Select(s => new
    {
        ID = s.ID,
        Text = string.Format("{0}. {1}", s.ID,
        string.Join(", ", s.Properties
                           .Select(p => string.Format("{0} = {1}",
                               p.Name,
                               p.Value ?? "(null)"))))
    }).ToArray();
comboBox1.DisplayMember = "Text";
comboBox1.ValueMember = "ID";
comboBox1.Items.AddRange(items);

我遇到的问题是,对于每个Solution / ID,有12个孩子property&#39; s。我希望能够只指定其中的6个,例如选择第一个

<Property>
    <Name>DriverSheave</Name>
    <Value>1VP34</Value>
</Property>

第3个,第6个等,并跳过其他人。

我看看这个Select specific nodes in XML with LINQ,但我不确定如何在我的情况下实现这一点。

2 个答案:

答案 0 :(得分:1)

此答案可以帮助您:Getting Nth value with Linq

var nthItem = items.Skip(n).First();

答案 1 :(得分:1)

您可以这样做:

var indexesToChoose = new List<int> {1, 2};

var cat = solutions
            .Descendants("Solution")
            .Select(x => new
            {
                ID = (string)x.Element("ID"),
                Properties = x.Elements("Property")
                    .Select((p, i) => new
                    {
                        Name = (string)p.Element("Name"),
                        Value = (string)p.Element("Value"),
                        idx = i
                    })
                    .Where(y => indexesToChoose.Contains(y.idx))
                    //.OrderBy(z => indexesToChoose.FindIndex(p => p == z.idx))
                    .ToList()
            });

首先我们创建要选择的索引列表,然后在创建每个匿名类实例时,我们将枚举它们,最后我们只采用indexesToChoose中具有索引的那些。

结果 - 执行Properties字段上方的代码后,只包含xml中的第一个和第二个<Property>元素。