2013-01-24 76 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. 僅生成包含值的元素的新節點。
  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」?另外請注意,你在這裏沒有任何用途使用查詢表達式 - 例如,而不是在節點select el中編寫'el,你可以稍後使用'node' ... –

+0

@JonSkeet - 我只是指空白的元素/空。是不是像NULL一樣? – jared

+0

不是真的 - XML中沒有「NULL」這樣的概念。目前還不清楚你期望返回哪種結構。如果您可以使用給定輸入文件的所需輸出來編輯您的問題,這將非常有用。 –

回答

30

單個單線程可以完成這項工作,無需遍歷所有元素。這裏有雲:

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(); 
     } 
    } 
} 

而且它也可以的情況下,被測試here

+1

+1 - 贏得一個內線! – jared

+1

您需要注意擁有屬性的自閉式元素,它很可能不是最終用戶IE的願望: aolszowka

+0

+1 @aolzowka。 magento_api在最離奇的地方使用屬性。我採取了這種方法來解決相關問題。 http://stackoverflow.com/a/31708077/969367 – Vic

1

在VB中我需要重新找到它:

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

這一行不會拋出空的父標記,它們是空的子標記。它只會移除他們的孩子,這可能會或可能不適合您的情況。這是一個非常簡單的改變,你只需要首先從最低層開始移除。類似於

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

感謝Nyerguds的屬性建議。

+1

雖然您可能希望在檢查時添加'&&!child.HasAttributes'。 – Nyerguds