class XMLQuery { private var qNodeName, qProvider, qSearchDepth; private var qNode; function XMLQuery(wNodeName, wProvider, wSearchDepth, wNode) { if (wSearchDepth == undefined) wSearchDepth = 0; if (wNode == undefined) { var iDepth = 1; wNode = wProvider; while (wNode.parentNode && iDepth < wSearchDepth) { wNode = wNode.parentNode; iDepth++; } if (wSearchDepth >= iDepth) { wSearchDepth = iDepth; while (wNode.previousSibling) wNode = wNode.previousSibling; } while (iDepth) { while (wNode.hasChildNodes() == false && wSearchDepth) wNode = wNode.nextSibling; wNode = wNode.firstChild; iDepth--; } } if (wProvider instanceof XMLQuery) { if (wProvider.qNode != wNode.parentNode) wProvider = cloneProvider(wProvider, wNode); } else { wProvider = wNode.parentNode; } // qNodeName = wNodeName; qProvider = wProvider; qSearchDepth = wSearchDepth; //! trace('['+qNodeName+']: '+ wNode); qNode = searchMatch(wNode, 1, true); } function previousMatch(wNode) { return searchMatch(wNode, -1); } function nextMatch(wNode) { return searchMatch(wNode, 1); } function searchMatch(wNode, wWay, wValidate) { if (wWay < 0 || wWay == '-' || wWay == '<' || wWay == 'previous') wWay = [ 'previousSibling', 'lastChild' ]; else wWay = [ 'nextSibling', 'firstChild' ]; // var iNode = wNode; var iDepth = 0; var wProvider = qProvider; if (wValidate != true) iNode = iNode[wWay[0]]; do { while (iNode && !checkNodeName(iNode.nodeName)) iNode = iNode[wWay[0]]; if (iNode != null) break; //! trace('['+qNodeName+']> {'); while (iNode == null && iDepth < qSearchDepth) { if (iDepth) wNode = wNode.parentNode; else wNode = wProvider; iNode = wNode[wWay[0]]; //! trace(' ' + iDepth + ': ' + wNode); //! trace(' : ' + iNode); iDepth++; } //! if (iNode == null) trace('} ! ' + iNode); if (iNode == null) break; while (iDepth) { while (iNode.hasChildNodes() == false) iNode = iNode.nextSibling; if (iDepth == 1) wProvider = iNode; iNode = iNode[wWay[1]]; iDepth--; } wNode = iNode; //! trace('} > ' + iNode); } while (true); return iNode; } private function checkNodeName(wName) { if (qNodeName == '' || qNodeName == undefined) return true; return (wName == qNodeName); } private function cloneProvider(wProvider, wNode) { return new XMLQuery(wProvider.qNodeName, wProvider.qProvider, wProvider.qSearchDepth, wNode.parentNode); } /** XMLNode copycat */ function get attributes() { return qNode.attributes; } function get childNodes() { return qNode.childNodes; } function get nodeName() { return qNode.nodeName; } function set nodeName(wNodeName) { qNode.nodeName = wNodeName; } function get nodeType() { return qNode.nodeType; } function get nodeValue() { return qNode.nodeValue; } function get firstChild() { return qNode.firstChild; } function get lastChild() { return qNode.lastChild; } function appendChild(newChild:XMLNode):Void { qNode.appendChild(newChild); } function cloneNode(deep:Boolean):XMLNode { return qNode.cloneNode(deep); } function hasChildNodes():Boolean { return qNode.hasChildNodes(); } function insertBefore(newChild:XMLNode, insertPoint:XMLNode):Void { qNode.insertBefore(newChild, insertPoint); } function removeNode():Void { qNode.removeNode(); } function toString():String { return qNode.toString(); } /** XMLNode customization */ function get parentNode() { return qProvider; } function get firstSibling() { var wNode, iDepth; // first search the firstmost node in range wNode = qNode; iDepth = 0; while (wNode.parentNode && iDepth < qSearchDepth) { wNode = wNode.parentNode; iDepth++; } while (wNode.previousSibling) wNode = wNode.previousSibling; while (iDepth) { wNode = wNode.firstChild; iDepth--; } // return the next match wNode = searchMatch(wNode, 1, true); // I don't check for null because there's at least the self occurence return new XMLQuery(qNodeName, qProvider, qSearchDepth, wNode); } function get previousSibling() { var wNode = searchMatch(qNode, -1); if (wNode == null) return null; else return new XMLQuery(qNodeName, qProvider, qSearchDepth, wNode); } function get nextSibling() { var wNode = searchMatch(qNode, 1); if (wNode == null) return null; else return new XMLQuery(qNodeName, qProvider, qSearchDepth, wNode); } function get lastSibling() { var wNode, iDepth; // first search the lastmost node in range wNode = qNode; iDepth = 0; while (wNode.parentNode && iDepth < qSearchDepth) { wNode = wNode.parentNode; iDepth++; } while (wNode.nextSibling) wNode = wNode.nextSibling; while (iDepth) { wNode = wNode.lastChild; iDepth--; } // return the previous match wNode = searchMatch(wNode, -1, true); // I don't check for null because there's at least the self occurence return new XMLQuery(qNodeName, qProvider, qSearchDepth, wNode); } function get node() { return qNode; } }