2013-01-24 23 views
11

に空/ブランクの要素を削除します。私は、各ノードを反復し、次の操作を実行しようとしている私はこのようなXML文書の持つXMLノードのコレクション

<magento_api> 
    <data_item> 
     <code>400</code> 
     <message>Attribute weight is not applicable for product type Configurable Product</message> 
    </data_item> 
    <data_item> 
     <code>400</code> 
     <message>Resource data pre-validation error.</message> 
    </data_item> 
    <data_item> 
     <code>1</code> 
     <message></message> 
    </data_item> 
    <data_item> 
     <code></code> 
     <message>No code was given</message> 
    </data_item> 
</magento_api> 

を:

  1. いずれかを捨てます空白/空白の要素。
  2. 値を含む要素のみで新しいNodeを生成します。
  3. 結果のドキュメントを別のWebサービスに送信します。

私が苦労している部分は、各ノードを反復し、各要素でヌル値をチェックする方法です。

私は http://rextester.com/runcodeで出て、このコードをテストしてきたが、それを把握することができないよう

Console.WriteLine("Querying tree loaded with XElement.Load"); 
Console.WriteLine("----"); 
XElement doc = XElement.Parse(@"<magento_api> 
      <data_item> 
      <code>400</code> 
      <message>Attribute weight is not applicable for product type Configurable Product</message> 
      </data_item> 
      <data_item> 
      <code>400</code> 
      <message>Resource data pre-validation error.</message> 
      </data_item> 
      <data_item> 
      <code>1</code> 
      <message></message> 
      </data_item> 
      <data_item> 
      <code></code> 
      <message>No code was given</message> 
      </data_item> 
    </magento_api>"); 

int counter = 1; 
IEnumerable<XNode> nodes = 
    from nd in doc.Nodes() 
    select nd; 
foreach (XNode node in nodes) 
{ 
    Console.WriteLine(counter + "-" + node); 
    IEnumerable<XElement> elements = 
    from el in node //this is where I've been trying various methods, but no dice. 
    select el; 
    foreach (XElement e in elements) 
    { 
      Console.WriteLine(counter + "-" + e.Name + "-" + e.Value + "\r\n"); 
    } 
    counter++; 
} 

上記のXML入力に基づいて、私は次のような出力を得ることを望んだ:

<magento_api> 
    <data_item> 
     <code>400</code> 
     <message>Attribute weight is not applicable for product type Configurable Product</message> 
    </data_item> 
    <data_item> 
     <code>400</code> 
     <message>Resource data pre-validation error.</message> 
    </data_item> 
    <data_item> 
     <code>1</code> 
    </data_item> 
    <data_item> 
     <message>No code was given</message> 
    </data_item> 
</magento_api> 

正しいメソッドを使用してノードと要素を反復処理しているかどうかはわかりません。

+1

"NULLの要素"とはどういう意味ですか?また、ここでは何も目的のためにクエリー式を使用していないことに注意してください - たとえば、 'el from node select el'の代わりに' node'を後で使うことができます... –

+0

@JonSkeet - /空の。それはNULLと同じではありませんか? – jared

+0

実際には、XMLに "NULL"という概念はありません。また、どのような構造が戻ってくるのかははっきりしていません。与えられた入力ファイルの目的の出力を使って質問を編集することができれば便利です。 –

答えて

30

1つの1ライナーで作業を行うことができ、すべての要素を反復処理する必要はありません。ここではそれが行く:

doc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove(); 

テスター

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Xml; 
using System.Xml.Linq; 

namespace ConsoleApplication1 
{ 
    public class TestRemove 
    { 
     public static void Main() { 
      Console.WriteLine("----OLD TREE STARTS---"); 
      XElement doc = XElement.Parse(@"<magento_api> 
               <data_item> 
               <code>400</code> 
               <message>Attribute weight is not applicable for product type Configurable Product</message> 
               </data_item> 
               <data_item> 
               <code>400</code> 
               <message>Resource data pre-validation error.</message> 
               </data_item> 
               <data_item> 
               <code>1</code> 
               <message></message> 
               </data_item> 
               <data_item> 
               <code></code> 
               <message>No code was given</message> 
               </data_item> 
             </magento_api>"); 
      Console.Write(doc.ToString()); 
      Console.WriteLine(""); 
      Console.WriteLine("----OLD TREE ENDS---"); 
      Console.WriteLine(""); 
      doc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove(); 
      Console.WriteLine("----NEW TREE STARTS---"); 
      Console.Write(doc.ToString()); 
      Console.WriteLine(""); 
      Console.WriteLine("----NEW TREE ENDS---"); 
      Console.ReadKey(); 
     } 
    } 
} 

そしてまた、私は再びそれを見つける必要がある場合にはVBでhere

+1

+1 - 勝利のための1つのライナー! – jared

+1

属性を持つSelf-Closing要素に注意する必要があります。エンドユーザーIEの要望はほとんどありません。 aolszowka

+0

+1 @aolszowka。また、magento_apiは最も奇妙な場所で属性を使用します。私はこのアプローチを関連する問題に取り入れました。 http://stackoverflow.com/a/31708077/969367 – Vic

1

をテストすることができます。

doc.Descendants().Where(Function(e) String.IsNullOrEmpty(e.Value)).Remove() 
4
doc.Descendants().Where(e => string.IsNullOrEmpty(e.Value)).Remove(); 

この1行は、空の子タグでいっぱいの空の親タグをスローしません。あなたの状況に適しているかもしれないし、そうでないかもしれない子供たちを取り除くだけです。これを達成するには本当に簡単な変更です。最初に最低レベルから削除しなければなりません。何かのように

foreach(XElement child in doc.Descendants().Reverse()) 
{ 
    if(!child.HasElements && string.IsNullOrEmpty(child.Value) && !child.HasAttributes) child.Remove(); 
} 

ありがとうございました。

+1

チェックの場合に '&&!child.HasAttributes'を追加したいかもしれません。 – Nyerguds