2011-10-25 21 views
6

Ho un file xml che restituisce un insieme di elementi che sono univoci per un valore di attributo. Questo presenta un problema, come non posso selezionare un nodo con il suo nome:Da Linq a XML che seleziona un nodo si basa su un valore di attributo

<doc> 
    <float name="score">1.2873721</float> 
    <arr name="2_category"> 
     <long>3021</long> 
    </arr> 
    <arr name="ATR_FamilyName"> 
     <str>Some Cookbook </str> 
    </arr> 
    <arr name="ATR_IsFamily"> 
     <str>0</str> 
    </arr> 
    <arr name="ATR_SellPrice"> 
     <str>49.95</str> 
    </arr> 
    <arr name="ATR_VendorId"> 
     <str>ABC</str> 
    </arr> 
    <arr name="ATR_VendorName"> 
     <str>WROX</str> 
    </arr>  
</doc> 

Sto usando LINQ per popolare una classe di "Prodotto". Sono in grado di selezionare gli elementi per posizione, tuttavia questo diventa un problema se il nodo non esiste. C'è un modo per selezionare un nodo in base al valore del suo attributo? Nell'esempio seguente, posso ottenere il nodo arr se l'attributo @name = "ATR_FamilyName"? In XPath sarebbe:

doc/arr[@name = 'ATR_FamilyName']/str 

qui è la mia query LINQ to XML:

var query = from rt in results 
    where (String)rt.Descendants().ElementAt(5).Element("str").Value == "0" 
    select new Product.Product 
      { 
       FamilyName = (String)rt.Descendants().ElementAt(3).Value 
       // doc/arr[@name = 'ATR_FamilyName']/str - select Family Name is arr/@name 'ATR_FamilyName'        
       MorePropertiestoset....        
       }; 

risposta

17

Come la risposta di AS-CII, ma senza utilizzare un'espressione di query (tranne quella esterna) e con il cast per XAttribute e selezionando il valore di elemento str all'interno di un tipo anonimo:

select new Product.Product 
{ 
    FamilyName = rt.Descendants("arr") 
        .Where(x => (string) x.Attribute("name") == "ATR_FamilyName") 
        .Select(x => (string) x.Element("str")) 
        .FirstOrDefault(), 
    MorePropertiesToSet....        
}; 

noti che l'utilizzo di un getto per il risultato della chiamata a Attribute("name") significa che se ci sono elementi che non fare avere l'attributo, il cast si tradurrà in riferimento null (che isn 'uguale alla stringa letterale). Se si utilizza la proprietà Value, si otterrà un'eccezione. A volte un'eccezione può essere migliore, se ciò indica che i dati sono fondamentalmente rotti e vuoi scoprirlo piuttosto che non corrispondere al valore.

(Lo stesso vale per il cast del XElement-string.)

+0

Grazie Jon - È inchiodato. Ho appropriato la risposta veloce da parte di tutti – PhillyNJ

+0

Thx per la spiegazione sul casting, Jon. Stavo correndo in situazioni in cui non tutti i nodi avevano l'attributo e lanciava un'eccezione perché ho usato .Value invece del cast; questo lo fidex. –

5

Con LINQ si può facilmente selezionare solo i nodi che hanno un attributo specificato, in questo modo:

var query = from node in results.Descendants("arr") // I believe you could use results.Elements("arr") here 
      where node.Attribute("name").Value == "ATR_FamilyName" 
      select new Product 
      { 
       FamilyName = node.Element("str").Value 
      }; 
2

Usa XElement come questo:

from rt in results.descendants("<node name>") 
where rt.attribute(attribute name).value == "specified value" 
select rt 

Ci scusiamo per la digitazione da telefono cellulare

Problemi correlati