	protected List<Element> handleModFind( Element contextNode, Element node ) {
		List<Element> result = null;
		if ( node.getNamespace().equals( modNS ) ) {
			if ( node.getName().equals( "findName" ) ) {
				String searchName = node.getAttributeValue( "name" );
				String searchType = node.getAttributeValue( "type" );
				boolean searchReverse = getAttributeBooleanValue( node, "reverse", true );
				int searchStart = getAttributeIntValue( node, "start", 0 );
				int searchLimit = getAttributeIntValue( node, "limit", 1 );
				boolean panic = getAttributeBooleanValue( node, "panic", false );
				if ( searchName == null || searchName.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> requires a name attribute (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchType != null && searchType.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> type attribute, when present, can't be empty (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchStart < 0 )
					throw new IllegalArgumentException( String.format( "<%s> 'start' attribute is not >= 0 (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchLimit < -1 )
					throw new IllegalArgumentException( String.format( "<%s> 'limit' attribute is not >= -1 (%s).", node.getName(), getPathToRoot(node) ) );
				Map<String,String> attrMap = new HashMap<String,String>();
				attrMap.put( "name", searchName );
				LikeFilter searchFilter = new LikeFilter( searchType, attrMap, null );
				List<Element> matchedNodes = new ArrayList<Element>( contextNode.getContent( searchFilter ) );
				if ( searchReverse ) Collections.reverse( matchedNodes );
				if ( searchStart < matchedNodes.size() ) {
					if ( searchLimit > -1 ) {
						matchedNodes = matchedNodes.subList( searchStart, Math.max( matchedNodes.size(), searchStart + searchLimit ) );
					} else if ( searchStart > 0 ) {
						matchedNodes = matchedNodes.subList( searchStart, matchedNodes.size() );
					}
				}
				if ( panic && matchedNodes.isEmpty() )
					throw new NoSuchElementException( String.format( "<%s> was set to require results but found none (%s).", node.getName(), getPathToRoot(node) ) );
				result = matchedNodes;
			}
			else if ( node.getName().equals( "findLike" ) ) {
				String searchType = node.getAttributeValue( "type" );
				boolean searchReverse = getAttributeBooleanValue( node, "reverse", false );
				int searchStart = getAttributeIntValue( node, "start", 0 );
				int searchLimit = getAttributeIntValue( node, "limit", -1 );
				boolean panic = getAttributeBooleanValue( node, "panic", false );
				if ( searchType != null && searchType.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> type attribute, when present, can't be empty (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchStart < 0 )
					throw new IllegalArgumentException( String.format( "<%s> 'start' attribute is not >= 0 (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchLimit < -1 )
					throw new IllegalArgumentException( String.format( "<%s> 'limit' attribute is not >= -1 (%s).", node.getName(), getPathToRoot(node) ) );
				Map<String,String> attrMap = new HashMap<String,String>();
				String searchValue = null;
				Element selectorNode = node.getChild( "selector", modNS );
				if ( selectorNode != null ) {
					for ( Attribute attr : selectorNode.getAttributes() ) {
						if ( attr.getNamespace().equals( Namespace.NO_NAMESPACE ) ) {
							if ( attr.getValue().length() == 0 )
								throw new IllegalArgumentException( String.format( "<%s> attributes, when present, can't be empty (%s).", selectorNode.getName(), getPathToRoot(selectorNode) ) );
							attrMap.put( attr.getName(), attr.getValue() );
						}
					}
					searchValue = selectorNode.getTextTrim();  
					if ( searchValue.length() > 0 ) searchValue = null;
				}
				LikeFilter searchFilter = new LikeFilter( searchType, attrMap, searchValue );
				List<Element> matchedNodes = new ArrayList<Element>( contextNode.getContent( searchFilter ) );
				if ( searchReverse ) Collections.reverse( matchedNodes );
				if ( searchStart < matchedNodes.size() ) {
					if ( searchLimit > -1 ) {
						matchedNodes = matchedNodes.subList( searchStart, Math.max( matchedNodes.size(), searchStart + searchLimit ) );
					} else if ( searchStart > 0 ) {
						matchedNodes = matchedNodes.subList( searchStart, matchedNodes.size() );
					}
				}
				if ( panic && matchedNodes.isEmpty() )
					throw new NoSuchElementException( String.format( "<%s> was set to require results but found none (%s).", node.getName(), getPathToRoot(node) ) );
				result = matchedNodes;
			}
			else if ( node.getName().equals( "findWithChildLike" ) ) {
				String searchType = node.getAttributeValue( "type" );
				String searchChildType = node.getAttributeValue( "child-type" );
				boolean searchReverse = getAttributeBooleanValue( node, "reverse", false );
				int searchStart = getAttributeIntValue( node, "start", 0 );
				int searchLimit = getAttributeIntValue( node, "limit", -1 );
				boolean panic = getAttributeBooleanValue( node, "panic", false );
				if ( searchType != null && searchType.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> type attribute, when present, can't be empty (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchChildType != null && searchChildType.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> child-type attribute, when present, can't be empty (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchStart < 0 )
					throw new IllegalArgumentException( String.format( "<%s> 'start' attribute is not >= 0 (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchLimit < -1 )
					throw new IllegalArgumentException( String.format( "<%s> 'limit' attribute is not >= -1 (%s).", node.getName(), getPathToRoot(node) ) );
				Map<String,String> attrMap = new HashMap<String,String>();
				String searchValue = null;
				Element selectorNode = node.getChild( "selector", modNS );
				if ( selectorNode != null ) {
					for ( Attribute attr : selectorNode.getAttributes() ) {
						if ( attr.getNamespace().equals( Namespace.NO_NAMESPACE ) ) {
							attrMap.put( attr.getName(), attr.getValue() );
						}
					}
					searchValue = selectorNode.getTextTrim();  
					if ( searchValue.length() > 0 ) searchValue = null;
				}
				LikeFilter searchChildFilter = new LikeFilter( searchChildType, attrMap, searchValue );
				WithChildFilter searchFilter = new WithChildFilter( searchType, searchChildFilter );
				List<Element> matchedNodes = new ArrayList<Element>( contextNode.getContent( searchFilter ) );
				if ( searchReverse ) Collections.reverse( matchedNodes );
				if ( searchStart < matchedNodes.size() ) {
					if ( searchLimit > -1 ) {
						matchedNodes = matchedNodes.subList( searchStart, Math.max( matchedNodes.size(), searchStart + searchLimit ) );
					} else if ( searchStart > 0 ) {
						matchedNodes = matchedNodes.subList( searchStart, matchedNodes.size() );
					}
				}
				if ( panic && matchedNodes.isEmpty() )
					throw new NoSuchElementException( String.format( "<%s> was set to require results but found none (%s).", node.getName(), getPathToRoot(node) ) );
				result = matchedNodes;
			}
			else if ( node.getName().equals( "findComposite" ) ) {
				boolean searchReverse = getAttributeBooleanValue( node, "reverse", false );
				int searchStart = getAttributeIntValue( node, "start", 0 );
				int searchLimit = getAttributeIntValue( node, "limit", -1 );
				boolean panic = getAttributeBooleanValue( node, "panic", false );
				if ( searchStart < 0 )
					throw new IllegalArgumentException( String.format( "<%s> 'start' attribute is not >= 0 (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchLimit < -1 )
					throw new IllegalArgumentException( String.format( "<%s> 'limit' attribute is not >= -1 (%s).", node.getName(), getPathToRoot(node) ) );
				Element parNode = node.getChild( "par", modNS );
				if ( parNode == null )
					throw new IllegalArgumentException( String.format( "<%s> requires a <par> tag (%s).", node.getName(), getPathToRoot(node) ) );
				List<Element> matchedNodes = handleModPar( contextNode, parNode );
				if ( searchReverse ) Collections.reverse( matchedNodes );
				if ( searchStart < matchedNodes.size() ) {
					if ( searchLimit > -1 ) {
						matchedNodes = matchedNodes.subList( searchStart, Math.max( matchedNodes.size(), searchStart + searchLimit ) );
					} else if ( searchStart > 0 ) {
						matchedNodes = matchedNodes.subList( searchStart, matchedNodes.size() );
					}
				}
				if ( panic && matchedNodes.isEmpty() )
					throw new NoSuchElementException( String.format( "<%s> was set to require results but found none (%s).", node.getName(), getPathToRoot(node) ) );
				result = matchedNodes;
			}
		}
		return result;
	}

	protected List<Element> handleModFind( Element contextNode, Element node ) {
		List<Element> result = null;
		if ( node.getNamespace().equals( modNS ) ) {
			if ( node.getName().equals( "findName" ) ) {
				String searchName = node.getAttributeValue( "name" );
				String searchType = node.getAttributeValue( "type" );
				boolean searchReverse = getAttributeBooleanValue( node, "reverse", true );
				int searchStart = getAttributeIntValue( node, "start", 0 );
				int searchLimit = getAttributeIntValue( node, "limit", 1 );
				boolean panic = getAttributeBooleanValue( node, "panic", false );
				if ( searchName == null || searchName.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> requires a name attribute (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchType != null && searchType.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> type attribute, when present, can't be empty (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchStart < 0 )
					throw new IllegalArgumentException( String.format( "<%s> 'start' attribute is not >= 0 (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchLimit < -1 )
					throw new IllegalArgumentException( String.format( "<%s> 'limit' attribute is not >= -1 (%s).", node.getName(), getPathToRoot(node) ) );
				Map<String,String> attrMap = new HashMap<String,String>();
				attrMap.put( "name", searchName );
				LikeFilter searchFilter = new LikeFilter( searchType, attrMap, null );
				List<Element> matchedNodes = new ArrayList<Element>( contextNode.getContent( searchFilter ) );
				if ( searchReverse ) Collections.reverse( matchedNodes );
				if ( searchStart < matchedNodes.size() ) {
					if ( searchLimit > -1 ) {
						matchedNodes = matchedNodes.subList( searchStart, Math.max( matchedNodes.size(), searchStart + searchLimit ) );
					} else if ( searchStart > 0 ) {
						matchedNodes = matchedNodes.subList( searchStart, matchedNodes.size() );
					}
				}
				if ( panic && matchedNodes.isEmpty() )
					throw new NoSuchElementException( String.format( "<%s> was set to require results but found none (%s).", node.getName(), getPathToRoot(node) ) );
				result = matchedNodes;
			}
			else if ( node.getName().equals( "findLike" ) ) {
				String searchType = node.getAttributeValue( "type" );
				boolean searchReverse = getAttributeBooleanValue( node, "reverse", false );
				int searchStart = getAttributeIntValue( node, "start", 0 );
				int searchLimit = getAttributeIntValue( node, "limit", -1 );
				boolean panic = getAttributeBooleanValue( node, "panic", false );
				if ( searchType != null && searchType.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> type attribute, when present, can't be empty (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchStart < 0 )
					throw new IllegalArgumentException( String.format( "<%s> 'start' attribute is not >= 0 (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchLimit < -1 )
					throw new IllegalArgumentException( String.format( "<%s> 'limit' attribute is not >= -1 (%s).", node.getName(), getPathToRoot(node) ) );
				Map<String,String> attrMap = new HashMap<String,String>();
				String searchValue = null;
				Element selectorNode = node.getChild( "selector", modNS );
				if ( selectorNode != null ) {
					for ( Attribute attr : selectorNode.getAttributes() ) {
						if ( attr.getNamespace().equals( Namespace.NO_NAMESPACE ) ) {
							if ( attr.getValue().length() == 0 )
								throw new IllegalArgumentException( String.format( "<%s> attributes, when present, can't be empty (%s).", selectorNode.getName(), getPathToRoot(selectorNode) ) );
							attrMap.put( attr.getName(), attr.getValue() );
						}
					}
					searchValue = selectorNode.getTextTrim();  
					if ( searchValue.length() == 0 ) searchValue = null;
				}
				LikeFilter searchFilter = new LikeFilter( searchType, attrMap, searchValue );
				List<Element> matchedNodes = new ArrayList<Element>( contextNode.getContent( searchFilter ) );
				if ( searchReverse ) Collections.reverse( matchedNodes );
				if ( searchStart < matchedNodes.size() ) {
					if ( searchLimit > -1 ) {
						matchedNodes = matchedNodes.subList( searchStart, Math.max( matchedNodes.size(), searchStart + searchLimit ) );
					} else if ( searchStart > 0 ) {
						matchedNodes = matchedNodes.subList( searchStart, matchedNodes.size() );
					}
				}
				if ( panic && matchedNodes.isEmpty() )
					throw new NoSuchElementException( String.format( "<%s> was set to require results but found none (%s).", node.getName(), getPathToRoot(node) ) );
				result = matchedNodes;
			}
			else if ( node.getName().equals( "findWithChildLike" ) ) {
				String searchType = node.getAttributeValue( "type" );
				String searchChildType = node.getAttributeValue( "child-type" );
				boolean searchReverse = getAttributeBooleanValue( node, "reverse", false );
				int searchStart = getAttributeIntValue( node, "start", 0 );
				int searchLimit = getAttributeIntValue( node, "limit", -1 );
				boolean panic = getAttributeBooleanValue( node, "panic", false );
				if ( searchType != null && searchType.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> type attribute, when present, can't be empty (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchChildType != null && searchChildType.length() == 0 )
					throw new IllegalArgumentException( String.format( "<%s> child-type attribute, when present, can't be empty (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchStart < 0 )
					throw new IllegalArgumentException( String.format( "<%s> 'start' attribute is not >= 0 (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchLimit < -1 )
					throw new IllegalArgumentException( String.format( "<%s> 'limit' attribute is not >= -1 (%s).", node.getName(), getPathToRoot(node) ) );
				Map<String,String> attrMap = new HashMap<String,String>();
				String searchValue = null;
				Element selectorNode = node.getChild( "selector", modNS );
				if ( selectorNode != null ) {
					for ( Attribute attr : selectorNode.getAttributes() ) {
						if ( attr.getNamespace().equals( Namespace.NO_NAMESPACE ) ) {
							attrMap.put( attr.getName(), attr.getValue() );
						}
					}
					searchValue = selectorNode.getTextTrim();  
					if ( searchValue.length() == 0 ) searchValue = null;
				}
				LikeFilter searchChildFilter = new LikeFilter( searchChildType, attrMap, searchValue );
				WithChildFilter searchFilter = new WithChildFilter( searchType, searchChildFilter );
				List<Element> matchedNodes = new ArrayList<Element>( contextNode.getContent( searchFilter ) );
				if ( searchReverse ) Collections.reverse( matchedNodes );
				if ( searchStart < matchedNodes.size() ) {
					if ( searchLimit > -1 ) {
						matchedNodes = matchedNodes.subList( searchStart, Math.max( matchedNodes.size(), searchStart + searchLimit ) );
					} else if ( searchStart > 0 ) {
						matchedNodes = matchedNodes.subList( searchStart, matchedNodes.size() );
					}
				}
				if ( panic && matchedNodes.isEmpty() )
					throw new NoSuchElementException( String.format( "<%s> was set to require results but found none (%s).", node.getName(), getPathToRoot(node) ) );
				result = matchedNodes;
			}
			else if ( node.getName().equals( "findComposite" ) ) {
				boolean searchReverse = getAttributeBooleanValue( node, "reverse", false );
				int searchStart = getAttributeIntValue( node, "start", 0 );
				int searchLimit = getAttributeIntValue( node, "limit", -1 );
				boolean panic = getAttributeBooleanValue( node, "panic", false );
				if ( searchStart < 0 )
					throw new IllegalArgumentException( String.format( "<%s> 'start' attribute is not >= 0 (%s).", node.getName(), getPathToRoot(node) ) );
				if ( searchLimit < -1 )
					throw new IllegalArgumentException( String.format( "<%s> 'limit' attribute is not >= -1 (%s).", node.getName(), getPathToRoot(node) ) );
				Element parNode = node.getChild( "par", modNS );
				if ( parNode == null )
					throw new IllegalArgumentException( String.format( "<%s> requires a <par> tag (%s).", node.getName(), getPathToRoot(node) ) );
				List<Element> matchedNodes = handleModPar( contextNode, parNode );
				if ( searchReverse ) Collections.reverse( matchedNodes );
				if ( searchStart < matchedNodes.size() ) {
					if ( searchLimit > -1 ) {
						matchedNodes = matchedNodes.subList( searchStart, Math.max( matchedNodes.size(), searchStart + searchLimit ) );
					} else if ( searchStart > 0 ) {
						matchedNodes = matchedNodes.subList( searchStart, matchedNodes.size() );
					}
				}
				if ( panic && matchedNodes.isEmpty() )
					throw new NoSuchElementException( String.format( "<%s> was set to require results but found none (%s).", node.getName(), getPathToRoot(node) ) );
				result = matchedNodes;
			}
		}
		return result;
	}
