2013-01-24 23 views
11

ho un documento XML come questo:Rimuovere vuoti/spazi vuoti elementi in collezione di nodi 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> 

Sto cercando di iterare ogni nodo e procedere come segue:

  1. Buttare via ogni elementi che sono vuoti/vuoti.
  2. Genera nuovo nodo con solo elementi contenenti valori.
  3. Inviare il documento risultante a un altro servizio Web.

La parte che sto cercando è come iterare attraverso ogni nodo e controllare ogni elemento per valori nulli.

Ho testato questo codice fuori a http://rextester.com/runcode, ma non riesco a capirlo:

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++; 
} 

Sulla base del input XML di cui sopra, spero di ottenere il seguente risultato:

<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> 

Non sono sicuro se sto utilizzando i giusti metodi per iterare su nodi ed elementi.

+1

Cosa intendi per "elementi NULL"? Nota anche che stai usando le espressioni di query senza scopo qui - per esempio, invece di scrivere 'da el in node select el' puoi semplicemente usare' node' dopo ... –

+0

@JonSkeet - Intendo solo elementi che sono vuoti /vuoto. Non è lo stesso di NULL? – jared

+0

Non proprio: non esiste un concetto come "NULL" in XML. Inoltre, non è chiaro quale struttura si prevede di restituire. Sarebbe utile se tu potessi modificare la tua domanda con l'output desiderato per il dato file di input. –

risposta

30

Un singolo liner potrebbe fare il lavoro, senza necessità di scorrere su tutti gli elementi. Qui si va:

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

Tester

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

Ed anche potrebbe essere testato here

+1

+1 - One liner per la vittoria! – jared

+1

È necessario prestare attenzione agli elementi di auto-chiusura che hanno attributi, molto probabilmente non è il desiderio dell'utente finale IE: aolszowka

+0

+1 @aolszowka. E il magento_api usa gli attributi nei luoghi più bizzarri.Ho preso questo approccio per un problema correlato. http://stackoverflow.com/a/31708077/969367 – Vic

1

In VB nel caso in cui ho bisogno di trovare di nuovo:

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

Questa riga non genererà tag padre vuoti pieni di tag bambini vuoti. Rimuoverà solo i loro figli, che potrebbero o meno essere appropriati nella tua situazione. È un cambiamento davvero semplice per raggiungere questo è sufficiente iniziare a rimuovere dal livello più basso prima. Qualcosa come

Grazie Nyerguds per il suggerimento di attributo.

+1

Si potrebbe voler aggiungere '&&! Child.HasAttributes' a quello in caso di controllo, però. – Nyerguds

Problemi correlati