2010-10-21 6 views
2

Voici l'extrait de code:LINQ to XML simple, attribut get de déclaration de noeud

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml")); 
string result = ""; 
var childType = from t in themes.Descendants() 
    where t.Attribute("name").Value.Equals(theme) 
    select new { value = t.Attribute("type").Value }; 

foreach (var t in childType) { 
    result += t.value; 
} 
return result; 

et voici le XML:

<?xml version="1.0" encoding="utf-8" ?> 
<themes> 
    <theme name="Agile"> 
    <root type="Project"> 
     <node type="Iteration" > 
     <node type="Story"> 
      <node type="Task"/> 
     </node> 
     </node> 
    </root> 
    </theme> 
    <theme name="Release" > 
    <root type="Project"> 
     <node type="Release"> 
     <node type="Task" /> 
     <node type="Defect" /> 
     </node> 
    </root> 
    </theme> 
</themes> 

Qu'est-ce que je fais mal? Je continue d'obtenir une exception "objet non défini sur une instance d'un objet". Ce que j'essaye de retourner est le type du noeud choisi basé sur le type d'un noeud parent, c.-à-d., Si le thème est "Agile" et le noeud parent est "Project" alors la valeur de retour devrait être "Itération". C'est le résultat final mais je ne suis jamais allé aussi loin parce que je suis resté coincé avec ce que vous voyez ci-dessus.

+0

J'ai édité ma réponse pour être en phase avec vos informations ajoutées. –

Répondre

5

Je pense que vous voulez quelque chose de plus proche de celle-ci:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml")); 
string result = ""; 
var childType = from t in themes.Descendants("theme") 
       where t.Attribute("name").Value.Equals(theme) 
       select new { value = t.Descendants().Attribute("type").Value }; 

foreach (var t in childType) { 
    result += t.value; 
} 
return result; 

EDIT: Sur la base de vos informations supplémentaires, peut-être cela est encore plus proche:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml")); 
string result = ""; 
var childType = from t in themes.Descendants("theme") 
       where t.Attribute("name").Value.Equals(theme) 
       where t.Element("node").Attribute("type").Value == parent 
       select new { value = t.Descendants().Attribute("type").Value }; 

foreach (var t in childType) { 
    result += t.value; 
} 
return result; 

EDIT 2: C'est travailler pour moi:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml")); 
string result = ""; 
var theme = "Agile"; 
var parent = "Project"; 
var childType = from t in themes.Descendants("theme") 
      where t.Attribute("name").Value.Equals(theme) 
      where t.Element("root").Attribute("type").Value == parent 
      from children in t.Element("root").Descendants() 
      select new { value = children.Attribute("type").Value }; 
foreach (var t in childType) { 
    result += t.value; 
} 
return result; 

EDIT 3: Voici le programme de travail complet, il suffit de le lancer dans une classe dans une application console.

static void Main(string[] args) 
     { 
      var xml = "<themes><theme name='Agile'><root type='Project'><node type='Iteration' ><node type='Story'><node type='Task'/></node></node></root></theme><theme name='Release' ><root type='Project'><node type='Release'><node type='Task' /><node type='Defect' /></node></root></theme></themes>"; 
      XDocument themes = XDocument.Parse(xml); 
      string result = ""; 
      var theme = "Agile"; 
      var parent = "Project"; 
      var childType = from t in themes.Descendants("theme") 
          where t.Attribute("name").Value.Equals(theme) 
          where t.Element("root").Attribute("type").Value == parent 
          from children in t.Element("root").Descendants() 
          select new { value = children.Attribute("type").Value }; 

      foreach (var t in childType) 
      { 
       Console.WriteLine(t.value); 
      } 

      Console.Read(); 

     } 
+0

Il n'existe pas de version de méthode de FirstNode, c'est une propriété qui n'a pas de méthode d'attribut. – Morgeh

+0

J'ai dû ajouter .First() à t.Descendants() dans l'instruction select pour l'obtenir pour compiler, mais je reçois toujours l'objet non défini sur une instance d'un objet exceptions – Morgeh

+0

Essayez ma deuxième édition pour voir si elle est ce que tu veux. –

0

Je ne suis pas autorisé à répondre à votre question. Voici ma solution (comme je l'ai compris)

var childType = themes.Descendants("theme") 
          .Where(X => X.Attribute("name").Value == "Agile") 
          .Where(X => X.Descendants("root").Attributes("type").First().Value == "Project") 
          .Select(X => X.Descendants("node").Attributes("type").First().Value); 
0

Il ya deux erreurs dans votre requête.

La première est:

from t in themes.Descendants() 

Cela vous donnera tous les éléments themes.
Si vous voulez que les theme éléments, vous devez le spécifier, en filtrant comme:

from t in themes.Descendants("theme") 

La deuxième erreur sera par conséquent

select new { value = t.Attribute("type").Value } 

parce t sera un élément theme, sans attribut " type".
Je ne peux pas aider sur celui-ci parce que ce n'est pas clair ce que le résultat final doit être.

Edit: Selon les informations ajoutées, cela devrait faire l'affaire:

 var childType = 
      from t in doc.Descendants("theme") 
      where t.Attribute("name").Value.Equals(theme) 
      select t.Element("root") 
        .Element("node") 
        .Attribute("type").Value; 

Cependant, cela est censé récupérer plusieurs types de nœuds avec le même nom theme. Si le type sera toujours le même, vous devriez appeler .SingleOrDefault().

+0

modifié pour fournir plus d'informations – Morgeh

1

Ok, voici ce que j'ai fait à la fin, ce n'est pas très joli mais ça marche. Son basé sur la réponse par Pramodh avec quelques tweeks. Maintenant, si je passe dans le thème "Agile" et parent "Iteration", il retourne l'histoire.

Comme je l'ai dit pas très joli mais ça marche.

Merci à tous ceux qui ont répondu.