Search code examples
javahtmlcssjsoup

How to add external CSS to HTML 'style'


How can I convert an external CSS style sheet into the 'style' section of my HTML using Java?

I want to be able to have my external CSS exist in the 'style' section so that I can parse it to inline styles rather than external and the easiest way I have seen to do this is to have the CSS directly in the HTML rather than linked.

I would like to change this in my HTML:

<link rel="stylesheet" href="smartdoc.css" /> 

To this (Ideally by passing the CSS file as an argument for a method):

<style>
    Content from external CSS.
</style>

So that I can apply JSoup to convert it to inline style using something like this:

public static String inlineCss(String html) {
final String style = "style";
Document doc = Jsoup.parse(html);
Elements els = doc.select(style);// to get all the style elements
for (Element e : els) {
  String styleRules = e.getAllElements().get(0).data().replaceAll("\n", "").trim();
  String delims = "{}";
  StringTokenizer st = new StringTokenizer(styleRules, delims);
  while (st.countTokens() > 1) {
    String selector = st.nextToken(), properties = st.nextToken();
    if (!selector.contains(":")) { // skip a:hover rules, etc.
      Elements selectedElements = doc.select(selector);
      for (Element selElem : selectedElements) {
        String oldProperties = selElem.attr(style);
        selElem.attr(style,
            oldProperties.length() > 0 ? concatenateProperties(
                oldProperties, properties) : properties);
      }
    }
  }
  e.remove();
}
return doc.toString();
}

private static String concatenateProperties(String oldProp, @NotNull String newProp) {
oldProp = oldProp.trim();
if (!oldProp.endsWith(";"))
  oldProp += ";";
return oldProp + newProp.replaceAll("\\s{2,}", " ");
}

Any suggestions for this?


Solution

  • I assume that all your files are on a local hard drive encoded in UTF-8.

    dummy.html

    <link rel="stylesheet" href="smartdoc.css" />
    

    smartdoc.css

    a {
      background-color: red;
    }
    
    p {
      background-color: green;
    }
    

    SAMPLE CODE

    To replace the link node with the CSS file content, do the following:

    // Load HTML file
    String charsetName = "UTF-8";
    Document doc = Jsoup.parse(new File("dummy.html"), charsetName);
    System.out.println("BEFORE:\n" + doc.outerHtml());
    
    // Replace each link nodes with its respective CSS file content
    for (Element link : doc.select("link[rel=stylesheet]")) {
        String cssFilename = link.attr("href");
    
        Element style = new Element(Tag.valueOf("style"), "");
        style.appendText("/* " + cssFilename + " */");
        style.appendText(loadCssFileContent(cssFilename, charsetName));
    
        link.replaceWith(style);
    }
    
    System.out.println("\nAFTER:\n" + doc.outerHtml());
    
    private static String loadCssFileContent(String path, String charsetName) throws IOException {
        byte[] encoded = Files.readAllBytes(Paths.get(path));
        return new String(encoded, charsetName);
    }
    

    OUTPUT

    BEFORE:
    <html>
     <head>
      <link rel="stylesheet" href="smartdoc.css">
     </head>
     <body></body>
    </html>
    
    AFTER:
    <html>
     <head>
      <style>/* smartdoc.css */a { background-color: red; } p { background-color: green; }</style>
     </head>
     <body></body>
    </html>