1

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 を修正

4

1 に答える 1

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 自体が*セレクターと一致し、2 番目の一致が得られることがわかりますが、xml 文字列の場合、jQuery はそれを xml として解析しますが、xml ドキュメントは作成しません。

それが役立つことを願っています。

于 2012-06-09T17:59:09.387 に答える