2015-06-03 19 views
0

我有大型的XML文件,其中包含許多節點&子節點。 我想要得到特定的細節&保存。 我粘貼代碼如下。 XML是無法使用LINQ to 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到主要功能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個圖像邊界矩形元素?以上,作爲測試目的,我只用一個元素嘗試。

編輯:我試着用參數化構造函數調用,而不是「選擇新的ROI {....}」,「選擇新的ROI({....})」。沒有結果

+0

你沒有輸出?你*嘗試過*調試嗎? – Will

+0

是的。調試控制在var m_cROI = ......&然後結束主,所以最後沒有輸出 – user3042916

+0

那麼,這並沒有照亮任何情況。你應該[編輯]並說出你在調試過程中觀察到的以及爲什麼它不是你的預期。 – Will

回答

3

您期待看到從public cROI(Int16 iX, Int16 iY, Int16 iWidth, Int16 iHeight)構造Console.WriteLine(...輸出的,但你不是,有以下原因:

  1. 你是不是調用此構造。相反,您正在調用無參數構造函數,然後使用object initializer填充屬性。

  2. Linq查詢是lazy。因此,結果直到請求才被實際評估。

  3. 您在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(); 

其中「//」字符串表示「在整個文檔中爲下面的鏈節點遞歸搜索」。它等效於:

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

+1

獲得了image1的第一個邊界矩形。謝謝。 我可以得到列表 AllBoundingRect =新列表()? – user3042916

+0

@ user3042916 - 答案已更新。 – dbc

+0

極好的指導.....謝謝! 以上,我已經發布了另一個問題。如果可能,請按照, http://stackoverflow.com/q/30637711/3042916 – user3042916

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

您可以刪除參數的構造函數,以避免再次犯同樣的錯誤。這樣,如果您嘗試使用它,編譯器會發出抱怨。