我遇到了一些麻烦,让一些孩子从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;}
}