无法使用LINQ to XML初始化类变量

时间:2015-06-03 17:58:08

标签: c# xml 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&amp;列表。填写所有20个图像边界矩形元素??以上,作为测试目的,我只尝试使用一个元素。

编辑:我试图用参数化构造函数调用,而不是&#34;选择新的投资回报率{....}&#34;,&#34;选择新的投资回报率({....})&#34;。没有结果

2 个答案:

答案 0 :(得分:4)

您正在调用cRoi类的无参数构造函数,并使用属性初始值设定项来填充类。这样,您就不会在带参数的构造函数中点击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),
        );

您可以删除无参数构造函数以避免再次出现同样的错误。这样,如果您尝试使用它,编译器会抱怨。

答案 1 :(得分:3)

您希望看到Console.WriteLine(...构造函数的public cROI(Int16 iX, Int16 iY, Int16 iWidth, Int16 iHeight)输出,但您不是,原因如下:

  1. 您没有调用此构造函数。相反,您调用无参数构造函数,然后使用object initializer填充属性。

  2. Linq查询为lazy。因此,在要求之前,实际上不会对结果进行评估。

  3. XML中的width和height元素名称错误。它们是<Width>30</Width><Height>46</Height>,而您的代码需要<iWidth>30</iWidth><iHeight>46</iHeight>。 (如果名称错误,您的代码将抛出NullReferenceException。)

  4. 将这些放在一起,以下内容应该产生您期望的控制台输出:

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

    其中“//”字符串表示“在整个文档中递归搜索以下节点链”。它相当于:

            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)的正确方法。