2012-06-14 57 views
0

查詢XML我問這個問題前面,我得到了非常快速的和有益的對策:Linq to XML query not picking up any values異常使用LINQ

我跟着意見,給出的答案標記爲正確的哪些工作,讓我拿起「產品'標籤。我現在正在'產品'標籤內搜索,以找到值導入到我的數據庫,我有點卡住了。

這裏是我的XML文件的結構:

<?xml version="1.0"?> 
<!DOCTYPE ONIXMessage SYSTEM "http://www.editeur.org/onix/2.1/reference/onix-international.dtd"> 
<ONIXMessage xmlns="http://www.editeur.org/onix/2.1/reference" release="2.1"> 
    <Header> 
    <FromCompany>MyCo</FromCompany> 
    <FromPerson>Joe Bloggs</FromPerson> 
    <FromEmail>[email protected]</FromEmail> 
    <SentDate>20120522</SentDate> 
    </Header> 
    <Product> 
    <ProductForm>DG</ProductForm> 
    <Title> 
     <TitleType>01</TitleType> 
     <TitleText>Blogg</TitleText> 
    </Title> 
    <WorkIdentifier> 
     <WorkIDType>15</WorkIDType> 
     <IDValue>PI3564231</IDValue> 
    </WorkIdentifier> 
    <Language> 
     <LanguageRole>01</LanguageRole> 
     <LanguageCode>eng</LanguageCode> 
    </Language> 
    </Product> 
</ONIXMessage> 

這裏是我的代碼片段:

 XElement onix = XElement.Load(fs); 

     // Get all the product information. 
     // 
     var products = onix.Descendants().Where(m => m.Name.LocalName == "Product").ToList(); 

     foreach (var p in products) 
     { 
      try 
      { 
       prod.Title = p.Elements("Title").First(t => (t.Element("TitleType").Value == "01")).Element("TitleText").Value; 
       //further processing 
      } 
      catch (Exception exp) 
      { 
       throw new FileProcessingException("Unable to process product.", exp); 
      } 
     } 

當我搜索標題文本如上圖所示,異常被捕獲。例外是「對象引用未設置爲對象的實例」。該項目顯然在XML文件中,它只是沒有正確選擇它。

我從來沒有見過.toda之前,我得到了什麼意思,但從我讀的我應該能夠使用.Elements()這裏呢?

任何人都可以看到什麼可能是錯的?

+2

您能告訴我們錯誤發生的位置以及Exception的說明嗎? – JDB

+0

此外,.First()是棘手的,因爲如果沒有發現任何東西,它將拋出一個異常。如果沒有發現任何內容,則FirstOrDefault()將返回Null,如果不測試Null,則仍然會導致NullReferenceException。 – JDB

+0

如果你在失敗的線上放置一個斷點並評估p.Element(「Title」),它是否包含任何元素?如果你評估'p.Elements(「Title」)。First(t =>(t.Element(「TitleType」)。Value ==「01」))''是異常來自哪裏? –

回答

1

嗯,我回答你剛纔的問題,我想我可以幫助...

您的文檔有一個命名空間(XMLNS)。 如果你想使用元素(「tagName」)或元素(「tagName」)等,你必須前綴所有你的TagName的命名空間。

所以您的查詢將工作(由Habib.OSU在你前面的問題提到的),如果你做

XNamespace ns = onix.Attribute("xmlns").Value; 
    var products2 = onix.Elements(ns + "Product").ToList(); 

    foreach (var p in products2) 
    { 
     var title = p.Elements(ns + "Title") 
     .First(t => (t.Element(ns + "TitleType").Value == "01")) 
     .Element(ns + "TitleText").Value; 
    } 

如果你絕對不想使用的命名空間,你必須使用後代()和Name.LocalName。它會給你一樣的,但是......它真的很難閱讀。

var products = onix.Descendants().Where(m => m.Name.LocalName == "Product").ToList(); 

foreach (var p in products) 
{ 

     var title = p.Descendants().Where(m => m.Name.LocalName == "Title") 
     .Descendants() 
     .First(m => m.Name.LocalName == "TitleType" && m.Value == "01") 
     .Parent 
     .Descendants() 
     .First(m => m.Name.LocalName == "TitleText") 
     .Value; 

} 

我沒有把任何NULL檢查,這將是的,當然,事情做。

另請注意,第二個查詢的性能會降低,因爲Descendants()會枚舉元素的所有子元素,而不會考慮層次結構。而Elements()只會檢索直接的子節點。

+0

感謝您的回覆。像往常一樣非常有用:) – 109221793

0

試試這個:

XDocument doc = XDocument.Load(fs); 
var products= from elements in doc.Elements("ONIXMessage").Elements("Product"); 
    foreach (var p in products) 
      { 
        var title = (from items in p.Elements("Title") 
           where items.Element("TitleType").Value == "01" 
           select items.Element("TitleText").Value).FirstOrDefault(); 
      } 
+0

感謝您的答覆。我嘗試了你的上面的例子,不再拋出異常,但是現在只填充'null',所以無論出於何種原因,linq都沒有正確地拾取XML。 – 109221793

+0

查看已更新的答案 –