C# 基于XML属性从直接父级自动加载子项

C# 基于XML属性从直接父级自动加载子项,c#,xml,linq,C#,Xml,Linq,我有一个XML文件,看起来像 <Modules> <Module Title='Mod1' Attr2='' Attr3=''> <Functions> <Function Title='Fun1' Attr2=''> <SubFunctions> <SubFunction Title='SubFun1' Att

我有一个XML文件,看起来像

<Modules>
    <Module Title='Mod1' Attr2='' Attr3=''>
        <Functions>
            <Function Title='Fun1' Attr2=''>
                <SubFunctions>
                    <SubFunction Title='SubFun1' Attr2='' />
                    <SubFunction Title='SubFun2' Attr2='' />
                </SubFunctions>
            </Function>
            <Function Title='Fun2' Attr2='' />
            <Function Title='Fun3' Attr2='' />
         </Functions>
</Module>
<Module Title='Mod2' Attr2='' Attr3=''>
    <Functions>
    </Functions>
</Module>
<Module Title='Mod3' Attr2='' Attr3=''>
    <Functions>
    </Functions>
</Module>

我一直在尝试在C#中使用LINQ和XML编写一个基于递归的泛型函数,但未能使该函数尽可能通用

我目前拥有的是我的函数加载所有与数据相关的“模块”,因此根据上述XML数据,计数为3。当用户选择第一个“模块”即“Mod1”时,应加载该“Mod1”下的所有相应数据,即Fun1、Fun2、Fun3。同样,如果用户选择Fun1,则应加载此“Fun1”下的所有数据,即子PUN1、子PUN2等

请注意:我不想在我的C#应用程序中硬编码任何XML标记。


提前感谢。

如果您不想硬编码标记的名称,我们应该假设XML结构。根据您的示例,似乎有两种元素:

  • “容器”元素。模块、功能、子功能。其中可以包含零个或多个“数据”元素
  • “数据”元素。模块、功能、子功能。它可以包含零个或一个“Container”元素,并且始终具有用于选择的“Title”属性
  • 请注意,“Title”属性名称是硬编码的,除非使用自定义名称。你的决定

    代码可以是泛型的,因为我们不关心元素的名称,只关心它们的关系。 如您所述,用户逐渐选择所选元素,根据此要求,我将提出以下解决方案:

    MyXmlReader—提供对XML文件的访问权限的类 DataElement—包含有关queries元素(包括其子元素)的数据的类

     class MyXmlReader
    {
        // refference to current list element
        XmlNode currentListElement = null;
        XmlDocument xml;
    
        // load file, initialize  and return data that contains info ablut
        // the first level elements names
        public DataElement Load(string path)
        {
            xml = new XmlDocument();
            xml.Load(path);
            Init();
            DataElement result = new DataElement();
            result.SubTitles = GetChildTitles();
            return result;
        }
    
        // Initialize the reader to read from the beggining
        public void Init()
        {
            currentListElement = xml.DocumentElement;
        }
    
        // Get next child
        public DataElement GetNext(string title)
        {
            string tempTitle;
    
            foreach (XmlNode child in currentListElement.ChildNodes)
            {
                DataElement result = null;
    
                if (child.Attributes["Title"].Value == title)
                {
                    // create object that contains the data about the child nodes Titles
                    result = new DataElement();
                    result.Title = child.Attributes["Title"].Value;
    
                    if (child.FirstChild != null) // means no child nodes
                    {
                        currentListElement = child.FirstChild;
    
                        // add subelements subtitles
                        result.SubTitles.AddRange(GetChildTitles());
                    }
                    return result;
    
    
                }
            }
            return null;
        }
    
    
        public List<string> GetChildTitles()
        {
            List<string> result = new List<string>();
    
            foreach (XmlNode child in currentListElement.ChildNodes)
            {
                result.Add(child.Attributes["Title"].Value);
            }
            return result;
        }
    
    
    }
    
    
    // add any other data to this class
    // that you need about the element you return
    class DataElement
    {
        public List<string> SubTitles = new List<string>();
        public string Title { get; set; }
    }
    

    似乎您正在查找
    元素()
    …@It'sNotALie。有什么样的代码可以分享吗?
    // test
        static void Main(string[] args)
        {
            MyXmlReader reader = new MyXmlReader();
            DataElement data = reader.Load("Data.xml");
    
            // Generic test:
    
            // get first module
            data = reader.GetNext(data.SubTitles[0]);
            // get first function 
            data = reader.GetNext(data.SubTitles[0]);
            // get first sub-function 
            data = reader.GetNext(data.SubTitles[0]);         
    
    
            // you can write test with hardcode nodes names like this:
            reader.Init();
            // get first module
            data = reader.GetNext("Mod1");
            // get first function 
            data = reader.GetNext("Fun1");
            // get first sub-function 
            data = reader.GetNext("SubFun1");  
    
            Console.Read();
        }