package com.dteviot.epubviewer.XmlFilter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.XMLFilterImpl;
import com.dteviot.epubviewer.IResourceSource;
import com.dteviot.epubviewer.ResourceResponse;
import com.dteviot.epubviewer.XmlUtil;
import android.net.Uri;
/*
* Convert style sheet link elements to in-line style elements
*/
public class StyleSheetElementFilter extends XMLFilterImpl{
private static final String LINK_ELEMENT_NAME = "link";
private static final String STYLE_ELEMENT_NAME = "style";
private static final String ATTRIBUTE_REL = "rel";
private static final String ATTRIBUTE_HREF = "href";
private static final String ATTRIBUTE_TYPE = "type";
private static final String ATTRIBUTE_VALUE_TEXT_CSS = "text/css";
private static final String ATTRIBUTE_URI = "";
private static final String ATTRIBUTE_CDATA = "CDATA";
private static final String STYLESHEET_REL = "stylesheet";
private IResourceSource mSource;
private Uri mUri;
private boolean mReplacingElement = false;
/*
* @param uri of the XML document being processed (used to resolve links)
* @param source to fetch data from
*/
public StyleSheetElementFilter(Uri sourceUri, IResourceSource source) {
mSource = source;
mUri = sourceUri;
}
@Override
public void startElement(String namespaceURI, String localName,
String qualifiedName, Attributes attrs) throws SAXException {
if (!localName.equals(LINK_ELEMENT_NAME)) {
super.startElement(namespaceURI, localName, qualifiedName, attrs);
} else if (isStyleSheet(attrs)) {
String href = XmlUtil.getAttributesValue(attrs, ATTRIBUTE_HREF);
String styleSheet = fetchStyleSheet(href);
if (!styleSheet.isEmpty()) {
mReplacingElement = true;
createStyleElement(namespaceURI, styleSheet);
}
}
}
@Override
public void endElement(String namespaceURI, String localName,
String qualifiedName) throws SAXException {
if (!localName.equals(LINK_ELEMENT_NAME)) {
super.endElement(namespaceURI, localName, qualifiedName);
} else if (mReplacingElement) {
super.endElement(namespaceURI, STYLE_ELEMENT_NAME, STYLE_ELEMENT_NAME);
mReplacingElement = false;
}
}
private void createStyleElement(String namespaceURI, String styleSheet)
throws SAXException {
AttributesImpl newAttrs = new AttributesImpl();
newAttrs.addAttribute(ATTRIBUTE_URI, ATTRIBUTE_TYPE, ATTRIBUTE_TYPE,
ATTRIBUTE_CDATA, ATTRIBUTE_VALUE_TEXT_CSS);
super.startElement(namespaceURI, STYLE_ELEMENT_NAME,
STYLE_ELEMENT_NAME, newAttrs);
// now write the style sheet
char[] text = styleSheet.toCharArray();
super.characters(text, 0, text.length);
}
private String fetchStyleSheet(String relativeUri) {
StringBuffer sb = new StringBuffer();
try {
Uri resourceUri = XmlUtil.resolveRelativeUri(mUri, relativeUri);
ResourceResponse response = mSource.fetch(resourceUri);
if (response != null)
{
try {
InputStreamReader isr =
new InputStreamReader(response.getData(), "UTF-8");
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append('\n');
}
} finally {
response.getData().close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
private boolean isStyleSheet(Attributes attrs) {
String relAttribute = XmlUtil.getAttributesValue(attrs, ATTRIBUTE_REL);
return (relAttribute != null) &&
(STYLESHEET_REL.compareToIgnoreCase(relAttribute) == 0);
}
}