2012-06-14 29 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

查看已更新的答案 –