有没有在我的XML code或.NET中的错误? [英] Is there a bug in my XML code or in .NET?

查看:111
本文介绍了有没有在我的XML code或.NET中的错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是碰到了一个问题,我的code的解析XML很好,但一旦我添加第二个节点,它开始加载不正确的数据。真正的code跨越许多类和项目,但对样品我已经把什么是导致基本问题

在code运行时,我期望的输出成为第二个任务节点的内容,而是第一个节点的内容输出。它使不管如何,当您检查设置对象的内部XML的是,第二个任务节点从EmailAddresses节点的第一次出现拉。以的SelectSingleNode(// EmailAddresses)电话是那里的问题发生。

我有解决这个问题的两个方面。

  1. 从EmailAddresses的XPath EX pression删除前导斜线
  2. 呼叫克隆()获取任务或设置节点后

解决方法1作品在这种情况下,但我相信,这将导致其他code在我的项目停止工作。

解决方案2看起来更像是一个黑客对我来说不是一个真正的解决方案。

我的问题是我我其实在做正确这一点,有一个在.NET中的错误(所有版本)或我只是拉XML错了吗?

在C#code

  VAR DOC =新的XmlDocument();
doc.Load(@D:\ TEMP \ sample.xml中);

VAR任务= doc.SelectSingleNode(服务器/任务);

的foreach(在tasks.ChildNodes XmlNode的threadNode)
{
    如果(threadNode.Name.ToLower()!=线程)
    {
        继续;
    }

    的foreach(XmlNode的taskNode在threadNode.ChildNodes)
    {
        如果(taskNode.Name.ToLower()!=任务|| taskNode.Attributes [名称]。值!=任务1)
        {
            继续;
        }

        VAR设置= taskNode.SelectSingleNode(设置);

        变种电子邮件= settings.SelectSingleNode(// EmailAddresses);

        Console.WriteLine(emails.InnerText);
    }
}
 

中的XML

 < XML版本=1.0&GT?;
<服务器>
    <任务>
        <主题>
            <任务名称=任务2>
                <设置>
                    < EmailAddresses>任务2数据和LT; / EmailAddresses>
                < /设置>
            < /任务>
        < /线程>
        <主题>
            <任务名称=任务1>
                <设置>
                    < EmailAddresses>任务1数据和LT; / EmailAddresses>
                < /设置>
            < /任务>
        < /线程>
    < /任务>
< /服务器>
 

解决方案

HTTP: //www.w3.org/TR/xpath/#path-abbrev

  

// 是短期的    /后代,或自::节点()/ 。对于   例如, //对是短期的    /后代,或自::节点()/ child :: para的   ,因此将选择在任何para元素   该文件(即使是对元素   是一个文档元素将被选择   通过 //对,因为文档元素   节点是根节点的孩子);

和也:

  

的位置,一步是短期的   自::节点()。这是特别   用于与 // 一起使用。对于   例如,位置路径 //对   是短期的。

 自::节点()/后代,或自::节点()/ child :: para的
 

     

,因此将选择所有对后代   上下文节点的元素

相反的:

  VAR设置= taskNode.SelectSingleNode(设置);

变种电子邮件= settings.SelectSingleNode(// EmailAddresses);
 

使用:

 变种的电子邮件= taskNode.SelectSingleNode(设置/ EmailAddresses);
 

I just ran into an issue where my code was parsing xml fine but once I added in a second node it started to load incorrect data. The real code spans a number of classes and projects but for the sample I've put together the basics of what's causing the issue

When the code runs I'd expect the output to be the contents of the second Task node, but instead the contents of the first node is output. It keeps pulling from the first occurrence of the EmailAddresses node despite how when you check the settings object its inner xml is that of the second Task node. The call to SelectSingleNode("//EmailAddresses") is where the issue happens.

I have two ways around this issue

  1. Remove the leading slashes from the EmailAddresses XPath expression
  2. Call Clone() after getting the Task or Settings node

Solution 1 works in this case but I believe this will cause other code in my project to stop working.

Solution 2 looks more like a hack to me than a real solution.

MY question is am I in fact doing this correctly and there's a bug in .NET (all versions) or am I just pulling the XML wrong?

The c# code

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);
    }
}

The 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>

解决方案

From 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);

And also:

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.

Instead of:

var settings = taskNode.SelectSingleNode("Settings");

var emails = settings.SelectSingleNode("//EmailAddresses");

Use:

var emails = taskNode.SelectSingleNode("Settings/EmailAddresses");

这篇关于有没有在我的XML code或.NET中的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆