无法使用 LINQ to XML 初始化 class 变量
Unable to initialize class variables using LINQ to XML
我有一个很大的 XML 文件,其中包含许多节点和子节点。
我正在尝试获取特定详细信息并保存它。
我粘贴代码如下。
XML 是
<?xml version="1.0"?>
<CLabelContainer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Labels>
<LabelList>
<CLabel>
<VehicleLabel>
<ImageName>image1.bmp</ImageName>
<BoundingRect>
<X>433</X>
<Y>205</Y>
<Width>39</Width>
<Height>42</Height>
</BoundingRect>
</VehicleLabel>
</CLabel>
.
& So on...
.
<CLabel>
<VehicleLabel>
<ImageName>image20.bmp</ImageName>
<BoundingRect>
<X>425</X>
<Y>305</Y>
<Width>30</Width>
<Height>46</Height>
</BoundingRect>
</VehicleLabel>
</CLabel>
</LabelList>
</Labels>
</CLabelContainer>
这是目标XML
class cROI
{
public Int16 iX { get; set; }
public Int16 iY { get; set; }
public Int16 iWidth { get; set; }
public Int16 iHeight { get; set; }
public cROI(Int16 iX, Int16 iY, Int16 iWidth, Int16 iHeight)
{
this.iX = iX;
this.iY = iY;
this.iWidth = iWidth;
this.iHeight = iHeight;
Console.WriteLine("{3}, {1}, {2}, {0}", this.iX, this.iY, this.iWidth, this.iHeight);
}
public cROI()
{
// TODO: Complete member initialization
}
}
LINQ to XML 在主函数中.....
class Program
{
static void Main(string[] args)
{
XDocument xXmlDoc = XDocument.Load("C:/Users/User1/Desktop/abc.xml");
var m_cROI = from ROI in xXmlDoc.Descendants("CLabelContainer") select new cROI
{
iX = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("X").Value),
iY = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Y").Value),
iWidth = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("iWidth").Value),
iHeight = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("iHeight").Value),
};
我没有输出。 (按任意键继续....)
注意:是否可以创建一个 cROI 列表并填充所有 20 个图像边界矩形元素?以上,作为测试目的,我只尝试了一个元素。
编辑:我尝试使用参数化构造函数调用,而不是“select new ROI {....}”,"Select new ROI( {....} )"。无结果
您正在调用 cRoi class 的无参数构造函数,并使用 属性 个初始化程序来填充 class。这样,您就不会在带有参数的构造函数中点击 Console.WriteLine 代码。
要调用构造函数,请使用此语法
var m_cROI = from ROI in xXmlDoc.Descendants("CLabelContainer") select new cROI
(
iX = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("X").Value),
iY = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Y").Value),
iWidth = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("iWidth").Value),
iHeight = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("iHeight").Value),
);
您可以删除无参数构造函数以避免再次犯同样的错误。这样,如果您尝试使用它,编译器会报错。
您希望看到 public cROI(Int16 iX, Int16 iY, Int16 iWidth, Int16 iHeight)
构造函数的 Console.WriteLine(...
输出,但您没有看到,原因如下:
您没有调用此构造函数。相反,您正在调用无参数构造函数,然后用 object initializer 填充属性。
Linq 查询是 lazy。因此,直到请求时才会实际评估结果。
您在 XML 中的宽度和高度元素的名称有误。它们是 <Width>30</Width>
和 <Height>46</Height>
,而您的代码需要 <iWidth>30</iWidth>
和 <iHeight>46</iHeight>
。 (使用错误的名称,您的代码将抛出 NullReferenceException
。)
将这些放在一起,以下应该会产生您期望的控制台输出:
var m_cROI = from ROI in xXmlDoc.Descendants("CLabelContainer")
select new cROI
( // Use the explicit constructor
Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("X").Value),
Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Y").Value),
Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Width").Value),
Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Height").Value)
);
var result = m_cROI.ToList(); // Actually evaluate the query.
更新
要获取所有 VehicleLabel
个边界矩形,您可以使用 XPathSelectElements
找到所有 BoundingRect
个节点。
如果 CLabelContainer
是 根文档节点(在您的示例中),那么最有效的查询是:
var query = from rect in xXmlDoc.XPathSelectElements("/CLabelContainer/Labels/LabelList/CLabel/VehicleLabel/BoundingRect")
select new cROI
(
Int16.Parse(rect.Element("X").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Y").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Width").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Height").Value, NumberFormatInfo.InvariantInfo)
);
var AllBoundingRect = query.ToList();
如果CLabelContainer
是不是根文档节点,你可以这样做:
var query = from rect in xXmlDoc.XPathSelectElements("//CLabelContainer/Labels/LabelList/CLabel/VehicleLabel/BoundingRect")
select new cROI
(
Int16.Parse(rect.Element("X").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Y").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Width").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Height").Value, NumberFormatInfo.InvariantInfo)
);
var AllBoundingRect = query.ToList();
其中“//”字符串表示 "search recursively throughout the document for the following chain of nodes"。相当于:
var query = from rect in xXmlDoc.Descendants("CLabelContainer").Elements("Labels").Elements("LabelList").Elements("CLabel").Elements("VehicleLabel").Elements("BoundingRect")
select new cROI
(
Int16.Parse(rect.Element("X").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Y").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Width").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Height").Value, NumberFormatInfo.InvariantInfo)
);
var AllBoundingRect = query.ToList();
请注意,我正在使用 invariant culture(即未本地化为特定语言或国家/地区)解析数字,这几乎总是解析 XML 等数据交换文件的正确方法。
我有一个很大的 XML 文件,其中包含许多节点和子节点。 我正在尝试获取特定详细信息并保存它。 我粘贴代码如下。 XML 是
<?xml version="1.0"?>
<CLabelContainer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Labels>
<LabelList>
<CLabel>
<VehicleLabel>
<ImageName>image1.bmp</ImageName>
<BoundingRect>
<X>433</X>
<Y>205</Y>
<Width>39</Width>
<Height>42</Height>
</BoundingRect>
</VehicleLabel>
</CLabel>
.
& So on...
.
<CLabel>
<VehicleLabel>
<ImageName>image20.bmp</ImageName>
<BoundingRect>
<X>425</X>
<Y>305</Y>
<Width>30</Width>
<Height>46</Height>
</BoundingRect>
</VehicleLabel>
</CLabel>
</LabelList>
</Labels>
</CLabelContainer>
这是目标XML
class cROI
{
public Int16 iX { get; set; }
public Int16 iY { get; set; }
public Int16 iWidth { get; set; }
public Int16 iHeight { get; set; }
public cROI(Int16 iX, Int16 iY, Int16 iWidth, Int16 iHeight)
{
this.iX = iX;
this.iY = iY;
this.iWidth = iWidth;
this.iHeight = iHeight;
Console.WriteLine("{3}, {1}, {2}, {0}", this.iX, this.iY, this.iWidth, this.iHeight);
}
public cROI()
{
// TODO: Complete member initialization
}
}
LINQ to XML 在主函数中.....
class Program
{
static void Main(string[] args)
{
XDocument xXmlDoc = XDocument.Load("C:/Users/User1/Desktop/abc.xml");
var m_cROI = from ROI in xXmlDoc.Descendants("CLabelContainer") select new cROI
{
iX = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("X").Value),
iY = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Y").Value),
iWidth = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("iWidth").Value),
iHeight = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("iHeight").Value),
};
我没有输出。 (按任意键继续....)
注意:是否可以创建一个 cROI 列表并填充所有 20 个图像边界矩形元素?以上,作为测试目的,我只尝试了一个元素。
编辑:我尝试使用参数化构造函数调用,而不是“select new ROI {....}”,"Select new ROI( {....} )"。无结果
您正在调用 cRoi class 的无参数构造函数,并使用 属性 个初始化程序来填充 class。这样,您就不会在带有参数的构造函数中点击 Console.WriteLine 代码。
要调用构造函数,请使用此语法
var m_cROI = from ROI in xXmlDoc.Descendants("CLabelContainer") select new cROI
(
iX = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("X").Value),
iY = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Y").Value),
iWidth = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("iWidth").Value),
iHeight = Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("iHeight").Value),
);
您可以删除无参数构造函数以避免再次犯同样的错误。这样,如果您尝试使用它,编译器会报错。
您希望看到 public cROI(Int16 iX, Int16 iY, Int16 iWidth, Int16 iHeight)
构造函数的 Console.WriteLine(...
输出,但您没有看到,原因如下:
您没有调用此构造函数。相反,您正在调用无参数构造函数,然后用 object initializer 填充属性。
Linq 查询是 lazy。因此,直到请求时才会实际评估结果。
您在 XML 中的宽度和高度元素的名称有误。它们是
<Width>30</Width>
和<Height>46</Height>
,而您的代码需要<iWidth>30</iWidth>
和<iHeight>46</iHeight>
。 (使用错误的名称,您的代码将抛出NullReferenceException
。)
将这些放在一起,以下应该会产生您期望的控制台输出:
var m_cROI = from ROI in xXmlDoc.Descendants("CLabelContainer")
select new cROI
( // Use the explicit constructor
Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("X").Value),
Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Y").Value),
Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Width").Value),
Int16.Parse(ROI.Element("Labels").Element("LabelList").Element("CLabel").Element("VehicleLabel").Element("BoundingRect").Element("Height").Value)
);
var result = m_cROI.ToList(); // Actually evaluate the query.
更新
要获取所有 VehicleLabel
个边界矩形,您可以使用 XPathSelectElements
找到所有 BoundingRect
个节点。
如果 CLabelContainer
是 根文档节点(在您的示例中),那么最有效的查询是:
var query = from rect in xXmlDoc.XPathSelectElements("/CLabelContainer/Labels/LabelList/CLabel/VehicleLabel/BoundingRect")
select new cROI
(
Int16.Parse(rect.Element("X").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Y").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Width").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Height").Value, NumberFormatInfo.InvariantInfo)
);
var AllBoundingRect = query.ToList();
如果CLabelContainer
是不是根文档节点,你可以这样做:
var query = from rect in xXmlDoc.XPathSelectElements("//CLabelContainer/Labels/LabelList/CLabel/VehicleLabel/BoundingRect")
select new cROI
(
Int16.Parse(rect.Element("X").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Y").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Width").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Height").Value, NumberFormatInfo.InvariantInfo)
);
var AllBoundingRect = query.ToList();
其中“//”字符串表示 "search recursively throughout the document for the following chain of nodes"。相当于:
var query = from rect in xXmlDoc.Descendants("CLabelContainer").Elements("Labels").Elements("LabelList").Elements("CLabel").Elements("VehicleLabel").Elements("BoundingRect")
select new cROI
(
Int16.Parse(rect.Element("X").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Y").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Width").Value, NumberFormatInfo.InvariantInfo),
Int16.Parse(rect.Element("Height").Value, NumberFormatInfo.InvariantInfo)
);
var AllBoundingRect = query.ToList();
请注意,我正在使用 invariant culture(即未本地化为特定语言或国家/地区)解析数字,这几乎总是解析 XML 等数据交换文件的正确方法。