2010-10-14 54 views
1

我試圖從使用LINQ在Internet上發佈的一些XML文件中提取數據。我正在使用LINQPad並使用C#語句。所有文件都具有相同的格式和元素名稱。我的目標是從每個文件中提取相同的元素,然後爲每個文件在一行中報告元素,創建一個排序網格。這將理想地被導出爲ex​​cel。我是LINQ的新手,所以任何幫助將不勝感激。 下面是我的工作代碼:使用LINQ在C#語句中查詢多個XML文件

// Load From Website. 
     XElement Tags=XElement.Load("http://fapt.efanniemae.com/epooltalk-hvd/pool.xml?type=XML&pn="+"510299"+".XML"); 
     //XElement Tags=XElement.Load("http://fapt.efanniemae.com/epooltalk-hvd/pool.xml?type=XML&pn="+(list1)+".XML"); 
     XNamespace p = "http://fapt.efanniemae.com"; 

/Run Export 

     var titles = 
     from book in Tags.Descendants(p + "Pool") 
     let bookAttributes = book.Element(p + "PoolFactors") 
     let title = ((string)book.Element(p + "PoolNumber")) 
     let title2 = ((string)bookAttributes.Element(p + "PoolFactor")) 
     let month = (string)bookAttributes.Element (p + "Month") 
     group title by month; 

     foreach (var group in titles) { 

     foreach (var title in group) { 
     Console.WriteLine("Pool Num |" + title); 
} 
} 
     foreach(XElement CusipElement in Tags.Descendants(p + "CUSIP")) { 
     Console.WriteLine("CUSIP |" +(string)CusipElement); 
     } 
     foreach(XElement PrefixElement in Tags.Descendants(p + "PoolPrefix")) { 
     Console.WriteLine("PoolPrefix |" +(string)PrefixElement); 
     } 
     foreach(XElement ObalElement in Tags.Descendants(p + "OriginalSecurityBalance")) { 
     Console.WriteLine("Orig. Bal |" +(string)ObalElement); 
     } 
     foreach(XElement OtermElement in Tags.Descendants(p + "WeightedAverageOrigLoanTerm")) { 
     Console.WriteLine("Orig. Term |" +(string)OtermElement); 
     } 
     foreach(XElement RtermElement in Tags.Descendants(p + "WAMnthsRemainingToAmortization")) { 
     Console.WriteLine("Remain Term |" +(string)RtermElement); 
     } 
     foreach(XElement WalaElement in Tags.Descendants(p + "WeightedAverageLoanAge")) { 
     Console.WriteLine("WALA |" +(string)WalaElement); 
     } 
     foreach(XElement AccrateElement in Tags.Descendants(p + "CurrentAccrualRate")) { 
     Console.WriteLine("Net Rate |" +(string)AccrateElement); 
     }   
     foreach(XElement MarginElement in Tags.Descendants(p + "WeightedAverageLoanMarginRate")) { 
     Console.WriteLine("WA Margin |" +(string)MarginElement); 
     } 
     foreach(XElement SubtElement in Tags.Descendants(p + "SubType")) { 
     Console.WriteLine("SubType |" +(string)SubtElement); 
     } 
     //foreach(XElement MonthElement in Tags.Descendants(p + "Month")) 
     //foreach(XElement WacElement in Tags.Descendants(p + "WAC")) { 
     //Console.WriteLine("WAC |" +(string)WacElement + "|" +(string)MonthElement); 
     //} 
     foreach(XElement UpdatedcapElement in Tags.Descendants(p + "UpdatedCap")) { 
     Console.WriteLine("Updated CAP |" +(string)UpdatedcapElement); 
     } 
     foreach(XElement IdateElement in Tags.Descendants(p + "IssueDate")) { 
     Console.WriteLine("Issue Date |" +(string)IdateElement); 
     } 
     foreach(XElement MdateElement in Tags.Descendants(p + "MaturityDate")) { 
     Console.WriteLine("Maturity Date |" +(string)MdateElement); 
     } 
     foreach(XElement RadjElement in Tags.Descendants(p + "RateAdjustmentFrequency")) { 
     Console.WriteLine("Rate Adj Freq |" +(string)RadjElement); 
     } 
     foreach(XElement PcapElement in Tags.Descendants(p + "PerAdjustmentCap")) { 
     Console.WriteLine("Period Cap |" +(string)PcapElement); 
     } 
     foreach(XElement PchgfreqElement in Tags.Descendants(p + "PaymentChangeFrequency")) { 
     Console.WriteLine("Pymt Chg Freq |" +(string)PchgfreqElement); 
     } 
     foreach(XElement MtrElement in Tags.Descendants(p + "WeightedAverageMonthsToRoll")) { 
     Console.WriteLine("WA MTR |" +(string)MtrElement); 
     } 
     foreach(XElement RatecapElement in Tags.Descendants(p + "WeightedAverageCap")) { 
     Console.WriteLine("WA CAP |" +(string)RatecapElement); 
     } 
var Months = Tags.Descendants(p + "Month") 
     .Select(titleElement => (string)titleElement); 
foreach (string title in Months) { 
Console.WriteLine("Months |" + title); 
} 
var Wacs = Tags.Descendants(p + "WAC") 
      .Select(titleElement => (string)titleElement); 
foreach (string title in Wacs) { 
Console.WriteLine("WAC |" + title); 
} 
var Wams = Tags.Descendants(p + "WAM") 
      .Select(titleElement => (string)titleElement); 
foreach (string title in Wams) { 
Console.WriteLine("WAM |" + title); 
} 
var Factors = Tags.Descendants(p + "Factor") 
      .Select(titleElement => (string)titleElement); 
foreach (string title in Factors) { 
Console.WriteLine("Factor |" + title); 
} 

如何獲得查詢的元素出現水平和一些分隔符?

目前我的代碼僅適用於1個XML文件。這怎麼可以改變循環多個文件?源文件名全都具有相同的基本URL,唯一的區別是結尾語句。有沒有辦法讓Load引用的基URL與一個變量列表連接在一起,後者將包含結束語句?

任何和所有的建議。

回答

1

它看起來像你在這方面做了一些體面的努力,所以對你的帽子。我認識到一些初學者LINQ在代碼中的錯誤或誤解,並希望在下面解決它們。

  1. 如果您希望存在一個元素,請不要使用Descendants。改爲使用Element。從「Pool Num」到「WA CAP」的每個選項都是一個獨立的XML元素,可以用這種方式直接檢索:parent.Element(p + "PoolNumber")其中parent是所需元素的父元素。
  2. 要獲取元素的值,請使用Value屬性:parent.Element(p + "PoolNumber").Value。使用(string)轉換不是不正確的,但是當您懷疑該元素可能存在或不存在時,最好使用它。如果它不存在,則調用Value將返回NullReferenceException,因爲它將爲空。投它可以解決這個問題。在下面的代碼中測試這個簡單的方法是在pool的聲明後添加一個pool.Element(p + "PoolNumber").Remove();並觀察它是否中斷。然後用你的(string)的方法,並愉快地繼續看着它。
  3. 與點#1相關的Element方法有效地取代了對結果的需要,即foreach只是爲了獲得一個值。我建議玩First,Single,FirstOrDefaultSingleOrDefault方法。您有LINQPad,請查看示例並與它們一起玩。

除此之外,您的本地變量名稱應該以標準格式期望的小寫字母開頭。將LINQ方法調用排列在單獨的行上,並在點表示法的開始處對齊它們也很有幫助。

如何獲得查詢的元素 出現橫向的,並與一些 分隔符?

使用String.Join方法。使用.NET 4.0,無需調用ToArray,因爲該方法接受IEnumerable<string>的過載。

目前我的代碼只適用於1 XML 文件。如何修改多個文件以循環使用 ?

將您的池號碼值放入列表中,然後對其進行foreach並將邏輯放置在循環體中。看到我的代碼如下。

這是您的代碼清理版本。我不確定你是否想要所有的標題都是水平的,或只關心在具有多個值的項目上使用分隔符。

// load from websites based on pool numbers in list 
var list = new List<string> { "510299", "510300"}; 
foreach (var poolNumber in list) 
{ 
    XElement tags=XElement.Load("http://fapt.efanniemae.com/epooltalk-hvd/pool.xml?type=XML&pn=" + poolNumber + ".XML"); 
    XNamespace p = tags.GetDefaultNamespace(); 

    // export process 

    XElement pool = tags.Element(p + "Pool"); 
    Console.WriteLine("Pool Num |" + pool.Element(p + "PoolNumber").Value); 
    Console.WriteLine("CUSIP |" + pool.Element(p + "CUSIP").Value); 
    Console.WriteLine("PoolPrefix |" + pool.Element(p + "PoolPrefix").Value); 
    Console.WriteLine("Orig. Bal |" + pool.Element(p + "OriginalSecurityBalance").Value); 
    Console.WriteLine("Orig. Term |" + pool.Element(p + "WeightedAverageOrigLoanTerm").Value); 
    Console.WriteLine("Remain Term |" + pool.Element(p + "WAMnthsRemainingToAmortization").Value); 
    Console.WriteLine("WALA |" + pool.Element(p + "WeightedAverageLoanAge").Value); 
    Console.WriteLine("Net Rate |" + pool.Element(p + "CurrentAccrualRate").Value); 
    Console.WriteLine("WA Margin |" + pool.Element(p + "WeightedAverageLoanMarginRate").Value); 
    Console.WriteLine("SubType |" + pool.Element(p + "SubType").Value); 
    Console.WriteLine("Updated CAP |" + pool.Element(p + "UpdatedCap").Value); 
    Console.WriteLine("Issue Date |" + pool.Element(p + "IssueDate").Value); 
    Console.WriteLine("Maturity Date |" + pool.Element(p + "MaturityDate").Value); 
    Console.WriteLine("Rate Adj Freq |" + pool.Element(p + "RateAdjustmentFrequency").Value); 
    Console.WriteLine("Period Cap |" + pool.Element(p + "PerAdjustmentCap").Value); 
    Console.WriteLine("Pymt Chg Freq |" + pool.Element(p + "PaymentChangeFrequency").Value); 
    Console.WriteLine("WA MTR |" + pool.Element(p + "WeightedAverageMonthsToRoll").Value); 
    Console.WriteLine("WA CAP |" + pool.Element(p + "WeightedAverageCap").Value); 

    var poolFactors = pool.Element(p + "PoolFactors"); 
    var months = poolFactors.Descendants(p + "Month") 
          .Select(m => m.Value); 
    Console.WriteLine("Months |" + String.Join(", ", months.ToArray())); 

    var wacs = poolFactors.Descendants(p + "WAC") 
          .Select(wac => wac.Value); 
    Console.WriteLine("WAC |" + String.Join(", ", wacs.ToArray())); 

    var wams = poolFactors.Descendants(p + "WAM") 
          .Select(wam => wam.Value); 
    Console.WriteLine("WAM |" + String.Join(", ", wams.ToArray())); 

    var factors = poolFactors.Descendants(p + "Factor") 
          .Select(f => f.Value); 
    Console.WriteLine("Factor |" + String.Join(", ", factors.ToArray())); 

    Console.WriteLine(); 
} 
1

我在看堆棧溢出的另一個問題時看到了這個問題,並且注意到這個問題仍然沒有答案。我不知道這是否仍然是一個問題,但對於閱讀此內容的任何人來說,這是對幾個來源執行LINQ查詢的一種方式。

訣竅是使用[Enumerable.Concat(TSource)方法] [1]。

XElement tags=XElement.Load("http://fapt.efanniemae.com/epooltalk-hvd/pool.xml?type=XML&pn="+"510299"+".XML"); 
XElement tags2=XElement.Load("http://fapt.efanniemae.com/epooltalk-hvd/pool.xml?type=XML&pn="+(list1)+".XML"); 

var titles = 
    from book in tags.Descendants(p + "Pool").Concat(tags2.Descendants(p + "Pool")) 
    let bookAttributes = book.Element(p + "PoolFactors") 
    let title = ((string)book.Element(p + "PoolNumber")) 
    let title2 = ((string)bookAttributes.Element(p + "PoolFactor")) 
    let month = (string)bookAttributes.Element (p + "Month") 
    group title by month; 

我希望這可以幫助你或任何人。 (1):http://msdn.microsoft.com/en-us/library/bb302894.aspx Enumerable.Concat(TSource)方法