package com.ramussoft.report.html; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import java.util.Vector; import net.htmlparser.jericho.HTMLElementName; import net.htmlparser.jericho.Segment; import net.htmlparser.jericho.Source; import net.htmlparser.jericho.StartTag; public class Style { /** * Клас, що відповідає за назву новостворених стилів, після генерації нової * сторінки. * * @author Яковчук В.В. */ public static class Counter { private int c = 0; public String next() { c++; return "rsfc" + c; } } ; public static Counter createCounter() { return new Counter(); } /** * Метод додає нові стилі з унікальними назвами (якщо в унікальності є * необхідність). * * @param text Текст, з якого будуть братись нові стилі. * @param currents Набір поточних стилів, які будуть додані. * @param counter об’єкт, який відповідає за назву новостворених стилів. * @return Набір правил, за якими мають замінятись всі теги та їх значення. */ public static Vector<ReplaceRight> getStyles(final String text, final Vector<Style> currents, final Counter counter) { int i = 0; final StyleParser parser = new StyleParser(); parser.parse(text); final Vector<Style> add = parser.getStyles(); final Vector<ReplaceRight> result = new Vector<ReplaceRight>(); for (i = 0; i < add.size(); i++) { final Style added = add.get(i); added.replaceRights(result); Style present = null; for (int j = 0; j < currents.size(); j++) { final Style c = currents.get(j); if (c.equals(added) && !c.isStyled()) { present = c; break; } } if (present != null) { final StyleHead[] hs = added.getHeads(); for (final StyleHead h : hs) { createRight(result, h, added, counter); present.addHead(h); } } else { final StyleHead[] hs = added.getHeads(); for (final StyleHead h : hs) { createRight(result, h, added, counter); } currents.add(added); } } return result; } private static void createRight(final Vector<ReplaceRight> heads, final StyleHead oldHead, final Style style, final Counter counter) { if (oldHead.getParent() != null) return; final ReplaceRight h = new ReplaceRight(); heads.add(h); final String cl = counter.next(); if (oldHead.isStyled()) { h.setNewName(oldHead.getName().substring(1)); h.setNewType(cl); if (!oldHead.isDefault()) { h.setOldType(oldHead.getType()); } else h.setDefault(true); oldHead.setType(cl); h.setStyle(style); } else { h.setTag(oldHead.getTag()); h.setNewName(cl); if (!oldHead.isDefault()) { h.setOldName(oldHead.getName()); } else h.setDefault(true); oldHead.setName(cl); } } private static class StyleParser { private boolean isTagComment; private boolean isTag; private int isComment; private final Vector<Style> styles = new Vector<Style>(); private Style style; private String head; private boolean isHead; private boolean isBody; private boolean isName; private boolean isValue; private boolean isL; private boolean isL1; private String value; private String name; private boolean isS; private String bHead; public StyleParser() { super(); isTagComment = false; isComment = 0; isTag = false; head = ""; isHead = false; isBody = false; addStyle(); } public void parse(final String text) { final int l = text.length(); for (int i = 0; i < l; i++) parse(text.charAt(i)); initStyles(); } private boolean isBed(final StyleHead head) { final String name = head.toString(); for (int i = 0; i < name.length(); i++) { final char c = name.charAt(i); if (c == '>' || c == '<') return true; } return false; } private boolean isStyleBed(final Style style) { final Vector<StyleHead> v = new Vector<StyleHead>(style.heads); for (int i = 0; i < v.size(); i++) { if (isBed(v.get(i))) style.heads.remove(v.get(i)); } return style.heads.size() == 0; } private void addStyle() { if (bHead != null) { style.addHead(bHead); bHead = null; } if (style != null) { if (isStyleBed(style)) styles.remove(style); } style = new Style(); styles.add(style); } private void parse(final char c) { if (!isBody && c == '<') { isTag = true; return; } if (isTag) { if (c == '!') { isTagComment = true; isTag = false; return; } isTag = false; } if (isTagComment) { if (c == '-') return; isTagComment = false; } if (isComment > 0) { if (isComment == 1) { if (c == '*') { isComment = 2; return; } else if (c == '/') { isComment = 3; return; } else isComment = 0; } else if (isComment == 2) { if (c == '*') isComment = 4; return; } else if (isComment == 3) { if (c == '\n') { isComment = 0; } return; } else if (isComment == 4) { if (c == '/') isComment = 0; return; } } else if (!isBody && c == '/') { isComment = 1; return; } if (isBody) { if (isName) { if (isP(c)) return; if (c != ':') name += c; else { isValue = true; value = ""; isL = false; isL1 = false; isName = false; } } else if (isValue) { if (isL) { if (c == '\"') isL = false; } else if (isL1) { if (c == '\'') isL1 = false; } else if (c == '\'') isL1 = true; else if (c == '\"') isL = true; else if (c == ';') { addAttribute(); isValue = false; return; } else if (c == '}') { addAttribute(); isValue = false; isBody = false; addStyle(); return; } value += c; } else { if (isP(c)) return; if (c == '}') { isBody = false; addStyle(); return; } isName = true; name += c; } return; } if (!isHead) { if (isP(c)) { if (c == ',') isS = true; return; } if (c != '{') { head += c; isHead = true; } } else { if (isP(c) || c == '{') { if (c == ',') isS = true; isHead = false; addHead(); } else head += c; } if (c == '{') { isBody = true; isName = false; isValue = false; name = ""; value = ""; isS = false; } } private void addAttribute() { style.addAttribute(name, value); name = ""; value = ""; } private void addHead() { if (bHead != null) { if (!isS) { bHead += " " + head; style.addHead(bHead); bHead = null; } else { style.addHead(bHead); bHead = head; } } else bHead = head; head = ""; } private boolean isP(final char c) { return c == '\n' || c == '\r' || c == '\f' || c == '\t' || c == ',' || c == ' '; } private void initStyles() { if (bHead != null) { style.addHead(bHead); bHead = null; } if (style != null) { if (isStyleBed(style)) styles.remove(style); style = null; } for (int i = 0; i < styles.size(); i++) { final Style s = styles.get(i); StyleHead h = null; for (int j = 0; j < s.heads.size(); j++) { if (s.heads.get(j).isStyled()) { h = s.heads.get(j); break; } } if (h != null && h.getPrefix() == null) { for (int j = 0; j < styles.size(); j++) { final Style s1 = styles.get(j); StyleHead h1 = null; for (int k = 0; k < s1.heads.size(); k++) if (s1.heads.get(k).isStyled()) { h1 = s1.heads.get(k); break; } if (h1 != null && h1.getPrefix() != null && h1.getType().equalsIgnoreCase(h.getType())) { h1.setParent(h); } } } } } public Vector<Style> getStyles() { return styles; } } ; private final Vector<Attribute> attributes = new Vector<Attribute>(); private final Vector<StyleHead> heads = new Vector<StyleHead>(); private final Vector<Style> childs = new Vector<Style>(); /** * Повертає набір елементів, для яких застосовується даний стиль. * * @return Масив елементів, для яких застосовується даний стиль. */ public StyleHead[] getHeads() { final StyleHead[] res = new StyleHead[heads.size()]; for (int i = 0; i < res.length; i++) res[i] = heads.get(i); return res; } public void addAttribute(final String name, final String value) { attributes.add(new Attribute(name, value)); } private void addHead(final String head) { addHead(new StyleHead(head)); } private void addHead(final StyleHead head) { heads.add(head); } private class Attribute { public String name; public String value; public Attribute(final String name, final String value) { this.name = name; this.value = value; } public Attribute(final Attribute a) { value = a.value; name = a.name; } public Attribute(final String string) { final StringTokenizer st = new StringTokenizer(string, ":"); name = st.nextToken().trim(); if (st.hasMoreElements()) { value = st.nextToken(); } else value = ""; } @Override public String toString() { return "\t" + name + ":" + value + ";"; } } ; @Override public String toString() { String res = ""; for (int i = 0; i < heads.size(); i++) { final StyleHead head = heads.get(i); if ("".equals(res)) res += head.toString(); else res += ", " + head.toString(); } res += "\n{\n"; for (int i = 0; i < attributes.size(); i++) { final Attribute a = attributes.get(i); res += a.toString() + "\n"; } res += "}\n"; for (int i = 0; i < childs.size(); i++) { } return res; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((attributes == null) ? 0 : attributes.hashCode()); return result; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof Style)) return false; Style other = (Style) obj; if (attributes == null) { if (other.attributes != null) return false; } else if (!attributes.equals(other.attributes)) return false; return true; } /** * Метод перевіряє, чи може мати тег стиль. * * @param tag Тег, для якого буде здійснена перевірка. * @return <code>true</code>, якщо тег може мати стиль, <code>false</code>, * якщо тег не може мати свій стиль. */ public static boolean isStyledTag(final String tag) { return true; } public void replaceRights(final Vector<ReplaceRight> rights) { for (int i = 0; i < rights.size(); i++) { final ReplaceRight right = rights.get(i); if (right.isStyled()) { Attribute atr = null; for (int j = 0; j < attributes.size(); j++) { final Attribute a = attributes.get(j); if (a.name.equalsIgnoreCase(right.getNewName())) { atr = a; } } if (right.isDefault()) { if (atr == null) { addDefAttr(right); } } else { if (atr != null) { if (atr.value.equals(right.getOldType())) atr.value = right.getNewType(); } } } } } private void addDefAttr(final ReplaceRight right) { final Style s = right.getStyle(); for (int i = 0; i < s.attributes.size(); i++) { final Attribute a = s.attributes.get(i); boolean have = false; for (int j = 0; j < attributes.size(); j++) { final Attribute a1 = attributes.get(j); if (a.name.equals(a1.name)) { have = true; break; } } if (!have) attributes.add(new Attribute(a)); } } private boolean isStyled() { for (int i = 0; i < heads.size(); i++) { if (heads.get(i).isStyled()) return true; } return false; } public Style(final String attr) { super(); if (attr == null) return; if ("".equals(attr)) return; final StringTokenizer st = new StringTokenizer(attr, ";"); while (st.hasMoreElements()) { attributes.add(new Attribute(st.nextToken())); } } private Style() { super(); } public int getAttributeCount() { return attributes.size(); } public String toAttributeValue() { final StringBuffer sb = new StringBuffer(); for (int i = 0; i < attributes.size(); i++) { final Attribute a = attributes.get(i); sb.append(a.name); sb.append(':'); sb.append(a.value); sb.append(';'); } return sb.toString(); } public static void main(final String[] args) { try { final FileInputStream is = new FileInputStream("d:/test.html"); final FileOutputStream o = new FileOutputStream("d:/res1.txt"); final Source source = new Source(is); final List<StartTag> list = source .getAllStartTags(HTMLElementName.STYLE); final Iterator<StartTag> iterator = list.iterator(); String text = ""; final PrintStream out = new PrintStream(o); while (iterator.hasNext()) { final StartTag tag = iterator.next(); final Segment s = new Segment(source, tag.getEnd(), tag .getElement().getEndTag().getBegin()); text += s.toString(); // out.println(text); // out.println("---------------"); } is.close(); final Vector<Style> styles = new Vector<Style>(); getStyles(text, styles, createCounter()); for (int i = 0; i < styles.size(); i++) { out.println(styles.get(i)); } o.close(); } catch (final IOException e) { e.printStackTrace(); } } }