2009-11-19 3 views
2

Je veux créer une liste à partir d'un fichier xml où seules les valeurs entre deux lettres sont affichées. Par exemple, affichez uniquement les enregistrements correspondants dans lesquels le premier caractère du titre est compris entre «A» et «E».Linq sélectionner une plage entre les lettres, par ex. a-e

Ma première approche de base est

where item.Element("title").Value >= "A" && item.Element("title").Value < "E" 

Bien sûr, cela ne fonctionne pas comme ces opérateurs ne peuvent pas être appliqués aux chaînes. J'ai essayé d'utiliser string.compare mais sans chance.

Quelqu'un peut-il me donner un exemple sur la façon d'obtenir cette requête?

acclamations, Terry

Mise à jour: Voici le code pour lire le xml.

var simpleListSource = (from item in doc.Descendants("item") 
    where item.Element("title").Value[0] >= 'A' && item.Element("title").Value[0] < 'E' 
    orderby item.Element("title").Value 
     select new 
      { 
      title = item.Element("title").Value, 
      description = item.Element("description").Value, 
      image = item.Element("image").Value, 
      type = item.Element("type").Value, 
      imagelink = item.Element("imagelink").Value 

      }).ToList(); 

    rptGetItems.DataSource = simpleListSource; 
    rptGetItems.DataBind(); 

Et le xml ...

<item> 
     <title>A test</title> 
     <titlelong>A</titlelong> 
     <type>test</type> 
     <description> 
     Some description 

     </description> 
     <image>includes/images/test.jpg</image> 
     <imagelink>http://somesite.com</imagelink> 

    </item> 
    <item> 
     <title>E test2</title> 
     <titlelong>E</titlelong> 
     <type>test</type> 
     <description> 
     Another sample 

     </description> 
     <image>includes/images/test.jpg</image> 
     <imagelink>http://somesite.com</imagelink> 

    </item> 

Répondre

4

Utilisez les caractères et les comparer au premier caractère dans le titre:

where item.Element("title").Value[0] >= 'A' 
     && item.Element("title").Value[0] < 'E' 

Vous pourriez vouloir tester pour les titres vides ...

bool TitleInRange(string title) 
    { 
     if (title == null || title.Trim() == string.Empty) 
      return false; 

     return (title[0] >= 'A' && title[0] <= 'E') 
      || (title[0] >= 'a' && title[0] <= 'e'); 
    } 

    ... 
    where TitleInRange(item.Element("title").Value) 

(mise à jour)

Votre code fonctionne comme prévu. Changez simplement le < E en <= E. Essayez d'imprimer les titres sur la console:

 foreach (var item in simpleListSource) 
     { 
      Console.WriteLine("{0}", item.title); 
     } 

Votre problème doit être lié à la liaison de données.

+0

Salut Bruno, a essayé de vos deux approches, il n » ai pas t travail. Aucun résultat n'est affiché J'ai essayé de changer les entrées dans le xml à un seul caractère, même résultat. Des indices? –

+0

@Terry, le problème peut ne pas être lié à cela. Pouvez-vous nous montrer plus de code? Juste un simple extrait de ce que vous faites. –

+0

Salut Bruno, je l'ai mis à jour avec la source ... merci ... –

1
where Enumerable.Range('A','E').Select(x => (char) x).Contains(title[0]) 

(non testé)

0

Essayez:

where item.Element("title").Value[0] >= 'A' && item.Element("title").Value[0] < 'E' 

Maintenant, vous comparez char carboniser, qui peut utiliser des opérateurs de comparaison normale.

EDIT: voici un exemple de programme:

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

namespace TestIdeas 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      XElement i1 = XElement.Parse(@" <item> 
               <title>A test</title> 
               <titlelong>A</titlelong> 
               <type>test</type> 
               <description> 
                Some description 
               </description> 
               <image>includes/images/test.jpg</image> 
               <imagelink>http://somesite.com</imagelink> 

              </item>"); 

      XElement i2 = XElement.Parse(@" <item> 
               <title>E test2</title> 
               <titlelong>E</titlelong> 
               <type>test</type> 
               <description> 
                Another sample 
               </description> 
               <image>includes/images/test.jpg</image> 
               <imagelink>http://somesite.com</imagelink> 
              </item>"); 

      XElement root = new XElement("root"); 
      root.Add(new[] { i1, i2 }); 

      var ts = from t in root.Elements("item").Elements("title") 
         where t.Value[0] >= 'A' && t.Value[0] <= 'E' 
         select t; 

      foreach (XElement t in ts) 
      { 
       Console.WriteLine(t.Value); 
      } 

      Console.ReadLine(); 
     } 
    } 
} 

donne la sortie

A Test 
E Test2 
+0

Salut Matt, essayé votre approche, malheureusement, cela n'a pas fonctionné. Aucun résultat n'est affiché Des indices? –

+0

Bonjour Terry, J'ai testé avec le XML que vous avez fourni et j'ai obtenu A mais pas E (comme prévu). Si vous voulez inclure E, utilisez <= 'E' –

+0

Salut Matt, merci pour votre aide, j'ai trouvé l'erreur, le titre emptpty xml noeud ... ouais je sais, stupide, stupide ... –

2
where "ABCDE".Contains(item.Element("title").Value[0]) 
0

Qu'en est-regex

Regex searchTerm = new Regex("^[a-eA-E]"); 

var simpleListSource = (from item in doc.Descendants("item") 
where searchTerm.Matches(item.Element("title").Value).Count > 0 
orderby item.Element("title").Value 
    select new 
     { 
     title = item.Element("title").Value, 
     description = item.Element("description").Value, 
     image = item.Element("image").Value, 
     type = item.Element("type").Value, 
     imagelink = item.Element("imagelink").Value 

     }).ToList(); 

rptGetItems.DataSource = simpleListSource; 
rptGetItems.DataBind(); 

pas testé, mais devrait être proche (la regex peut avoir besoin d'un peu de travail)

+0

juste remarqué le vôtre est tout en majuscules, donc l'expression rationnelle peut-être besoin d'être^[A-E] – Pharabus

0

Pour que je pense que je voudrais peut-être faire une méthode comme ceci:

public static bool IsInRange<T>(T subject, T first, T last) 
{ 
    return IsInRange(subject, first, last, Comparer<T>.Default); 
} 

public static bool IsInRange<T>(T subject, T first, T last, IComparer<T> comparer) 
{ 
    return comparer.Compare(subject, first) >= 0 && comparer.Compare(subject, last) <= 0; 
} 

ou quelque chose de similaire.Non testé, mais je pense que cela devrait fonctionner: P

Mise à jour: Pour l'utiliser dans votre exemple, vous pouvez faire quelque chose comme ceci:

var items = doc.Descendants("item") 
     .Where(x => IsInRange(x.Element("title").Value[0], "A", "E") 
     .OrderBy(x => x.Element("title").Value 
     .Select(x => new 
      { 
       title = x.Element("title").Value, 
       description = x.Element("description").Value, 
       image = x.Element("image").Value, 
       type = x.Element("type").Value, 
       imagelink = x.Element("imagelink").Value 
      }) 
     .ToList(); 
Questions connexes