【问题标题】:Listing atributes from sub-elements列出子元素的属性
【发布时间】:2013-12-08 10:02:33
【问题描述】:

我是 C# 新手,但我正在尝试从这样的 xml 文件加载数据...

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

我想要做的是将名称属性加载到 itemlistbox 中选定的 Adventure_path 元素内的 Adventure 元素(“adventure 1”、“adventure 2”等)的 itemlistbox。我让选择部分工作并且加载到列表工作。不工作的是加载所有的冒险......

基本上发生的事情是 ListBox1 加载冒险路径都很好而且花花公子,我选择了其中一条冒险路径,而 ListBox2 加载了第一个冒险......就是这样。它不会加载冒险 2、3 或 4。所以这是应该加载所有冒险的代码-

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

【问题讨论】:

  • 附注 - 您的示例 xml 中没有关闭 &lt;/adventure&gt; 标记
  • 啊,对,对不起。我会解决的。
  • 以这种方式使用catch 是个坏主意。您应该只捕获特定的异常。

标签: c# xml


【解决方案1】:

你有两个问题:

  1. 在访问其后代之前,您不会检查 selectedElement 是否为空
  2. 您将在每个循环中添加selectedElement 的第一个冒险元素(看看 - 您正在从selectedElement 加载Element("adventure") 而不是使用docs 元素(这是冒险))

你应该使用

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

或者,简单地获取所有冒险名称:

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

或使用 XPath

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

【讨论】:

  • 抱歉,我不确定这正是我想要的,或者我只是个菜鸟。我不打算制作一个列表本身,而是将每个属性添加到我拥有的列表框中。
  • @GiantDwarf 我更新了我的答案以显示您的问题在哪里
  • @GiantDwarf 因为doc 变量名-我没有注意到您将它用于XDocument。现在修好了。顺便说一句,最好将冒险元素命名为 adventurea
  • @GiantDwarf 确保您使用的代码与我提供的完全相同。看起来你在 foreach 循环中有不同的变量名
  • 找到了错误...现在我觉得很愚蠢...有一个 ;在 foreach 事情之后......搞砸了整个代码......现在效果很好,谢谢
【解决方案2】:

您缺少值属性 x.Attribute("Name").Value

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

【讨论】:

  • 对不起,你这是什么意思?我在 foreach 循环上方的 2 行中有该行。还是你的意思是别的?
  • 试试吧,让我们知道
  • 啊,我看到了区别,但现在我得到了一个 NullReferenceException。有什么想法吗?
  • @JulieShannon 我的反对意见 - 为 XAttribute 定义了一组显式转换运算符。将属性或元素转换为字符串是完全可以的,这比访问 Value 属性要好得多,因为如果找不到节点,那么你会得到 NullReferenceException
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-14
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 2014-07-06
  • 1970-01-01
相关资源
最近更新 更多