【问题标题】:How do I read values from an XML document to build a ComboBox?如何从 XML 文档中读取值来构建 ComboBox?
【发布时间】:2013-05-24 08:46:00
【问题描述】:

我正在尝试阅读我想为我妈妈制作的 文件。所以基本上这就是我想做的:

  1. ComboBox 将显示 XML 中的所有蔬菜名称。
  2. 选择蔬菜后,第二个ComboBox 将在 XML 中显示食谱名称,可以使用在第一个 ComboBox 中选择的蔬菜进行烹饪。
  3. 最后,使用 OK Button,所选配方将读取指向该配方的文件路径。

我写的 XML

<Vegetables>
    <vegetable name="Carrot">
        <recipe name="ABCrecipe">
            <FilePath>C:\\</FilePath>
        </recipe>
        <recipe name="DEFrecipe">
            <FilePath>D:\\</FilePath>
        </recipe>   
    </vegetable>
    <vegetable name="Potato">
        <recipe name="CBArecipe">
            <FilePath>E:\\</FilePath>
        </recipe>
            <recipe name"FEDrecipe">
            <FilePath>F:\\</FilePath>
        </recipe>
    </vegetable>
</Vegetables>

C#代码

private void Form1_Load(object sender, EventArgs e)
{
    XmlDocument xDoc = new XmlDocument();
    xDoc.Load("Recipe_List.xml");
    XmlNodeList vegetables = xDoc.GetElementsByTagName("Vegetable");
    for (int i = 0; i < vegetables.Count; i++)
    {
        comboBox1.Items.Add(vegetables[i].Attributes["name"].InnerText);
    }
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    //I'm lost at this place.
}

第一个ComboBox 现在可以显示蔬菜名称,但是如何让第二个ComboBox 阅读食谱?

【问题讨论】:

  • 您应该将“potato”和“carrot”值放入它们自己的节点中。您只需要改进您的选择过程,您正在抓取一个高级节点并打印出其中的所有内容,而不是使用更具体的选择器来查找特定项目。
  • 作为添加新节点的替代方法,您可以将蔬菜名称作为蔬菜节点的属性放入。

标签: xml c# xml winforms


【解决方案1】:

你的 xml 应该被重组,因为你在将配方名称和文件路径节点作为配方节点的值时混合数据

这是一个更好的方法:

<Vegetables>
    <vegetable name="Carrot">
        <recipe name="ABCrecipe">
            <FilePath>C:\\</FilePath>
        </recipe>
        <recipe name="DEFrecipe">
            <FilePath>D:\\</FilePath>
        </recipe>   
    </vegetable>
    <vegetable name="Potato">
        <recipe name="CBArecipe">
            <FilePath>E:\\</FilePath>
        </recipe>
        <recipe name="FEDrecipe">
            <FilePath>F:\\</FilePath>
        </recipe>
    </vegetable>
</Vegetables>

所以要显示配方,您需要提取配方节点的属性。 此处解释了如何执行此操作:How to read attribute value from XmlNode in C#?

编辑:更正了由于 cmets 导致的 xml 结构。谢谢

【讨论】:

  • 需要同样的重组来将蔬菜名称提取到属性/节点中。一个 xml 元素可以包含文本 或 一个或多个子元素;它不能同时包含两者。
  • @Phylogenesis 您可以拥有同时包含文本和其他元素的元素。这称为混合内容。 XHTML 就是一个很好的例子,其中&lt;p&gt;Hello &lt;span class="name"/&gt;Mr X&lt;/span&gt;&lt;/p&gt; 是有效的 XML。
  • @Tragedian 你是对的 - 但在这种情况下,混合内容会造成糟糕的结构。
  • 混合内容完全有效,正如@Tragedian 所说,但我确实会提取蔬菜名称。很抱歉漏掉了。我会改正的
【解决方案2】:

如果您希望能够从文档中获取蔬菜的名称,最简单的做法是将其定义为自己的单独数据片段。您所做的事情并没有无效,但这使得获取所需数据变得相当困难。

如果可以的话,把结构改成这样,让你的生活更轻松:

<vegetables>
    <vegetable>
        <name>Carrot</name>
        <recipe>
             <name>ABCrecipe</name>
             <path>C:\\</path>
        </recipe>
        <recipe>
            <name>DEFrecipe</name>
            <path>D:\\</path>
        </recipe>   
    </vegetable>
</vegetables>

假设您使用的是 .NET 3.5 或更高版本,您将可以访问 LINQ-to-XML API。这些提供了一种从 XML 文档中读取值的简化方法,应该可以更轻松地解决这个问题。

您使用以下方法创建文档:

var document = XDocument.Load("Recipe_List.xml");

然后你可以编写一个查询来获取蔬菜元素,如下所示:

var vegetables = document
    .Element(XName.Get("vegetables"))
    .Elements(XName.Get("vegetable"));

一旦你有了这些元素,你就可以得到它们的名字,像这样:

var vegNames = vegetables.Select(ele => ele.Element(XName.Get("name")).Value);

然后,您可以非常轻松地将这些信息插入您的组合框:

foreach (string name in vegNames)
{
    comboBox1.Items.Add(name);
}

【讨论】:

    【解决方案3】:

    我假设您在 .Net 4.0 框架中使用 C#

    你可以像这样格式化你的xml:

    <Vegetables>
        <vegetable>
            <name>Carrot</name>
            <recipe>
                <name>ABCrecipe</name>
                <FilePath>C:\\</FilePath>
            </recipe>
            <recipe>
                <name>DEFrecipe</name>
                <FilePath>D:\\</FilePath>
            </recipe>   
        </vegetable>
        <vegetable>
            <name>Potato</name>
            <recipe>
                <name>CBArecipe</name>
                <FilePath>E:\\</FilePath>
            </recipe>
            <recipe>
                <name>FEDrecipe</name>
                <FilePath>F:\\</FilePath>
            </recipe>
        </vegetable>
    </Vegetables>
    

    然后只需使用此查询来选择这些项目:

    var vegiesList = (from veg in xDoc.Descendants("vegetable")
                      select new Vegetable()
                      {
                           Name = veg.Element("name").Value,
                           Recipes = (from re in veg.Elements("recipe")
                                      select new Recipe(re.Element("name").Value, re.Element("FilePath").Value)).ToList()
                      })
                      .ToList();
    

    那么对于你的类结构:

    class Vegetable
    {
        public string Name { get; set; }
        public List<Recipe> Recipes { get; set; }
    }
    
    class Recipe
    {
        public Recipe(string name, string path)
        {
           Name = name;     Path = path;
        }
        public string Name { get; set; }
        public string Path { get; set; } 
    }
    
    vegiesList.ForEach(veg => comboBox1.Items.Add(veg.Name));
    //You can select its property here depending on what property you want to add on your `ComboBox`
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-18
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-09
      相关资源
      最近更新 更多