2016-04-21 73 views
0

這是我擁有的一個XML文件的一小部分(見下文)。使用LINQ to XML查詢元素時出錯

我能讀我需要什麼,就像我可以得到消息等,但在PreflightResultEntry節的一個有一個叫做瓦爾我需要「<Var name="NumPages">8</Var>元素集「

--  
<PreflightResultEntry type="GeneralDocInfo"> 
    <PreflightResultEntryMessage xml:lang="en-US"> 
     <Message>457834a.pdf </Message> 
     <StringContext> 
      <BaseString>%FileInfo%</BaseString> 
      <Const name="Category">GeneralDocInfo</Const> 
      <Const name="ActionID">-1</Const> 
      <Instance> 
       <Var name="FileInfo"> 
        <Var name="DIPath">/V/PitStop/Testing/Mike/Processed Docs on Success/457834a.pdf</Var> 
        <Var name="CreationDate">D:20120724153648-05'00'</Var> 
        <Var name="ModDate">D:20120725134534-04'00'</Var> 
        <Var name="Producer">Adobe PDF Library 10.0</Var> 
        <Var name="Creator">Acrobat PDFMaker 10.1 for Word</Var> 
        <Var name="Author">DOL Comments</Var> 
        <Var name="Title"/> 
        <Var name="Subject"/> 
        <Var name="Keywords"/> 
        <Var name="Trapped">1</Var> 
        <Var name="NumPages">8</Var> 
        <Var name="Major">1</Var> 
        <Var name="Minor">5</Var> 
        <Var name="WasRepairedOnOpen">0</Var> 
        <Var name="IsLinearized">0</Var> 
        <Var name="ContainsThumbnails">0</Var> 
        <Var name="LeftToRightReading">1</Var> 
        <Var name="ContainsJobTicket">0</Var> 
        <Var name="EncryptionType">1</Var> 
        <Var name="Permissions">-1</Var> 
        <Var name="PrinergyTraps">3</Var> 
       </Var> 
       <Location page="-1"/> 
      </Instance> 
     </StringContext> 
    </PreflightResultEntryMessage> 
</PreflightResultEntry> 
     --- 

這裏我已經得到了適用於郵件和類型

List<PitStopMessage> messages = XDocument.Load(file) 
     .Descendants("PreflightResultEntryMessage") 
     .Where(x => x.Parent != null) 
     .Select(x => new PitStopMessage() 
     { 
      message = x.Element("Message").Value, 
      type = x.Parent.Attribute("type").Value, 
      xmllevel = x.Parent.Attribute("level") != null ? x.Parent.Attribute("level").Value : String.Empty, 
      link = 0 
     }).ToList(); 

我需要一個新的查詢元素var只有當它退出父元素PreflightResultEntry

這裏我到目前爲止,但它給了我一個錯誤「對象引用未設置爲對象的實例」。這是告訴我在找什麼(元素)不存在。

List<PitStopPages> messages = XDocument.Load(file) 
    .Descendants("PreflightResultEntryMessage") 
    .Where(x => x.Parent != null && x.Parent.Attribute("type").Value == "GeneralDocInfo" && x.Parent.Element("Var").Value == "NumPages") 
    .Select(x => new PitStopPages() 
    { 
     Pages = x.Parent.Attribute("name").Value 
    }).ToList(); 

回答

0

如果您邏輯地閱讀了您的查詢,您可能會發現錯誤。

您的查詢試圖找到:

  • 的元素稱爲PreflightResultEntryMessage
  • 凡母公司擁有的GeneralDocInfo
  • 一個type屬性如果它的父元素的第一個孩子命名Var具有價值NumPages
  • 獲取父元素的name屬性值

這個問題是最後兩部分。 Parent在你所有的情況下是PreflightResultEntry元素。PreflightResultEntry沒有任何的孩子Var元素,沒有Var元素有NumPagesPreflightResultEntry沒有name屬性。這些中的任何一個都會導致空引用異常(您所看到的異常)。

這可能是從上到下的方法,而不是找到一個元素,然後回顧其父項。所以:

  • 查找與GeneralDocInfo
  • 一個type屬性稱爲PreflightResultEntry元素獲得後代Var元素具有name屬性的NumPages

所以:

var numPages = (int)XDocument.Load(file) 
     .Descendants("PreflightResultEntry") 
     .Where(x => (string) x.Attribute("type") == "GeneralDocInfo") 
     .Descendants("Var") 
     .Single(x => (string) x.Attribute("name") == "NumPages"); 

this fiddle爲一個工作演示。

+0

謝謝,但我提供的XML文檔只是保存文檔的一個片段。當我將代碼應用於整個XML文檔文檔時,出現以下錯誤:「根級別的數據無效,行1,位置1」。 。一些元素不具備其他元素的所有元素。所以可能有元素var,有些可能不會。我認爲這就是爲什麼我有錯誤。 – Mike

+0

好吧我發現問題有一個DTD在文檔的頂部,一旦我刪除它的工作,謝謝 – Mike

0

我建議使用XPath來選擇你想要的節點。您可以使用方法XPathSelectElements並通過您的XPath。如果您只需要選擇一個節點,則可以使用XPathSelectElement(不含's')。

在你的情況,我認爲XPath應該是:/PreflightResultEntry//Var[@name='NumPages']

可以測試XPathhere

+0

這工作在我發佈的片段,但在完整的XML文件它不工作。 PreflightResultEntry部分重複但Var不。不知道是否這個問題。但那個你。 – Mike

+0

您可以檢查方法的輸出。如果'Var'不存在,它將返回一個空列表或'null'。 – AnhTriet

0

讓我什麼@AnhTriet建議擴大,

var xml = new XmlDocument(); 

xml.LoadXml(str); // suppose that str string contains your xml 

var xnList = xml.SelectNodes("/PreflightResultEntry//Var[@name='NumPages']"); 

foreach (XmlNode xn in xnList) 
{ 
    Console.WriteLine(xn.InnerText); //this should print the 8 
} 

.NET Fiddle

爲了能夠使用XPathSelectElement方法則需要使用XDocument

先加載XML所以,它會是這樣的:

var xml = XDocument.Load(file); 

XmlNode node = xml.XPathSelectElement("/PreflightResultEntry//Var[@name='NumPages']"); 

Console.WriteLine(node.InnerText);