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() のトリックは、2 番目のセットに :not フィルターを再度適用する必要があることです (これにより、最初の :not フィルターは時代遅れになります)。そうして初めて、正しい結果が得られます。後述の @Steve として結果をログに記録することで、さまざまな段階を視覚化するのに役立ちます。
編集 3: 最後の find() の前にサブセットにアクセスする標準的な方法が必要な場合、これは解決策になります。まず、フィルターを使用して、テンプレートとその子を除くリーフ ノードを選択します。次に、以下の例のように、この $subset から $subset まで検索します。
$subset = $dataXDoc.find('*:not([template], [template] *)').filter(function(){return $(this).children().length == 0});
$node = $subset.filter('node2a');
編集 4: 編集 3 を修正