c# - 我的 XML 代码或 .NET 中是否存在错误?

标签 c# .net xml xpath

我刚刚遇到一个问题,我的代码可以很好地解析 xml,但是一旦我添加了第二个节点,它就开始加载不正确的数据。实际代码跨越许多类和项目,但对于示例,我已经将导致问题的基础知识放在一起

当代码运行时,我希望输出是第二个任务节点的内容,但输出的是第一个节点的内容。尽管当您检查设置对象时它的内部 xml 是第二个 Task 节点的,它仍然从第一次出现的 EmailAddresses 节点开始拉取。对 SelectSingleNode("//EmailAddresses") 的调用是问题发生的地方。

我有两种方法解决这个问题

  1. 从 EmailAddresses XPath 表达式中删除前导斜杠
  2. 获取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 for self::node(). This is particularly useful in conjunction with //. For example, the location path .//para is short for

self::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/

相关文章:

c# - 如何在 WPF 中为我的弹出窗口应用图标?

c# - 我应该绑定(bind)到 ICollectionView 还是 ObservableCollection

xml - 为什么 eclipse 项目源目录中的 xml 文件没有复制到 target/classes 目录?

c# - 如何在调用 Main() 方法后打印任何值?

c# - 在代码优先 Entity Framework 中将外键包含在复合主键中

c# - 如何保持进程在远程 Windows 服务器上运行

c# - 自动完成:用 json 数据显示结果

c# - 从 SID 获取 user@domain 而不是 domain\user

xml - 在平面结构中使用 xpath 导航到节点

java - sessionfactory、bean 和多个 xml 配置文件