0

我之前问过这个问题,我得到了非常快速和有用的回答:Linq to XML query not pick up any values

我遵循了标记为正确的答案中给出的建议,该建议有效,并允许我选择“产品”标签。我现在正在那个“产品”标签中搜索,以便找到要导入我的数据库的值,但我又有点卡住了。

这是我的 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>joe@bloggs.com</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 之前我从未见过 .Descendants() ,我明白它的含义,但从我读到的内容来看,我应该也可以在这里使用 .Elements() 吗?

谁能看到可能出了什么问题?

4

2 回答 2

1

好吧,正如我回答您之前的问题一样,我想我可能会有所帮助...

您的文档有一个命名空间 (xmlns)。如果你想使用 Elements("tagName") 或 Element("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;
  }

如果您绝对不想使用命名空间,则必须使用 Descendants() 和 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 Check,这当然是要做的事情。

另请注意,第二个查询的性能会降低,因为 Descendants() 会枚举元素的所有子元素,而不考虑层次结构。而 Elements() 将仅检索直接子节点。

于 2012-06-14T14:17:02.780 回答
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();
            }
于 2012-06-14T13:21:48.080 回答