2010-10-14 24 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)方法