简体   繁体   中英

Listing atributes from sub-elements

I'm new to C# but I'm attempting to load data from a xml file that's like this...

<?xml version="1.0" encoding="utf-8" ?> 
<adventures>
  <adventure_path Name ="Adventure Path 1">
    <adventure Name ="Adventure 1">
      <senario Name ="Senario 1">
        <location Name="Location 1" Players="1"/>
      </senario>

    <adventure Name ="Adventure 2">
      <senario Name ="Senario 2">
        <location Name="Location 2" Players="1"/>
      </senario>
    </adventure>
  </adventure_path>

  <adventure_path Name ="Adventure Path 2">
    <adventure Name ="Adventure 3">
      <senario Name ="Senario 3">
        <location Name="Location 3" Players="1"/>
      </senario>

    <adventure Name ="Adventure 4">
      <senario Name ="Senario 4">
        <location Name="Location 4" Players="1"/>
      </senario>
    </adventure>
  </adventure_path>
</adventures>

What I'm trying to do with this is load the name attributes to an itemlistbox of the adventure element (the "adventure 1", "adventure 2", etc.) within the selected adventure_path element in an itemlistbox. I got the selection part working and the loading to the list working. What's not working is loading all the adventures...

Basically what happens is ListBox1 loads the adventure paths all fine and dandy, I select one of the said adventure paths, and ListBox2 load the first adventure... and that's it. It wont load adventure 2, 3, or 4. So here's the code that should load all the adventures-

private void lst_Adventure_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    string selectedItem = lst_Adventure.SelectedItem.ToString();

    lst_Adventures.Items.Clear();

    XDocument doc = new XDocument();
    bool gotStatsXml = false;
    try
    {

        doc = XDocument.Load("D:\\WpfApplication1\\WpfApplication1\\Adventures.xml");
        gotStatsXml = true;
    }
    catch
    {
        gotStatsXml = false;

    }

    XElement selectedElement = doc.Descendants().Where(x => (string)x.Attribute("Name") == selectedItem).FirstOrDefault();

    foreach (var docs in selectedElement.Descendants("adventure")) ;
    {
        XElement elements = selectedElement.Element("adventure");

        string AdventuresPathName = elements.Attribute("Name").Value;

        lst_Adventures.Items.Add(AdventuresPathName);
    }
}

you are missing the value property x.Attribute("Name"). Value

 XElement selectedElement = doc.Descendants().Where(x => x.Attribute("Name").Value == selectedItem).FirstOrDefault();

You have two problems:

  1. You don't check if selectedElement is null before accessing its descendants
  2. You are adding first adventure element of selectedElement on each loop (take a look - instead of using docs element (which is adventure) you are loading Element("adventure") from selectedElement )

Instead you should use

if (selectedElement != null)
{
   foreach (var docs in selectedElement.Elements("adventure")) 
   {
       string AdventuresPathName = (string)docs.Attribute("Name");
       lst_Adventures.Items.Add(AdventuresPathName);
   }
}

Or, simply get all adventure names:

List<string> adventureNames =
         doc.Root.Elements("adventure_path")
            .Where(ap => (string)ap.Attribute("Name") == selectedItem)
            .Elements("adventure")
            .Select(a => (string)a.Attribute("Name"))
            .ToList();

Or with XPath

var xpath = String.Format("//adventure_path[@Name='{0}']/adventure", selectedItem);
List<string> adventureNames = doc.XPathSelectElements(xpath)
                                 .Select(a => (string)a.Attribute("Name"))
                                 .ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM