[IM]リピーターとエンクロージャーの識別

HTMLドキュメントからリピーターを検出し、データベースのないように置き換えるための処理手順を検討します。ここで、ドキュメント内のノードの一部を取り出したものが以下の図です。「エンクロージャー」「リピーター」に加えて、データベースのデータを受け入れる「リンクされた要素」があるものとします。

a2ba5

.5までは、リンクされた要素はINPUTなどいくつかの種類のタグのみで、ElementsByTagNameメソッドで要素を参照して、NAME属性があるかどうかというところをチェックしていました。ここで、リンクされた要素になり得る要素はすべての要素となると、基本的にはドキュメント内のすべての要素をチェックしなければなりません。従って、BODYタグの要素より以下を調べる事になるが、ここで、エンクロージャーが見つかった場合、エンクロージャーよりも下位を走査する必要はない。もしくはしていはいけない。なぜなら、エンクロージャー以下はリピーター要素の複製などによって内容が変わる可能性があるからである。加えて、エンクロージャーが見つかった場合の処理はリピーターの中でカスケードされるようにすれば、全体は走査する必要はない。従って、BODY以下は前順走査を行い、エンクロージャーが見つかった場合はエンクロージャー内の複製・展開処理を行い、引き続いては自分の兄弟のノードに移動すれば良いということになる。この考察に基づいて、ドキュメント中の展開すべきところを検知するプログラムとしては以下のようになる。

var bodyNode = document.getElementsByTagName( ‘BODY’ )[0];
seekNodes( bodyNode );

function seekNodes( node ) {
var enclosure = null;
var nType = node.nodeType;
if ( nType == 1 ) {
if ( isLinkedElement( node ) ) {
enclosure = getEnclosure( node );
} else {
var childs = node.childNodes;
for ( var i = 0 ; i < childs.length ; i++ ) {
var checkingEncl = seekNodes( childs[i] );
if ( checkingEncl != null ) {
if ( checkingEncl == childs[i] ) {
expandEnclosure( node );
enclosure = null;
} else {
return checkingEncl;
}
}
}
}
} else {

}
return enclosure;
}

function isLinkedElement( node ) {
if ( node.getAttribute( ‘TITLE’ ) != null ) {
return true
} else {
return false;
}
}

function getEnclosure( node ) {
var currentNode = node;
var encTagCandidate = null;
var encTagCandidateAlt = null;
var encClassCandidate = null;
while ( currentNode != null ) {
var tagName = currentNode.tagName;
var className = currentNode.getAttribute(‘class’);
if ( tagName == ‘TR’ ) {
encTagCandidate = ‘TBODY’;
} else if ( tagName == ‘LI’ ) {
encTagCandidate = ‘UL’;
encTagCandidateAlt = ‘OL’;
} else if ( tagName == ‘OPTION’ ) {
encTagCandidate = ‘SELECT’;
} else if ( tagName == ‘DIV’ && (className != null) && className.match(/_im_repeater/) {
encTagCandidate = ‘DIV’;
encClassCandidate = ‘_im_enclosure’;
}
if ( (( encTagCandidate != null ) && ( tagName == encTagCandidate ))
|| (( encTagCandidateAlt != null ) && ( tagName == encTagCandidateAlt ))
|| (( encClassCandidate != null ) && ( className.indexOf(encClassCandidate) >= 0 ))) {
return currentNode;
}
<div class=”wiki_entry”> currentNode 2010-03-08 02:49:24
=”Apple-tab-span”> </span>currentNode = currentNode.parentNode;</div>
}
return null;
}

function expandEnclosure( node ) {

}