c#
  • xml
  • linq
  • crystal-reports
  • linq-to-xml
  • 2011-05-08 106 views 2 likes 
    2

    我有一個XML格式的CrystalReport報告父節點的屬性子節點(抱歉冗長外,我切了大部分樣本數據)獲得基於

    <?xml version="1.0" encoding="UTF-8" ?> 
    <FormattedReport xmlns = 'urn:crystal-reports:schemas' xmlns:xsi = 'http://www.w3.org/2000/10/XMLSchema-instance'> 
    <FormattedAreaPair Level="0" Type="Report"> 
    <FormattedAreaPair Level="1" Type="Details"> 
    <FormattedArea Type="Details"> 
    <FormattedSections> 
    <FormattedSection SectionNumber="0"> 
    <FormattedReportObjects> 
    <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:string" FieldName="{AIRCRAFT.Tail Number}"><ObjectName>Field2</ObjectName> 
    <FormattedValue>C-FBCS</FormattedValue> 
    <Value>C-FBCS</Value> 
    </FormattedReportObject> 
    <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:string" FieldName="{AIRCRAFT.Type ID}"><ObjectName>Field8</ObjectName> 
    <FormattedValue>DHC8</FormattedValue> 
    <Value>DHC8</Value> 
    </FormattedReportObject> 
    <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:unsignedLong" FieldName="{TRIP LEGS.Trip Number}"><ObjectName>Field9</ObjectName> 
    <FormattedValue>68344</FormattedValue> 
    <Value>68344.00</Value> 
    </FormattedReportObject> 
    </FormattedReportObjects> 
    </FormattedSection> 
    </FormattedSections> 
    </FormattedArea> 
    </FormattedAreaPair> 
    <FormattedAreaPair Level="1" Type="Details"> 
    <FormattedArea Type="Details"> 
    <FormattedSections> 
    <FormattedSection SectionNumber="0"> 
    <FormattedReportObjects> 
    <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:string" FieldName="{AIRCRAFT.Tail Number}"><ObjectName>Field2</ObjectName> 
    <FormattedValue>C-FBCS</FormattedValue> 
    <Value>C-FBCS</Value> 
    </FormattedReportObject> 
    <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:string" FieldName="{AIRCRAFT.Type ID}"><ObjectName>Field8</ObjectName> 
    <FormattedValue>DHC8</FormattedValue> 
    <Value>DHC8</Value> 
    </FormattedReportObject> 
    <FormattedReportObject xsi:type="CTFormattedField" Type="xsd:unsignedLong" FieldName="{TRIP LEGS.Trip Number}"><ObjectName>Field9</ObjectName> 
    <FormattedValue>68344</FormattedValue> 
    <Value>68344.00</Value> 
    </FormattedReportObject> 
    </FormattedReportObjects> 
    </FormattedSection> 
    </FormattedSections> 
    </FormattedArea> 
    </FormattedAreaPair> 
    ... 
    </FormattedAreaPair> 
    </FormattedReport> 
    

    我試圖使用LINQ到XML查詢提取 節點基於父節點的字段名稱屬性並將它們放入對象中。沒有Value或FormattedReportObject節點的父項的唯一屬性。到目前爲止,這是我的代碼,這樣做

    from fs in xDoc.Descendants("FormattedSection") 
    select new FlightSchedule 
    { 
        AircraftType = from fos in fs.Descendants("FormattedReportObjects") 
           from fo in fs.Descendants("FormattedReportObject") 
           where fo.Attribute("FieldName").Value.Equals("{AIRCRAFT.Type ID}") 
           from e in fo.Element("Value") 
           select e.Value), 
        .... 
    }; 
    

    我不斷收到錯誤:

    型「System.Xml.Linq.XElement」的表達,在以後允許從子句中使用源類型「System.Collections.Generic.IEnumerable」查詢表達式。在對'SelectMany'的調用中,類型推斷失敗)

    或者如果我沒有收到錯誤我最終沒有收到任何東西。任何建議將不勝感激改善我的查詢。

    回答

    2

    您的代碼有幾個問題。首先,編譯器所抱怨的是,正如@MizardX所提到的那樣,您正在使用fo.Element("Value")就好像它是一個序列。你可能想要寫的是let e = fo.Element("Value")(或完全跳過這部分,直接寫select fo.Element("Value").Value)。

    另一個問題是您的XML使用的是命名空間,但您不是。這意味着你應該創建一個XNamespace對象,並在有元素名稱的地方使用它。

    此外,您的代碼寫入的方式,AircraftType是一串字符串。我認爲這不是你想要的。

    而且看到你想對FieldName的不同值做同樣的事情,你可能想把它變成一個方法。

    隨着上述固定提到的所有問題,代碼應該是這個樣子:

    static readonly XNamespace ns = XNamespace.Get("urn:crystal-reports:schemas"); 
    
    string GetFieldValue(XElement fs, string fieldName) 
    { 
        return (from fo in fs.Descendants(ns + "FormattedReportObject") 
          where fo.Attribute("FieldName").Value == fieldName 
          let e = fo.Element(ns + "Value") 
          select e.Value).Single(); 
    } 
    … 
    var flts = (from fs in xDoc.Descendants(ns + "FormattedSection") 
          select new FlightSchedule 
          { 
           AircraftType = GetFieldValue(fs, "{AIRCRAFT.Type ID}"), 
           … 
          }).ToList(); 
    
    1

    fo.Element("Value")返回XElement -object。你想要的可能是fo.Elements("Value")(注意複數'')。

    錯誤消息抱怨說它不知道如何遍歷XElement對象。

    你沒有得到任何結果的原因是XML文件正在使用命名空間。要找到默認名稱空間外的元素,您需要在節點名稱前加上名稱空間的前綴。

    我還注意到你沒有使用fos變量,所以循環是不必要的。 fs.Decendants()已經給你正確的結果。

    List<FlightSchedule> flts = 
        (from fs in xDoc.Descendants("{urn:crystal-reports:schemas}FormattedSection") 
        select new FlightSchedule 
        { 
         AircraftType = 
          (from fo in fs.Descendants("{urn:crystal-reports:schemas}FormattedReportObject") 
           where fo.Attribute("FieldName").Value == "{AIRCRAFT.Type ID}" 
           from e in fo.Elements("{urn:crystal-reports:schemas}Value") 
           select e.Value), 
              .... 
        }).ToList(); 
    
    相關問題