001 package fi.iki.hsivonen.xml;
002
003 import java.util.Arrays;
004
005 import org.xml.sax.Attributes;
006 import org.xml.sax.SAXException;
007
008 import gnu.xml.pipeline.EventConsumer;
009 import gnu.xml.pipeline.EventFilter;
010
011 public class HeadingShiftFilter extends EventFilter {
012
013 /**
014 * The XHTML namespace URI
015 */
016 private final static String XHTML_NS = "http://www.w3.org/1999/xhtml";
017
018 private static String[] HEADINGS = {
019 "h1",
020 "h2",
021 "h3",
022 "h4",
023 "h5",
024 "h6"
025 };
026
027 private static String[] HEADING_TARGETS = {
028 "h1",
029 "h1",
030 "h1",
031 "h1",
032 "h1",
033 "h1",
034 "h2",
035 "h3",
036 "h4",
037 "h5",
038 "h6",
039 "h6",
040 "h6",
041 "h6",
042 "h6",
043 "h6"
044 };
045
046 private int offset;
047
048 public HeadingShiftFilter(EventConsumer next, int offset) {
049 super(next);
050 setContentHandler(this);
051 if (offset > 5 || offset < -5) {
052 throw new IllegalArgumentException("Offset out of range.");
053 }
054 this.offset = offset;
055 }
056
057 private String mapName(String name) {
058 int i = Arrays.binarySearch(HEADINGS, name);
059 if (i < 0) {
060 return name;
061 } else {
062 return HEADING_TARGETS[5 + i + offset];
063 }
064 }
065
066 /**
067 * @see gnu.xml.pipeline.EventFilter#endElement(java.lang.String, java.lang.String, java.lang.String)
068 */
069 public void endElement(String ns, String local, String q) throws SAXException {
070 if (XHTML_NS.equals(ns)) {
071 local = mapName(local);
072 }
073 super.endElement(ns, local, local);
074 }
075
076 /**
077 * @see gnu.xml.pipeline.EventFilter#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
078 */
079 public void startElement(String ns, String local, String q, Attributes attrs) throws SAXException {
080 if (XHTML_NS.equals(ns)) {
081 local = mapName(local);
082 }
083 super.startElement(ns, local, local, attrs);
084 }
085
086 }