如果从XML文档创建jQuery对象,则使用JQuery.find()查询XML会提供意外结果

时间:2012-06-09 17:24:23

标签: jquery xml find xforms

我在使用jQuery查询XML时注意到了不同的结果,具体取决于jQuery对象的实例化方式,即。来自 XML文档或来自 XML字符串。前者给出了意想不到的结果,我猜我在这里遗漏了一些东西。

xmlStr = '<data>'+
               '<node1 />'+
               '<node2 template="">'+
                      '<node2a>def</node2a>'+
               '</node2>'+
               '<node2>'+
                      '<node2a>val2a</node2a>'+
               '</node2>'+
               '<node2 />'+
               '<node3>a value</node3>'+
         '</data>';

dataXMLDoc = $.parseXML(xmlStr);
$dataXDoc = $(dataXMLDoc);
$data = $(xmlStr);

//queries using $dataXDoc (created from XML Document)
console.log('1a:length: '+$dataXDoc.find('node2a:not([template], [template] *)').length); //finds 1
console.log('2a:length: '+$dataXDoc.find('*:not([template], [template] *)').find('node2a').length); //finds *2*
console.log('3a:length: '+$dataXDoc.find('*').not('[template], [template] *').find('node2a').length); //finds *2*
console.log('4a:length: '+$dataXDoc.find('*:not([template], [template] *)').find('node2a').length); //finds *2*

//queries using $data (created from XML String)
console.log('1b:length: '  +  $data.find('node2a:not([template], [template] *)').length);  //finds 1
console.log('2b:length: '  +  $data.find('*:not([template], [template] *)').find('node2a').length); //finds 1
console.log('3b:length: '  +  $data.find('*').not('[template], [template] *').find('node2a').length); //finds 1
console.log('4b:length: '  +  $data.find('*:not([template], [template] *)').find('node2a').length); //finds 1

我意识到使用后续的find()在这个特定的例子中没有意义,1a和1b是这个上下文中的最佳选择。但是,2a,3a和4a不应该给出相同的结果吗?为什么不呢?

基本上,我试图排除具有模板属性的节点和具有模板属性的节点后代的节点,在我尝试找到我想要的节点之前。

编辑1: 感谢@Steven,这为两个JQuery对象提供了相同的结果(不包括XMLDocument本身):

console.log('2a:length: '+$dataXDoc.find('* *:not([template], [template] *)').find('node2a').length); //finds *1*
console.log('3a:length: '+$dataXDoc.find('* *').not('[template], [template] *').find('node2a').length); //finds *1*
console.log('4a:length: '+$dataXDoc.find('* *:not([template], [template] *)').find('node2a').length); //finds *1*

编辑2: 当使用更复杂的XML文档进行测试时,我注意到仍然存在问题。后续find()的技巧是你必须在第二组上再次应用:not过滤器(这使第一组:过滤器类型过时)。只有这样你才能得到正确的结果。通过将结果记录为下面提到的@Steve,可以将不同阶段可视化。

编辑3: 如果我想在最终的find()之前访问子集的标准方法,这将是一个解决方案。首先使用过滤器选择除模板及其子项之外的叶节点。然后像下面的示例一样在$ sub子上搜索。

$subset = $dataXDoc.find('*:not([template], [template] *)').filter(function(){return $(this).children().length == 0});
$node = $subset.filter('node2a');

编辑4: 纠正编辑3

1 个答案:

答案 0 :(得分:1)

如果检查find命令链的每个步骤的输出:

console.log($dataXDoc);
console.log($dataXDoc.find('*:not([template], [template] *)'));
console.log($dataXDoc.find('*:not([template], [template] *)').find('node2a'));

console.log($data);
console.log($data.find('*:not([template], [template] *)'));
console.log($data.find('*:not([template], [template] *)').find('node2a'));

您将看到xmlDocument本身与*选择器匹配,然后它会为您提供第二个匹配,但在xml字符串中,jQuery将其解析为xml,但不创建xml文档。

希望有所帮助。