Xml如下。
<System>
<ID></ID>
<Name></Name>
<Monitor>
<ID></ID>
<Type></Type>
<Alert>
<ID></ID>
<Status></Status>
</Alert>
<Alert>
<ID></ID>
<Status></Status>
</Alert>
</Monitor>
</System>
<System>
<ID></ID>
<Name></Name>
<Monitor>
<ID></ID>
<Type></Type>
<Alert>
<ID></ID>
<Status></Status>
</Alert>
</Monitor>
</System>
我想像这样遍历它
XElement xmlDoc = XElement.Load(@"xml");
var q = from el in xmlDoc.Elements("System") select el;
foreach(el in q) {
Console.WriteLine(el.ID);
Console.WriteLine(el.Name);
if (el.Monitor) {
foreach (mon in el.Monitor) {
Console.WriteLine(el.ID);
Console.WriteLine(el.Type);
if (mon.Alert) {
foreach (alert in mon.Alert) {
Console.WriteLine(alert.ID);
Console.WriteLine(alert.Status);
}
}
}
}
}
目前我循环遍历了几次并使用if检查字段然后为变量赋值。然后我必须再次循环它。有没有更简单的方法,我应该使用简单的LINQ或LINQ-TO-XML吗?
答案 0 :(得分:0)
如果你想像你那样遍历它:
var xml = @"
<Root>
<System>
<ID>1</ID>
<Name>One</Name>
<Monitor>
<ID>2</ID>
<Type>Two</Type>
<Alert>
<ID>3</ID>
<Status>Three</Status>
</Alert>
<Alert>
<ID>4</ID>
<Status>Four</Status>
</Alert>
</Monitor>
</System>
<System>
<ID>5</ID>
<Name>Five</Name>
<Monitor>
<ID>6</ID>
<Type>Six</Type>
<Alert>
<ID>7</ID>
<Status>Seven</Status>
</Alert>
</Monitor>
</System>
</Root>
";
XElement xmlDoc = XElement.Parse(xml);
var q = xmlDoc.Elements("System");
foreach(var el in q) {
Console.WriteLine(el.Element("ID").Value);
Console.WriteLine(el.Element("Name").Value);
foreach(var mon in el.Elements("Monitor")) {
Console.WriteLine(mon.Element("ID").Value);
Console.WriteLine(mon.Element("Type").Value);
foreach(var alert in mon.Elements("Alert")) {
Console.WriteLine(alert.Element("ID").Value);
Console.WriteLine(alert.Element("Status").Value);
}
}
}
答案 1 :(得分:0)
好的,试试这段代码(见下面的代码解释)
class Program {
static void Main(string[] args) {
var xml = @"
<Root>
<System>
<ID>1</ID>
<Name>one</Name>
<Monitor>
<ID>3</ID>
<Type>t3</Type>
<Alert>
<ID>5</ID>
<Status>a5</Status>
</Alert>
<Alert>
<ID>6</ID>
<Status>a6</Status>
</Alert>
</Monitor>
</System>
<System>
<ID>2</ID>
<Name>two</Name>
<Monitor>
<ID>4</ID>
<Type>t4</Type>
<Alert>
<ID>7</ID>
<Status>a7</Status>
</Alert>
</Monitor>
</System>
</Root>
";
XElement xmlDoc = XElement.Parse(xml);
// set q to an enumeration of XElements
// where the elements xname is "System"
// the query actually executes the first time q is used
var q = xmlDoc.Elements("System");
foreach (var ele in q) {
// Get the value of the Element with the xname of "ID"
Console.WriteLine(ele.Element("ID").Value);
Console.WriteLine(ele.Element("Name").Value);
// if ele.Elements("Monitor") returns nothing
// then the foreach will be skipped (null-execution)
foreach (var mon in ele.Elements("Monitor")) {
Console.WriteLine(mon.Element("ID").Value);
Console.WriteLine(mon.Element("Type").Value);
foreach (var alert in mon.Elements("Alert")) {
Console.WriteLine(alert.Element("ID").Value);
Console.WriteLine(alert.Element("Status").Value);
}
}
}
}
}
此代码将在XML文档中移动一次。在C#中,LINQ包含语言元素(如'select'和'from')和库元素(.NET框架方法,如XDocument.Elements);混合两者是可以的,但只应该了解语句背后发生的事情。在这种情况下,您要求XDocument返回XName为“System”的所有子元素。在上面的代码中,'q'没有接收到所有元素,它接收一个可以迭代的枚举。 q的分配是一个非常低成本的操作,因为XDocument内容在第一个foreach之前不是横向的,然后一次只检查一个元素。搜索“C#yield return”以查看其实现方式。
如果您只对“警报”元素感兴趣,可以执行以下操作:
var alerts = xmlDoc.Descendants("Alert")
这将返回XName为“Alert”的所有元素的枚举(无论它们在XML文档的层次结构中的何处)。如果您想确保层次结构,可以使用“where”,例如:
var alerts = xmlDoc.Descendants("Alert")
.Where(ele => (ele.Parent != null) && (ele.Parent.Name == "Monitor"))
.Where(ele => (ele.Parent.Parent != null) && (ele.Parent.Parent.Name == "System"));
foreach (var alert in alerts) {
Console.WriteLine(alert.Element("ID").Value);
Console.WriteLine(alert.Element("Status").Value);
}
如果需要多次迭代相同的节点,则应考虑将枚举转换为列表或数组,这样可以节省时间,但会增加内存使用量。 IEnumerable的&LT;&GT;为此目的具有扩展方法“。ToArray()”和“.ToList()”。
答案 2 :(得分:0)
C#是一种OOP语言,我认为你应该利用它:
示例:
public class MySystem
{
public int Id { get; private set; }
public string Name { get; private set; }
public MyMonitor[] Monitors { get; private set; }
public MySystem(XElement x)
{
Id = (int)x.Element("ID");
Name = x.Element("Name").Value;
// a little confusing from your code if there can be more than one Monitor
Monitors = x.Elements("Monitor").Select(m => new MyMonitor(m)).ToArray();
}
}
为您的Monitor类和Alert类执行类似的操作。我把它命名为MySystem,因为名为System的类是一团糟。
您可以创建系统数组,例如我使用以下方法创建了Monitor的数组:
XElement xmlDoc = XElement.Load(@"xml");
MySystem[] systems = xmlDoc.Elements("System")
.Select(s => new MySystem(s))
.ToArray();
现在,您已将所有值都放在易于使用的类中。