如果您不想硬编码标签的名称,我们应该对 XML 结构做一个假设。根据您的示例,似乎有两种元素:
- “容器”元素。模块、函数、子函数。哪个可以包含零个或多个“数据”元素
- “数据”元素。模块、函数、子函数。它可以包含零个或一个“容器”元素,并且始终具有用于选择的“标题”属性。
请注意,除非您使用自定义名称,否则“标题”属性名称是硬编码的。你的决定。
代码可以是通用的,因为我们不关心元素的名称,而只关心它们的关系。如您所述,用户逐渐选择所选元素,按照此要求,我将提出以下解决方案:
MyXmlReader - 提供对 XML 文件的访问的类 DataElement - 包含有关查询元素的数据的类,包括其子元素
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; }
}
测试:
// 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();
}