public final void endElement(
        final String ns,
        final String lName,
        final String qName) throws SAXException
    {
        // the actual element name is either in lName or qName, depending
        // on whether the parser is namespace aware
        String name = lName == null || lName.length() == 0 ? qName : lName;

        // Fire "end" events for all relevant rules in reverse order
        Rule r = (Rule) RULES.match(match);
        if (r != null) {
            r.end(name);
        }

        // Recover the previous match expression
        int slash = match.lastIndexOf('/');
        if (slash >= 0) {
            match = match.substring(0, slash);
        } else {
            match = "";
        }
    }