OSDN Git Service

Version 0.6.208, bug fixes.
[pettanr/clientJs.git] / 0.6.x / js / 05_util / 04_XXML.js
1 /*\r
2  * XMLWrapper_find 周りの オリジナルコードに関する情報\r
3  *  Original code by pettanR team\r
4  *  - https://osdn.jp/projects/pettanr/scm/git/clientJs/blobs/master/0.6.x/js/02_dom/08_XNodeSelector.js\r
5  *  and\r
6  *  Original code by ofk ( kQuery, ksk )\r
7  *  - http://d.hatena.ne.jp/ofk/comment/20090106/1231258010\r
8  *  - http://d.hatena.ne.jp/ofk/20090111/1231668170\r
9  * \r
10  * TODO X.Class で作り、kill を強要する\r
11  */\r
12 X[ 'XML' ] = XMLWrapper;\r
13 \r
14 /**\r
15  * XML ツリーを探索して読み出す用のラッパークラスです.XML を操作する機能はありません、あしからず…\r
16  * @alias X.XML\r
17  * @class XML 探索用のラッパークラスです\r
18  * @constructor\r
19  * @param {XMLElement}\r
20  */\r
21 function XMLWrapper( xml ){\r
22         if( xml ){\r
23                 this._rawXML = xml;\r
24                 this.tagName = xml.tagName;\r
25         };\r
26 };\r
27 \r
28 /**\r
29  * tagName または nodeName\r
30  * @alias X.XML.prototype.tagName\r
31  * @type {string}\r
32  */\r
33 XMLWrapper.prototype.tagName     = '';\r
34 /**\r
35  * ラップした xml の数 常に1または0, XMLList の場合2以上\r
36  * @alias X.XML.prototype.length\r
37  * @type {Number}\r
38  */\r
39 XMLWrapper.prototype.length      = 1;\r
40 XMLWrapper.prototype[ 'parent' ] = XMLWrapper_parent;\r
41 XMLWrapper.prototype[ 'has' ]    = XMLWrapper_has;\r
42 XMLWrapper.prototype[ 'get' ]    = XMLWrapper_get;\r
43 XMLWrapper.prototype[ 'val' ]    = XMLWrapper_val;\r
44 XMLWrapper.prototype[ 'find' ]   = XMLWrapper_find;\r
45 \r
46 /**\r
47  * 親要素を返す、ルート要素の場合 null を返す\r
48  * @alias X.XML.prototype.parent\r
49  * @return {X.XML} 親要素\r
50  */\r
51 function XMLWrapper_parent(){\r
52         if( this.length === 1 ) return this._rawXML && this._rawXML.parentNode ? new XMLWrapper( this._rawXML.parentNode ) : null;\r
53         if( this.length === 0 ) return null;\r
54         \r
55         return this[ 0 ].parentNode ? ( new XMLWrapper( this[ 0 ].parentNode ) ) : null;\r
56 };\r
57 \r
58 /**\r
59  * セレクターにヒットした要素数を返す\r
60  * @alias X.XML.prototype.has\r
61  * @param {string} queryString XML セレクター文字列\r
62  * @return {number}\r
63  */\r
64 function XMLWrapper_has( queryString ){\r
65         return !!this.find( queryString ).length;\r
66 };\r
67 \r
68 /**\r
69  * <p>X.XML では常に自信を返す\r
70  * <p>X.XMLList ではラップした xml 群から index のものを返す\r
71  * @alias X.XML.prototype.get\r
72  * @param {number} index\r
73  * @return {X.XML} X.XML では自身、X.XMLList では index の X.XML\r
74  */\r
75 function XMLWrapper_get( index ){\r
76         if( this.length === 1 ) return this;\r
77         if( this.length === 0 ) return null;\r
78         // 一度発行した XMLWrapper は控えて置いて再発行する。\r
79         if( this._wraps && this._wraps[ index ] ) return this._wraps[ index ];\r
80         if( !this._wraps ) this._wraps = [];\r
81         return this[ index ] ?\r
82                 ( this._wraps[ index ] = new XMLWrapper( this[ index ] ) ) :\r
83                 null;\r
84 };\r
85 \r
86 /**\r
87  * セレクターにヒットした要素の内容を指定されたデータ型で返す。複数要素にヒットした場合、0番目の要素の内容を使用する。\r
88  * @alias X.XML.prototype.val\r
89  * @param {string} queryString XML セレクター文字列\r
90  * @param {string} type 'number','int','boolean','string'\r
91  * @return {boolean|number|string} 内容を型変換した値\r
92  */\r
93 function XMLWrapper_val( queryString, type ){\r
94         var //attr_textContent = X_UA[ 'IE' ] < 9 || X_UA[ 'Opera' ] ? 'innerText' : X_UA[ 'IE9' ] ? 'text' : 'textContent',\r
95                 wrapper, xml, v;\r
96         \r
97         switch( queryString ){\r
98                 case 'number' :\r
99                 case 'int' :\r
100                 case 'boolean' :\r
101                 case 'string' :\r
102                 case undefined :\r
103                         type = queryString;\r
104                         queryString = 0;\r
105         };\r
106                 \r
107         wrapper = queryString ? this.find( queryString ) : this;\r
108         xml     = wrapper.length === 1 ? wrapper._rawXML : wrapper[ 0 ];\r
109 \r
110         if( !xml ){\r
111                 switch( type ){\r
112                         case 'number' :\r
113                         case 'int' :\r
114                                 return NaN;\r
115                         case 'boolean' :\r
116                                 return false;\r
117                         case 'string' :\r
118                                 return '';\r
119                         default :\r
120                                 return null;\r
121                 };\r
122         };\r
123         \r
124         v = xml.nodeType === 1 ? xml.innerText || xml.text || xml.textContent : xml.nodeValue;\r
125         //xml.toStrign()\r
126         switch( type ){\r
127                 case 'number' :\r
128                         return parseFloat( v );\r
129                 case 'int' :\r
130                         return parseFloat( v ) | 0;\r
131                 case 'boolean' :\r
132                         return !!X_String_parse( v );\r
133                 //case 'string' :\r
134                 //default :     \r
135         };\r
136         return v || '';\r
137 };\r
138 \r
139 /**\r
140  * セレクターにヒットした要素を返す。0~1個の要素がヒットした場合は X.XML を、それ以上の場合は X.XMLList を返す。\r
141  * @alias X.XML.prototype.find\r
142  * @param {string} queryString セレクター文字列\r
143  * @return {X.XML|X.XMLList} \r
144  */\r
145         function XMLWrapper_find( queryString ){\r
146 \r
147                 var scope     = this.constructor === XMLListWrapper ? this : [ this._rawXML ],\r
148                         parents   = scope, // 探索元の親要素 xmlList の場合あり\r
149                         ARY_PUSH  = Array.prototype.push,\r
150                         ret       = [], // 結果要素\r
151                         isXML     = true,\r
152                         isMulti   = 1 < scope.length,// 要素をマージする必要がある\r
153                         isStart   = true,\r
154                         _         = ' ',\r
155                         isAll, isNot, hasRoot,\r
156                         l, i, n, parsed,\r
157                         xmlList, // 一時保存用\r
158                         merge, // 要素がコメントノードで汚染されている場合使う\r
159                         combinator, selector, name, tagName,\r
160                         uid, tmp, xml, filter, key, op, val, toLower, useName,\r
161             links, className, attr, flag;\r
162 \r
163                 // 文字列以外は空で返す\r
164                 if( !X_Type_isString( queryString ) ) return XMLListWrapper_0;\r
165                 \r
166                 xmlList = [];\r
167                 \r
168                 // 以下、パースと探索\r
169                 for( ; queryString.length; ){\r
170                         //console.log( 'queryString[' + queryString + ']' );\r
171                         \r
172                         // 初期化処理\r
173                         if( !parsed ){\r
174                                 parsed = X_Node_Selector__parse( queryString );\r
175                                 \r
176                                 if( X_Type_isNumber( parsed ) ){\r
177                                         // error\r
178                                         return XMLListWrapper_0;\r
179                                 };\r
180                                 \r
181                                 queryString = queryString.substr( parsed[ 0 ] );\r
182                                 parsed      = parsed[ 1 ];\r
183                                 \r
184                                 if( parsed === 5 ){\r
185                                         isMulti = true;\r
186                                         parents = scope;\r
187                                         xmlList && xmlList.length && ARY_PUSH.apply( ret, xmlList );\r
188                                         parsed  = null;\r
189                                         xmlList = [];\r
190                                         isStart = true;\r
191                                         continue;\r
192                                 };\r
193                         };\r
194                         \r
195                         combinator  = parsed[ 0 ];\r
196                         selector    = parsed[ 1 ];\r
197                         name        = parsed[ 2 ];\r
198                         tagName     = selector === 1 ? name : '*';\r
199                         isAll       = tagName === '*';\r
200         \r
201                         if( !isStart ){\r
202                                 if( !xmlList.length ){\r
203                                         parsed = null;\r
204                                         continue;                                       \r
205                                 } else\r
206                                 if( combinator !== 0 ){\r
207                                         parents = xmlList;\r
208                                         xmlList = [];\r
209                                         //console.log( 'cobinator !== 0 ' + parents.length + ' : ' + xmlList.length );\r
210                                 };\r
211                         };\r
212                         \r
213                         i = 0;\r
214                         l = parents.length;\r
215                         n = -1; \r
216                         isMulti = isMulti || 1 < l;\r
217                         \r
218                         //console.log( 'combinator ' + combinator );\r
219         \r
220                         switch( combinator ){\r
221                                 // > TagName|*\r
222                                 case 2 :\r
223                                         for( ; i < l; ++i ){\r
224                                                 for( xml = parents[ i ].firstChild; xml; xml = xml.nextSibling ){\r
225                                                         if( xml.nodeType === 1 && ( isAll || tagName === xml.tagName ) ) xmlList[ ++n ] = xml;\r
226                                                 };                              \r
227                                         };\r
228                                         break;\r
229                                 // + TagName|*\r
230                                 case 3 :\r
231                                         for( ; i < l; ++i ){\r
232                                                 for( xml = parents[ i ].nextSibling; xml; xml = xml.nextSibling ){\r
233                                                         if( xml.nodeType === 1 ){\r
234                                                                 if( isAll || tagName === xml.tagName ) xmlList[ ++n ] = xml;\r
235                                                                 break;                                                          \r
236                                                         };\r
237                                                 };                                                              \r
238                                         };\r
239                                         break;\r
240                                 // ~ TagName|*\r
241                                 case 4 :\r
242                                         merge = [];\r
243                                         for( ; i < l; ++i ){\r
244                                                 for( xml = parents[ i ].nextSibling; xml; xml = xml.nextSibling ){\r
245                                                         if( xml.nodeType === 1 && ( isAll || tagName === xml.tagName ) ){\r
246                                                                 if( merge.indexOf( xml ) !== -1 ){\r
247                                                                         break;\r
248                                                                 } else {\r
249                                                                         merge[ merge.length ] = xml;\r
250                                                                         xmlList[ ++n ] = xml;\r
251                                                                 };\r
252                                                         };                                                                      \r
253                                                 };                                                              \r
254                                         };\r
255                                         break;\r
256 \r
257                                 // @ 属性ノード\r
258                                 case 6 :\r
259                                         selector = 0;\r
260                                         tagName  = '*';\r
261                                         for( ; i < l; ++i ){\r
262                                                 if( xml = parents[ i ].getAttributeNode( name ) ){\r
263                                                         xmlList[ ++n ] = xml;\r
264                                                 };\r
265                                         };\r
266                                         break;\r
267                                 default :\r
268                                         if( combinator === 1 || ( isStart && selector < 7 ) ){\r
269                                                 //console.log( l + ' > ' + xmlList.length + ' tag:' + tagName );\r
270                                                 for( ; i < l; ++i ){\r
271                                                         xml = parents[ i ];\r
272                                                         xml.childNodes && xml.childNodes.length && XMLWrapper_fetchElements( xmlList, xml, isAll ? null : tagName );\r
273                                                 };\r
274                                                 //console.log( l + ' >> ' + xmlList.length + ' tag:' + tagName );\r
275                                         };\r
276                         };\r
277                         \r
278                         isStart = false;\r
279                         \r
280                         //alert( 'pre-selector:' + ( xmlList && xmlList.length ) )\r
281                         \r
282                         switch( selector ){\r
283                                 // #, ID\r
284                                 case 2 :\r
285                                         filter = [ 'id', 1, name ]; break;\r
286                                 // ., class\r
287                                 case 3 :\r
288                                         filter = [ 'class', 3 /*'~='*/, name ]; break;\r
289                                 // :, 擬似クラス\r
290                                 case 4 :\r
291                                         if( !( filter = XMLWrapper_filter[ name ] ) ){\r
292                                                 return XMLListWrapper_0;\r
293                                         };\r
294                                         break;\r
295                                 // [] 属性\r
296                                 case 5 :\r
297                                         filter = [ name, parsed[ 3 ], parsed[ 4 ] ]; break;\r
298                                 // :not\r
299                                 case 6 :\r
300                                         isNot  = true;\r
301                                         parsed = parsed[ 2 ];\r
302                                         name   = parsed[ 2 ];\r
303                                         switch( parsed[ 1 ] ) {\r
304                                                 case 1 :\r
305                                                         filter = [ 'tag', 1, name ]; break;\r
306                                                 // #, ID\r
307                                                 case 2 :\r
308                                                         filter = [ 'id', 1, name ]; break;\r
309                                                 // ., class\r
310                                                 case 3 :\r
311                                                         filter = [ 'class', 3, name ]; break;\r
312                                                 // :, 擬似クラス\r
313                                                 case 4 :\r
314                                                         if( !( filter = XMLWrapper_filter[ name ] ) ){\r
315                                                                 return [];\r
316                                                         };\r
317                                                         break;\r
318                                                 // [] 属性\r
319                                                 case 5 :\r
320                                                         filter = [ name, parsed[ 3 ], parsed[ 4 ] ]; break;\r
321                                         };\r
322                                         break;\r
323                                 // scope\r
324                                 case 7 :\r
325                                         xmlList = scope; break;\r
326                                 /* root\r
327                                 case 8 :\r
328                                         hasRoot = true;\r
329                                         xmlList = [ HTML ]; break;\r
330                                 // link\r
331                                 case 9 :\r
332                                         if( links = document.links ){\r
333                                                 for( xmlList = [], i = links.length; i; ){\r
334                                                         xmlList[ --i ] = new Node( links[ i ] );\r
335                                                 };\r
336                                         } else {\r
337                                                 // area[href],a[href]\r
338                                         }; */\r
339                         };\r
340                         \r
341                         if( filter && xmlList.length ){\r
342                                 // filter.mが関数の場合\r
343                                 if( filter.m ){\r
344                                         xmlList = filter.m(\r
345                                                 {\r
346                                                         not : isNot,\r
347                                                         xml : isXML\r
348                                                 },\r
349                                                 xmlList,\r
350                                                 parsed[ 3 ], parsed[ 4 ]\r
351                                         );\r
352                                 } else\r
353                                 // filterが関数の場合\r
354                                 if( X_Type_isFunction( filter ) ){\r
355                                         tmp = [];\r
356                                         for( i = 0, n = -1; xml = xmlList[ i ]; ++i ){\r
357                                                 if( ( !!filter( xml ) ) ^ isNot ) tmp[ ++n ] = xml;     \r
358                                         };\r
359                                         xmlList = tmp;\r
360                                 } else {\r
361                                 // 属性セレクター                        \r
362                                         tmp = [];\r
363                                         key = filter[ 0 ];\r
364                                         op  = filter[ 1 ];\r
365                                         val = filter[ 2 ];\r
366 \r
367                                         // 通常\r
368                                                 if( op === 3 ) val = _ + val + _;\r
369 \r
370                                                 for( i = 0, n = -1, l = xmlList.length; i < l; ++i ){\r
371                                                         xml  = xmlList[ i ];\r
372                                                         attr = xml.getAttribute( key, 2 );\r
373                                                         flag = attr != null;// && ( !useName || attr !== '' );\r
374                                                         if( flag && op ){\r
375                                                                 //if( toLower ) attr = attr.toLowerCase();\r
376                                                                 \r
377                                                                 switch( op ){\r
378                                                                         case 1: // =\r
379                                                                                 flag = attr === val;\r
380                                                                                 break;\r
381                                                                         case 2: // !=\r
382                                                                                 flag = attr !== val;\r
383                                                                                 break;\r
384                                                                         case 3: // ~=\r
385                                                                                 flag = ( _ + attr + _ ).indexOf( val ) !== -1;\r
386                                                                                 break;\r
387                                                                         case 4: // ^=\r
388                                                                                 flag = attr.indexOf( val ) === 0;\r
389                                                                                 break;\r
390                                                                         case 5: // $=\r
391                                                                                 flag = attr.lastIndexOf( val ) + val.length === attr.length;\r
392                                                                                 break;\r
393                                                                         case 6: // *=\r
394                                                                                 flag = attr.indexOf( val ) !== -1;\r
395                                                                                 break;\r
396                                                                         case 7: // |=\r
397                                                                                 flag = attr === val || attr.substring( 0, val.length + 1 ) === val + '-';\r
398                                                                                 break;\r
399                                                                 };\r
400                                                         };\r
401                                                         if( !!flag ^ isNot ) tmp[ ++n ] = xml;\r
402                                                 //};\r
403                                         };\r
404                                         xmlList = tmp;\r
405                                 };\r
406                         };\r
407                         filter  = null;\r
408                         isNot   = false;\r
409                         parsed  = null;\r
410                         \r
411                         //console.log( '//end :' + ( xmlList && xmlList.length ) );\r
412                 };\r
413                 //console.log( 'multi:' + ( xmlList && xmlList.length ) );\r
414                 \r
415                 // tree 順に並び替え、同一要素の排除\r
416                 if( isMulti ){\r
417                         xmlList && xmlList.length && ARY_PUSH.apply( ret, xmlList );\r
418                         l = ret.length;\r
419                         if( l === 0 ) return XMLListWrapper_0;\r
420                         if( l === 1 ) return new XMLWrapper( ret[ 0 ] );\r
421                         \r
422                         xmlList = [];\r
423                         //merge   = [];\r
424                         for( i = 0, n = -1; i < l; ++i ){\r
425                                 //alert( 'multi:' + i )\r
426                                 xml = ret[ i ];\r
427                                 if( xmlList.indexOf( xml ) === -1 ){\r
428                                         //merge[ merge.length ] = xml;\r
429                                         xmlList[ ++n ] = xml;\r
430                                 };\r
431                         };\r
432                         XMLWrapper_sortElementOrder( ret = [], xmlList, this._rawXML.childNodes );\r
433                         \r
434                         // @\r
435                         for( i = 0, l = xmlList.length; i < l; ++i ){\r
436                                 if( ret.indexOf( xml = xmlList[ i ] ) === -1 ){\r
437                                         ret[ ret.length ] = xml;\r
438                                 };\r
439                         };\r
440                         \r
441                         xmlList = ret;\r
442                 };\r
443 \r
444                 return xmlList.length === 1 ? new XMLWrapper( xmlList[ 0 ] ) : new XMLListWrapper( xmlList );\r
445         };\r
446 \r
447         function XMLWrapper_sortElementOrder( newList, list, xmlList ){\r
448                 var l = xmlList.length,\r
449                         i = 0,\r
450                         j, child, _xmlList;\r
451                 for( ; i < l; ++i ){\r
452                         child = xmlList[ i ];\r
453                         //if( child.nodeType !== 1 ) continue;\r
454                         //console.log( child.tagName );\r
455                         if( ( j = list.indexOf( child ) ) !== -1 ){\r
456                                 newList[ newList.length ] = child;\r
457                                 list.splice( j, 1 );\r
458                                 if( list.length === 1 ){\r
459                                         newList[ newList.length ] = list[ 0 ];\r
460                                         list.length = 0;\r
461                                         return true;\r
462                                 };\r
463                                 if( list.length === 0 ) return true;\r
464                         };\r
465                         if( ( _xmlList = child.childNodes ) && XMLWrapper_sortElementOrder( newList, list, _xmlList ) ){\r
466                                 return true;\r
467                         };\r
468                 };\r
469         };\r
470         \r
471         function XMLWrapper_fetchElements( list, parent, tag ){\r
472                 var xmlList = parent.childNodes,\r
473                         l      = xmlList.length,\r
474                         i      = 0,\r
475                         child;\r
476                 for( ; i < l; ++i ){\r
477                         child = xmlList[ i ];\r
478                         if( child.nodeType === 1 ){\r
479                                 ( !tag || child.tagName === tag ) && ( list[ list.length ] = child );\r
480                                 //console.log( parent.tagName + ' > ' + child.tagName + ' == ' + tag+ ' l:' + list.length );\r
481                                 child.childNodes && child.childNodes.length && XMLWrapper_fetchElements( list, child, tag );\r
482                         };\r
483                 };\r
484         };\r
485 \r
486         function XMLWrapper_funcSelectorChild( type, flag_all, flags, xmlList ){\r
487                 var res      = [],\r
488                         flag_not = flags.not,\r
489                         i = 0, n = -1, xml, node,\r
490                         tagName, tmp;\r
491                 for( ; xml = xmlList[ i ]; ++i ){\r
492                         tagName = flag_all || xml.tagName;\r
493                         tmp     = null;\r
494                         if( /* tmp === null && */ type <= 0 ){\r
495                                 for( node = xml.previousSibling; node; node = node.previousSibling ){\r
496                                         if( node.nodeType === 1 && ( flag_all || tagName === node.tagName ) ){\r
497                                                 tmp = false;\r
498                                                 break;\r
499                                         };\r
500                                 };\r
501                         };\r
502                         if( tmp === null && 0 <= type ){\r
503                                 for( node = xml.nextSibling; node; node = node.nextSibling ){\r
504                                         if( node.nodeType === 1 && ( flag_all || tagName === node.tagName ) ){\r
505                                                 tmp = false;\r
506                                                 break;\r
507                                         };              \r
508                                 };                                              \r
509                         };\r
510                         if( tmp === null ) tmp = true;\r
511                         if( tmp ^ flag_not ) res[ ++n ] = xml;\r
512                 };\r
513                 return res;\r
514         };\r
515         function XMLWrapper_funcSelectorNth( pointer, sibling, flag_all, flags, xmlList, a, b ){\r
516                 var uids     = X_Array_copy( xmlList ),\r
517                         res      = [],\r
518                         checked  = {},\r
519                         flag_not = flags.not,\r
520                         i = 0, n = -1,\r
521                         c, xml, tmp, node, tagName, uid;\r
522 \r
523                 for( ; xml = xmlList[ i ]; ++i ){\r
524                         tmp = checked[ i ];\r
525                         if( tmp === undefined ){\r
526                                 for( c = 0, node = xml.parentNode[ pointer ], tagName = flag_all || xml.tagName; node; node = node[ sibling ] ){\r
527                                         if( node.nodeType === 1 && ( flag_all || tagName === node.tagName ) ){\r
528                                                 ++c;\r
529                                                 uid = uids.indexOf( node );\r
530                                                 if( uid === -1 ) uids[ uid = uids.length ] = node;\r
531                                                 checked[ uid ] = a === 0 ? c === b : (c - b) % a === 0 && (c - b) / a >= 0;\r
532                                         };\r
533                                 };\r
534                                 tmp = checked[ i ];\r
535                         };\r
536                         if( tmp ^ flag_not ) res[ ++n ] = xml;\r
537                 };\r
538                 return res;\r
539         };\r
540         /*\r
541         function XMLWrapper_funcSelectorProp( prop, flag, flags, xmlList ){\r
542                 var res = [],\r
543                         flag_not = flag ? flags.not : !flags.not,\r
544                         i = 0, n = -1, xml;\r
545                 for( ; xml = xmlList[ i ]; ++i ){\r
546                         if( xml.getAttributeNode( prop ) ^ flag_not ) res[ ++n ] = xml;\r
547                 };\r
548                 return res;\r
549         }; */\r
550 \r
551 var XMLWrapper_filter = {\r
552         'first-child' : {\r
553                 m : function( flags, xmlList ){ return XMLWrapper_funcSelectorChild( -1, true, flags, xmlList ); }\r
554         },\r
555         'last-child' : {\r
556                 m : function( flags, xmlList ){ return XMLWrapper_funcSelectorChild( 1, true, flags, xmlList ); }\r
557         },\r
558         'only-child' : {\r
559                 m : function( flags, xmlList ){ return XMLWrapper_funcSelectorChild( 0, true, flags, xmlList ); }\r
560         },\r
561         'first-of-type' : {\r
562                 m : function( flags, xmlList ){ return XMLWrapper_funcSelectorChild( -1, false, flags, xmlList ); }\r
563         },\r
564         'last-of-type' : {\r
565                 m : function( flags, xmlList ){ return XMLWrapper_funcSelectorChild( 1, false, flags, xmlList ); }\r
566         },\r
567         'only-of-type' : {\r
568                 m : function( flags, xmlList ){ return XMLWrapper_funcSelectorChild( 0, false, flags, xmlList ); }\r
569         },\r
570         'nth-child' : {\r
571                 m : function( flags, xmlList, a, b ){ return XMLWrapper_funcSelectorNth( 'firstChild', 'nextSibling', true, flags, xmlList, a, b ); }\r
572         },\r
573         'nth-last-child' : {\r
574                 m : function( flags, xmlList, a, b ){ return XMLWrapper_funcSelectorNth( 'lastChild', 'previousSibling', true, flags, xmlList, a, b ); }\r
575         },\r
576         'nth-of-type' : {\r
577                 m : function( flags, xmlList, a, b ){ return XMLWrapper_funcSelectorNth( 'firstChild', 'nextSibling', false, flags, xmlList, a, b ); }\r
578         },\r
579         'nth-last-of-type' : {\r
580                 m : function( flags, xmlList, a, b ){ return XMLWrapper_funcSelectorNth( 'lastChild', 'previousSibling', false, flags, xmlList, a, b ); }\r
581         },\r
582         'empty' : {\r
583                 m : function( flags, xmlList ){\r
584                         var res = [],\r
585                                 flag_not = flags.not,\r
586                                 i = 0, n = -1, xml, tmp, node;\r
587                         for( ; xml = xmlList[i]; ++i ){\r
588                                 tmp = true;\r
589                                 for( node = xml.firstChild; node; node = node.nextSibling ){\r
590                                         if( node.nodeType === 1 || ( node.nodeType === 3 && node.nodeValue ) ){\r
591                                                 tmp = false;\r
592                                                 break;\r
593                                         };                              \r
594                                 };\r
595                                 if( tmp ^ flag_not ) res[ ++n ] = xml;\r
596                         };\r
597                         return res;\r
598                 }\r
599         },\r
600         'contains' : {\r
601                 m : function( flags, xmlList, arg ){\r
602                         var res = [],\r
603                                 flag_not = flags.not,\r
604                                 i = 0, n = -1, xml, text = '';\r
605 \r
606                         for( ; xml = xmlList[ i ]; ++i ){\r
607                                 switch( xml.nodeType ){\r
608                                         case 1 :\r
609                                                 text = xml.innerText || xml.text || xml.textContent;\r
610                                                 break;\r
611                                         //case 2 :\r
612                                         case 3 :\r
613                                                 text = xml.nodeValue;\r
614                                                 break;\r
615                                 };\r
616                                 if ( ( -1 < text.indexOf( arg ) ) ^ flag_not ) res[ ++n ] = xml;                \r
617                         };\r
618                         return res;\r
619                 }\r
620         }\r
621 };\r
622 \r
623 /**\r
624  * XML配列を扱う XML 探索用のラッパークラスです\r
625  * @alias X.XMLList\r
626  * @class XMLList XML配列を扱う XML 探索用のラッパークラスです\r
627  * @constructor\r
628  * @extends {X.XML}\r
629  */\r
630 function XMLListWrapper( xmlList ){\r
631         var i = 0, l = xmlList ? xmlList.length : 0;\r
632         for( ; i < l; ++i ){\r
633                 this[ i ] = xmlList[ i ];\r
634         };\r
635         this.length = l;\r
636 };\r
637 \r
638 var XMLListWrapper_0 = new XMLListWrapper();\r
639 \r
640 XMLListWrapper.prototype.length      = 0;\r
641 XMLListWrapper.prototype._wraps      = null;\r
642 XMLListWrapper.prototype[ 'parent' ] = XMLWrapper_parent;\r
643 XMLListWrapper.prototype[ 'has' ]    = XMLWrapper_has;\r
644 XMLListWrapper.prototype[ 'get' ]    = XMLWrapper_get;\r
645 XMLListWrapper.prototype[ 'val' ]    = XMLWrapper_val;\r
646 XMLListWrapper.prototype[ 'find' ]   = XMLWrapper_find;\r