我有一个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'下的所有数据,即SubFun1,SubFun2等。
请注意:我不想在C#应用程序中对任何XML标记进行硬编码。
提前致谢。
答案 0 :(得分:0)
如果您不想硬编码标签的名称,我们应该对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();
}