我在使用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
答案 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文档。
希望有所帮助。