XmlNode.SelectNode奇怪(没有找到两个非常相似的节点之一)

时间:2012-02-16 20:13:10

标签: xml vb.net csv xmlnode

我遇到了一个我管理的软件的bug,用于根据用户选择创建Bills of Materials。它适用于包含我们所有零件编号的大型xml文件以及我们编写的规则,这些规则用于根据工程师的选择选择这些零件编号。

我今天意识到,在一个非常具体的部分,大约一半的选择工作,而另一半没有。以下是具体细节。

我们根据相关规则的参数构建一个字符串,这些参数是根据用户选择设置的。此字符串将传递给XmlNode.SelectNode方法:

mItem = mXMLData.SelectNodes(XPath)

以下是xpath字符串的两个示例,一个用于查找节点,另一个用于查找节点:

A)

/Root/Items/Item[@DropDownDescription='Ball Bearing' and @Diameter='1 7/16']

B)

/Root/Items/Item[@DropDownDescription='Ball Bearing' and @Diameter='1 11/16']

第一个字符串A不会返回任何节点,而第二个字符串B将返回。以下是我们的xml数据库中包含这些部件号的部分:

<Item Key="FanBearing.1.3" ItemNumber="30400074" DropDownDescription="Ball Bearing" Diameter="1 7/16" />
<Item Key="FanBearing.1.4" ItemNumber="30400075" DropDownDescription="Ball Bearing" Diameter="1 11/16" />

(我从这些条目中删除了一些无关紧要的数据,使它们更短更容易阅读。在这两种情况下,删除的数据几乎相同,差异只是成本/重量等。)

如您所见,A和B两个条目都在数据文件中。最奇怪的部分是我能够用我们所有不同的轴承尺寸复制错误,并且它确实找到的那个在数字的小数部分有一个双位数分子,而它没有找到一位数分子。现在,这当然必须是巧合,因为它只是一个字符串,根本不重要,但它对我们所拥有的每一个尺寸都适用。

这就是我所拥有的,我一直在与我们的其他开发人员(实际编写了大部分程序的开发人员)进行讨论,我们都不知所措。如果有人有任何想法,请分享。此外,我试图尽可能彻底地在这里,但如果需要其他信息,我很乐意添加它。

感谢。

编辑:我终于弄明白了。

好的,所以这最终是一个非常奇怪的事情,最终与XmlNode.SelectNode函数无关。

使用我们在此处从.csv文件集合创建的自定义工具编译有问题的XML文件。当我们需要进行更改或具有这种性质的事情时,csv文件使数据更容易操作。

我们编译它的工具也加密了文件,正如我前面提到的。我们还有一个版本,可以在没有加密的情况下编译它,这是我之前查看它的方式。

当未加密查看时,有问题的行在'1 7/16'中有一个空格

在记事本中查看CSV文件时,有一个空格。

在excel中查看CSV文件时,它显示了两个空格,以便列匹配(excel格式化,呃)。

当我最终浏览代码,并查看它正在搜索的内存中的实际xml数据时,'1 7/16'有两个空格,所以当然它从来没有匹配。

最后,我必须将保存直径数据的excel中的CSV文件列更改为数字格式的文本格式,保存并重新编译。如果我再次打开CSV文件,没有更改,保存它,它会再次将第二个空格放回去。

我修好了,程序正在运行。

感谢大家的回复(特别是关于xpathvisualizer工具,非常方便)。这是一种沮丧的运动,烧毁了我一整天。

1 个答案:

答案 0 :(得分:0)

我已经验证了一个最小的例子:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var doc = new XmlDocument();
            doc.Load(@"..\..\XMLFile1.xml");

            var x1 = doc.SelectSingleNode("Items/Item[@DropDownDescription='Ball Bearing' and @Diameter='1 7/16']");
            var x2 = doc.SelectSingleNode("Items/Item[@DropDownDescription='Ball Bearing' and @Diameter='1 11/16']");
        }
    }
}

...适用于C#和.NET 4.0。我从样本文档中排除了<Root>,因为我看不出它是如何相关的。

编辑#1:

对于VB来说,并不是说它应该有所不同,而事实并非如此。我还注意到我在第一个例子中使用了SelectSingleNode而不是SelectNodes。我纠正了这一点,它也按预期工作。