我刚刚遇到一个问题,我的代码可以很好地解析 xml,但是一旦我添加了第二个节点,它就开始加载不正确的数据。实际代码跨越许多类和项目,但对于示例,我已经将导致问题的基础知识放在一起
当代码运行时,我希望输出是第二个任务节点的内容,但输出的是第一个节点的内容。尽管当您检查设置对象时它的内部 xml 是第二个 Task 节点的,它仍然从第一次出现的 EmailAddresses 节点开始拉取。对 SelectSingleNode("//EmailAddresses")
的调用是问题发生的地方。
我有两种方法解决这个问题
- 从 EmailAddresses XPath 表达式中删除前导斜杠
- 获取Task或Settings节点后调用
Clone()
解决方案 1 在这种情况下有效,但我相信这会导致我项目中的其他代码停止工作。
在我看来,解决方案 2 更像是 hack 而不是真正的解决方案。
我的问题是,我是否确实正确地执行了此操作,并且 .NET(所有版本)中存在错误,或者我只是将 XML 拉错了?
C#代码
var doc = new XmlDocument();
doc.Load(@"D:\temp\Sample.xml");
var tasks = doc.SelectSingleNode("Server/Tasks");
foreach (XmlNode threadNode in tasks.ChildNodes)
{
if (threadNode.Name.ToLower() != "thread")
{
continue;
}
foreach (XmlNode taskNode in threadNode.ChildNodes)
{
if (taskNode.Name.ToLower() != "task" || taskNode.Attributes["name"].Value != "task 1")
{
continue;
}
var settings = taskNode.SelectSingleNode("Settings");
var emails = settings.SelectSingleNode("//EmailAddresses");
Console.WriteLine(emails.InnerText);
}
}
XML
<?xml version="1.0"?>
<Server>
<Tasks>
<Thread>
<Task name="task 2">
<Settings>
<EmailAddresses>task 2 data</EmailAddresses>
</Settings>
</Task>
</Thread>
<Thread>
<Task name="task 1">
<Settings>
<EmailAddresses>task 1 data</EmailAddresses>
</Settings>
</Task>
</Thread>
</Tasks>
</Server>
最佳答案
来自 http://www.w3.org/TR/xpath/#path-abbrev
//
is short for/descendant-or-self::node()/
. For example,//para
is short for/descendant-or-self::node()/child::para
and so will select any para element in the document (even a para element that is a document element will be selected by//para
since the document element node is a child of the root node);
还有:
A location step of
.
is short forself::node()
. This is particularly useful in conjunction with//
. For example, the location path.//para
is short forself::node()/descendant-or-self::node()/child::para
and so will select all para descendant elements of the context node.
代替:
var settings = taskNode.SelectSingleNode("Settings");
var emails = settings.SelectSingleNode("//EmailAddresses");
使用:
var emails = taskNode.SelectSingleNode("Settings/EmailAddresses");
关于c# - 我的 XML 代码或 .NET 中是否存在错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4055016/