linq到XML和XPath的后代



我遇到了一些麻烦,让一些孩子从linq-xml返回与xpath查询的混合。主要的父母"控制器"几乎没有字段,其中两个拥有自己的孩子。看起来如下:

<Site>
  <Controllers>
    <Controller>
      <Name>CtrEast</Name>
      <CntrlType>xx1</CntrlType>
      <IPAddress>x.x.x.1</IPAddress>
      <NetworkId>123</NetworkId>
      <DeviceId>MyId</DeviceId>
      <IO>
        <Inputs>
          <Input>
          <Name>xyz_Temp</Name>
          <Channel>10</Channel>
          <Value>10.5</Value>
          </Input>
        </Inputs>
        <Outputs>
          <Output>
            <Name>xyz_vlv</Name>
            <Channel>8</Channel>
            <Value>20</Value>
          </Output>
        </Outputs>
      </IO>
      <ChildControllers>
        <ChildController>
          <Name>GF</Name>
          <CntrlType>xyz</CntrlType>
          <Id>850</Id>
          <Port>comm1</Port>
          <IO>
            <Inputs>
              <Input>
              <Name>GF_Temp</Name>
              <Channel>1</Channel>
              <Value>13.9</Value>
              </Input>
            </Inputs>
            <Outputs>
              <Output>
                <Name>xyz_vlv</Name>
                <Channel>8</Channel>
                <Value>20</Value>
              </Output>
            </Outputs>
          </IO>
        </ChildController>
      </ChildControllers>
    </Controller>
  </Controllers>
</Site>

我没有问题从"控制器"中获得孩子的问题,以及从属于"控制器"元素的" IO"元素中获得的孩子,我也能够在" ChildController"中获得孩子。但是,我无法从属于" childController"的" IO"元素中正确检索孩子的。

以下是我的linq XML和XPATH代码:

NC_List =
                        (
                        from nc in XDocument.Load(@"Data.xml").Descendants("Controller")
                        let NC_Name = nc.Element("Name").Value
                        let NC_CntrlType = nc.Element("CntrlType").Value
                        let NC_IPAddress = nc.Element("IPAddress").Value
                        let NC_NetworkId = nc.Element("NetworkId").Value
                        let NC_DeviceId = nc.Element("DeviceId").Value
                        let NC_BacnetMSTPNetNum = nc.Element("BacnetMSTPNetNum").Value
                        let NC_BACnetDeviceId = nc.Element("BACnetDeviceId").Value
                        let NC_SerialNum = nc.Element("SerialNum").Value
                        let NC_VersionNum = nc.Element("VersionNum").Value
                        select new CtrlClass_NC
                        {
                            Name = NC_Name,
                            CntrlType = NC_CntrlType,
                            IPAddress = NC_IPAddress,
                            NetworkId = NC_NetworkId,
                            DeviceId = NC_DeviceId,
                            BacnetMSTPNetNum = NC_BacnetMSTPNetNum,
                            BACnetDeviceId = NC_BACnetDeviceId,
                            SerialNum = NC_SerialNum,
                            VersionNum = NC_VersionNum,
                            NC_IO =
                            (
                                from NC_io in nc.XPathSelectElements("IO/InfinityInputs/InfinityInput | IO/InfinityOutputs/InfinityOutput")
                                select new IO_Class
                                {
                                    IO_DeviceId = (string)NC_io.Element("DeviceId").Value,
                                    IO_Name = (string)NC_io.Element("Name").Value,
                                    IO_Channel = (string)NC_io.Element("Channel").Value,
                                    IO_Type = (string)NC_io.Element("Type").Value,
                                    IO_Value = (string)NC_io.Element("Value").Value,
                                    IO_Units = (string)NC_io.Element("Units").Value,
                                    IO_ElecType = (string)NC_io.Element("ElecType").Value,
                                    IO_Invert = (string)NC_io.Element("Invert").Value,
                                    IO_Conversion = (string)NC_io.Element("Conversion").Value,
                                    IO_Threshold = (string)NC_io.Element("Threshold").Value
                                }
                            ).ToList(),
                            Infinet =
                            (
                                from ic in nc.XPathSelectElements("InfinetControllers/InfinetController")
                        
                                let IC_Name = ic.Element("Name").Value
                                let IC_CntrlType = ic.Element("CntrlType").Value
                                let IC_InfinetId = ic.Element("InfinetId").Value
                                let IC_BACnetDeviceId = ic.Element("BACnetDeviceId").Value
                                let IC_Port = ic.Element("Port").Value
                                let IC_DeviceId = ic.Element("DeviceId").Value
                                let IC_NetworkId = ic.Element("NetworkId").Value
                                let IC_SerialNum = ic.Element("SerialNum").Value
                                let IC_VersionNum = ic.Element("VersionNum").Value
                                select new CtrlClass_IC
                                {
                                    Name = IC_Name,
                                    CntrlType = IC_CntrlType,
                                    InfinetId = IC_InfinetId,
                                    BACnetDeviceId = IC_BACnetDeviceId,
                                    Port = IC_Port,
                                    DeviceId = IC_DeviceId,
                                    NetworkId = IC_NetworkId,
                                    SerialNum = IC_SerialNum,
                                    VersionNum = IC_VersionNum,
                                    IC_IO =
                                    (
                                        from IC_io in nc.XPathSelectElements("InfinetControllers/InfinetController/IO/InfinityInputs/InfinityInput | InfinetControllers/InfinetController/IO/InfinityOutputs/InfinityOutput")                                        
                                        select new IO_Class
                                        {
                                            IO_DeviceId = (string)IC_io.Element("DeviceId").Value,
                                            IO_Name = (string)IC_io.Element("Name").Value,
                                            IO_Channel = (string)IC_io.Element("Channel").Value,
                                            IO_Type = (string)IC_io.Element("Type").Value,
                                            IO_Value = (string)IC_io.Element("Value").Value,
                                            IO_Units = (string)IC_io.Element("Units").Value,
                                            IO_ElecType = (string)IC_io.Element("ElecType").Value,
                                            IO_Invert = (string)IC_io.Element("Invert").Value,
                                            IO_Conversion = (string)IC_io.Element("Conversion").Value,
                                            IO_Threshold = (string)IC_io.Element("Threshold").Value
                                        }
                                    ).ToList(),
                                }
                            ).ToList()
                          }
                        ).ToList();

这是一个有效的查询,我能够获得一些值,但是,这是没有意义的,是从"控制器"元素中的IO,我得到正确的数据,例如:3第一个控制器的输入和4个输出,然后为下一个控制器提供一些不同的东西。对于" ChildController",就像所有200个儿童控制器一样具有相同数量的点和数据。我得到了每个儿童controller/io元素下方的419个输入和输出。

希望这是有道理的。我确定这一定是简单的,但是我看不到代码中的问题。

任何反馈都非常感谢。

问:

alain

取您提供的XML并使用Xlement(请注意,可以将儿童控制器的IO部分和常规控制器的IO部分纳入,因为它很常见)。而且我也没有考虑丢失的元素和值(正如您会看到我在某些地方使用的first()。值)。

var xml = XElement.Parse(GetXmlToProcess());
var Controllers = xml.Elements("Controllers").Select(x=> x)
                      .Elements("Controller").Select(x=> 
                      {
                          return GetControllerFromXml(x);
                      });

public Controller GetControllerFromXml( XElement elem)
{
    var controller  = new Controller();
    controller.Name = elem.Elements("Name").First().Value;
    controller.CntrlType = elem.Elements("CntrlType").First().Value;
    controller.IPAddress = elem.Elements("IPAddress").First().Value;
    controller.NetworkId = elem.Elements("NetworkId").First().Value;
    controller.DeviceId = elem.Elements("DeviceId").First().Value;
    var io = elem.Elements("IO");
    if (io != null)
    {
        controller.IO.Inputs.AddRange( io.Elements("Inputs")
                                        .Elements("Input")
                                        .Select(v=> new Input
                                                {
                                                    Name =  v.Elements("Name").First().Value,
                                                    Channel =  v.Elements("Channel").First().Value,
                                                    Value =  v.Elements("Value").First().Value
                                                })
                                    );
        controller.IO.Outputs.AddRange( io.Elements("Outputs")
                                        .Elements("Output")
                                        .Select(v=> new Output
                                                {
                                                    Name =  v.Elements("Name").First().Value,
                                                    Channel =  v.Elements("Channel").First().Value,
                                                    Value =  v.Elements("Value").First().Value
                                                })
                                    );
    }
    var childrenController =  elem.Elements("ChildControllers");
    if(childrenController != null)
    {
        foreach(var child in childrenController.Elements("ChildController"))
        {
            var childController =  new ChildController();
            controller.ChildControllers.Add(childController);
            childController.Name = child.Elements("Name").First().Value;
            childController.CntrlType = child.Elements("CntrlType").First().Value;
            childController.Id = child.Elements("Id").First().Value;
            childController.Port = child.Elements("Port").First().Value;
            var cio = child.Elements("IO");
            if (cio != null)
            {
                childController.IO.Inputs.AddRange( cio.Elements("Inputs")
                                        .Elements("Input")
                                        .Select(v=> new Input
                                                {
                                                    Name =  v.Elements("Name").First().Value,
                                                    Channel =  v.Elements("Channel").First().Value,
                                                    Value =  v.Elements("Value").First().Value
                                                })
                                    );
                childController.IO.Outputs.AddRange( cio.Elements("Outputs")
                                        .Elements("Output")
                                        .Select(v=> new Output
                                                {
                                                    Name =  v.Elements("Name").First().Value,
                                                    Channel =  v.Elements("Channel").First().Value,
                                                    Value =  v.Elements("Value").First().Value
                                                })
                                    );
    }
        }
    }
    return controller;
}
// Define other methods and classes here
public class Controller
{
    public string Name{get;set;}
    public string CntrlType{get; set;}
    public string IPAddress{get; set;}
    public string NetworkId{get; set;}
    public string DeviceId{get; set;}
    public IO IO {get;set;}
    public List<ChildController> ChildControllers{get; set;}
    public Controller()
    {
        IO  = new IO();
        ChildControllers = new List<ChildController>();
    }
}
public class ChildController
{
    public string Name{get;set;}
    public string CntrlType{get; set;}
    public string Id{get; set;}
    public string Port{get; set;}
    public IO IO {get;set;}
    public ChildController()
    {
        IO  = new IO();
    }
}
public class IO
{
    public List<Input> Inputs {get; set;} 
    public List<Output> Outputs  {get; set;} 
    public IO()
    {
        Inputs = new List<Input>();
        Outputs = new List<Output>();
    }
}
public class Input
{
    public string Name{get;set;}
    public string Channel{get; set;}
    public string Value{get; set;}
}
public class Output
{
    public string Name{get;set;}
    public string Channel{get; set;}
    public string Value{get; set;}
}

最新更新