我遇到了一个我管理的软件的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工具,非常方便)。这是一种沮丧的运动,烧毁了我一整天。
答案 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
。我纠正了这一点,它也按预期工作。