Home Contact Me Tutorials

Parsing CSS with SAC and Java

Contents

Introduction

This is a simple example on how to get started parsing CSS using Java and the Simple API for CSS (SAC). The SAC website actually provides a Java program (DemoSAC.java) that supposedly demonstrates this functionality but I was unable to compile it out of the box. I got quite a few compilation errors. Most of these errors were caused by missing methods that were actually required to be implemented by the DemoSAC class.

I finally did manage to get it running after spending some time making modifications to the original source, and tracking down the JAR files the program depended on. The example provided in this tutorial is the one I got to run.

Eclipse Project

You can download my modified version using the following link. It's a ZIP file containing

Download SACExample.zip

Source Listing for Modified DemoSAC.java

Source code of my modified version of DemoSAC.java. The original can be found here. Basically what the program does is to take a CSS file that is passed to it and print out the number of CSS properties it finds in each CSS ruleset.

package com.windrealm;

import org.w3c.css.sac.*;
import org.w3c.css.sac.helpers.*;
import java.net.*;
import java.io.*;

/**
 * <p>
 * This example count the number of property in the style rules (outside a media
 * rule).
 * </p>
 * <p>
 * This class is based on the DemoSAC.java found <a
 * href="http://www.w3.org/TR/SAC/">on this page</a>. The original example did
 * not compile out of the box for me, and I had to made some modifications. This
 * class is the modified version.
 * </p>
 * <p>
 * This class needs 2 JAR files to compile properly: sac.jar and flute.jar. Both
 * files can be downloaded from <a href="http://www.w3.org/Style/CSS/SAC/">the
 * SAC website</a>.
 * </p>
 * 
 * @author Andrew Lim Chong Liang
 */
public class DemoSAC implements DocumentHandler {
  boolean inMedia = false;
  boolean inStyleRule = false;
  int propertyCounter = 0;

  public void startMedia(SACMediaList media) throws CSSException {
    inMedia = true;
  }

  public void endMedia(SACMediaList media) throws CSSException {
    inMedia = false;
  }

  public void startSelector(SelectorList patterns) throws CSSException {
    if (!inMedia) {
      inStyleRule = true;
      propertyCounter = 0;
    }
  }

  public void endSelector(SelectorList patterns) throws CSSException {
    if (!inMedia) {
      System.out.println("Found " + propertyCounter + " properties.");
    }
    inStyleRule = false;

  }

  public void property(String name, LexicalUnit value, boolean important)
      throws CSSException {
    if (inStyleRule) {
      propertyCounter++;
    }
  }

  public static void main(String[] args) throws Exception {
    System.setProperty("org.w3c.css.sac.parser", "org.w3c.flute.parser.Parser");

    InputSource source = new InputSource();
    URL uri = new URL("file", null, -1, args[0]);
    InputStream stream = uri.openStream();

    source.setByteStream(stream);
    source.setURI(uri.toString());
    ParserFactory parserFactory = new ParserFactory();
    Parser parser = parserFactory.makeParser();

    parser.setDocumentHandler(new DemoSAC());
    parser.parseStyleSheet(source);
    stream.close();
  }

  public void startFontFace() {
  }

  public void endFontFace() {
  }

  public void startPage(String name, String pseudoPage) {
  }

  public void endPage(String name, String pseudoPage) {
  }

  public void importStyle(String uri, SACMediaList media,
      String defaultNamespaceURI) {
  }

  public void namespaceDeclaration(String prefix, String uri) {
  }

  public void ignorableAtRule(String atRule) {
  }

  public void comment(String text) {
  }

  public void startDocument(InputSource source) {
  }

  public void endDocument(InputSource source) {
  }
}

Sample CSS Input and Output

Given a CSS file with the following contents:

body {
  width: 100% ;
}

redText {
  color: red ;
  font-weight: bold ;
}

The program will output:

Found 1 properties.
Found 2 properties.