0

以前にこの質問をしたところ、非常に迅速で役立つ回答が得られました。Linq to XML クエリが値を取得しない

正しいとマークされた回答に示されているアドバイスに従い、「製品」タグを取得することができました。データベースにインポートする値を見つけるために、その「製品」タグ内を検索していますが、また少し行き詰まっています。

私の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 By 名前空間の前に付ける必要があります。

そのため、クエリは機能します (前の質問で 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 チェックは入れませんでした。これは当然のことです。

また、Descendants() は階層を考慮せずに要素のすべての subElements を列挙するため、2 番目のクエリはパフォーマンスが低下することに注意してください。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 に答える