2017-01-16 56 views
0

我試圖優化我的查詢,只讓活動的公司但不是「債務」。公司。另外,我只需要爲第一個安全性提供數據。這裏是我的XML字符串的樣子:LINQ到XML:找到第一個安全

<DataFeed FeedName="AdminData"> 
    <Issuer> 
    <id>579</id> 
    <name>Microsoft</name> 
    <symbol>MSFT-NSDQ</symbol> 
    <active>1</active> 
    <shortName>FirstService</shortName> 
    <clientCode>MSFT=US</clientCode> 
    <hide>0</hide> 
    <securities> 
     <Security> 
     <id>579</id> 
     <rank>0</rank> 
     <pricingSymbol>MSFT-NSDQ</pricingSymbol> 
     <displaySymbol>MSFT</displaySymbol> 
     <active>1</active> 
     <clientCode>MSFT=US</clientCode> 
     <coverage> 
      <Coverage> 
      <analyst id="101" clientCode="BG" firstName="Bill" lastName="Gates" rank="1"/> 
      </Coverage> 
     </coverage> 
     <customFields> 
      <customField name="ADP Security Code" type="Textbox"> 
      <values> 
       <value>F020941</value> 
      </values> 
      </customField> 
     </customFields> 
     </Security> 
     <Security> 
     <id>581</id> 
     <rank>1</rank> 
     <pricingSymbol>MSFT-TSX</pricingSymbol> 
     <displaySymbol>MSFT-TSX</displaySymbol> 
     <active>1</active> 
     <clientCode>MSFT=US</clientCode> 
     <customFields> 
      <customField name="ADP Security Code" type="Textbox"> 
      <values> 
       <value>F020941</value> 
      </values> 
      </customField> 
     </customFields> 
     </Security> 
    </securities> 
    </Issuer> 
    <Issuer> 
    <id>558</id> 
    <name>Apple</name> 
    <symbol>AAPL-NYSE</symbol> 
    <active>1</active> 
    <clientCode>AAPL=US</clientCode> 
    <hide>0</hide> 
    <securities> 
     <Security> 
     <firmId>18524</firmId> 
     <id>558</id> 
     <rank>0</rank> 
     <pricingSymbol>AAPL-NYSE</pricingSymbol> 
     <displaySymbol>AAPL</displaySymbol> 
     <active>1</active> 
     <clientCode>AAPL=US</clientCode> 
     <coverage> 
      <Coverage> 
      <analyst id="129" clientCode="SJ" firstName="Steve" lastName="Jobs" rank="1"/> 
      </Coverage> 
     </coverage> 
     <customFields> 
      <customField name="ADP Security Code" type="Textbox"> 
      <values> 
       <value>F106997</value> 
      </values> 
      </customField> 
     </customFields> 
     </Security> 
    </securities> 
    </Issuer> 
    <Issuer> 
    <id>612</id> 
    <name>Tesla</name> 
    <symbol>DEBT.TSLA</symbol> 
    <active>1</active> 
    <clientCode>DEBT.TSLA</clientCode> 
    <hide>0</hide> 
    <securities> 
     <Security> 
     <id>613</id> 
     <rank>0</rank> 
     <pricingSymbol>TSLA-NYSE</pricingSymbol> 
     <displaySymbol>TSLA</displaySymbol> 
     <active>1</active> 
     <clientCode>DEBT.TSLA</clientCode> 
     <coverage> 
      <Coverage> 
      <analyst id="101" clientCode="EM" firstName="Elon" lastName="Musk" rank="1"/> 
      </Coverage> 
     </coverage> 
     <customFields> 
      <customField name="ADP Security Code" type="Textbox"> 
      <values> 
       <value>G002869</value> 
      </values> 
      </customField> 
     </customFields> 
     </Security> 
    </securities> 
    </Issuer> 
</DataFeed> 

這裏是我迄今爲止對我的查詢:

var xDoc = XDocument.Parse(xmlString) 
.Descendants("Issuer") 
.Where(xd => (int?)xd.Element("active") == 1 && (int?)xd.Element("hide") == 0 && 
    !xd.Element("clientCode").ToString().StartsWith("DEBT.") 
    ) 
.Select(xd => new { 
    Ticker = xd.Element("clientCode").Value, 
    Symbol = xd.Element("symbol").Value, 
    DisplaySymbol = xd.Element("displaySymbol").Value, 
    AnalystFName = xd.Element("Analyst").Attribute("firstName").Value, 
    CompanyName = xd.Element("name").Value, 
    ADP = xd. <-- not sure what to do here 
}); 

,我發現了以下錯誤:

NullReferenceException: Object reference not set to an instance of an object. 

我覺得問題是,我似乎無法獲得唯一的安全性。我如何獲得只有第一個安全性所需的信息。另外,如何獲得ADP代碼?我很難想出代碼。最後,我試圖得到如下結果:

enter image description here

回答

3

Element只得到直接子元素,你需要在Descendants這裏的某些點。

你或許可以做到這一點與一些重構爲更小的組合的一大塊漂亮時尚,但是這將讓你的示例文件所做的工作:

var rows = 
    from issuer in doc.Descendants("Issuer") 
    let ticker = (string) issuer.Element("clientCode") 
    let symbol = (string) issuer.Element("symbol") 
    where (int?) issuer.Element("active") == 1 && 
      (int?) issuer.Element("hide") == 0 && !ticker.StartsWith("DEBT.") 
    from security in issuer.Descendants("Security").Take(1) 
    from analyst in security.Descendants("analyst") 
    from adpField in security.Descendants("customField") 
    where (string) adpField.Attribute("name") == "ADP Security Code" 
    select new 
    { 
     Ticker = ticker, 
     Symbol = symbol, 
     DisplaySymbol = (string) security.Element("displaySymbol"), 
     AnalystFName = (string) analyst.Attribute("firstName"), 
     AnalystLName = (string) analyst.Attribute("lastName"), 
     ADP = adpField.Value 
    }; 

了工作演示見this fiddle