cssutils - CSS Cascading Style Sheets parser and library for Python

A Python package to parse and build CSS Cascading Style Sheets. Currently a DOM only, no rendering options.

cssutils is licensed under the LGPL 3, see http://www.gnu.org/licenses.

links

kind request

cssutils is far from being perfect or even complete. If you find any bugs (especially specification violations) or have problems or suggestions please create a new issue.

examples

parsing

command line

Simplest way to validate a given stylesheet may be to use the command line script cssparse-script.py (or cssparse.exe in PYTHONHOME/Scripts/) which simply prints the given stylesheet(s) or string to stdout and reports logging information to stderr . Effectively all input stylesheets are concanated if stdout is redirected.

> cssparse-script.py --help
Usage: cssparse-script.py [options] filename1.css [filename2.css ...]
[>filename_combined.css] [2>parserinfo.log]

Options:
-h, --help            show this help message and exit
-e ENCODING, --encoding=ENCODING
encoding of the file
-d, --debug           activate debugging output
-m, --minify          minify parsed CSS
-s, --string          parse given string
  
example

In the following example unknown CSS2 properties are reported on the INFO level, invalid CSS2 property values as a WARNING. Nevertheless all properties are kept given they are syntactically correct. Empty rules are omitted, in this case the third rule is not empty as it contains a comment.

> cssparse -s "a{color:red;top:2px;left:red;x:1}b{}c{/*empty*/}"
WARNING CSSValue: Invalid value for CSS2 property u'left': u'red'
INFO    Property: No CSS2 Property: u'x'. [1:30: x]
a {
color: red;
top: 2px;
left: red;
x: 1
}
c {
/*empty*/
}
  

Or with option --minify :

> cssparse -sm "a{color:red;top:2px;left:red;x:1}b{}c{/*empty*/}"
WARNING CSSValue: Invalid value for CSS2 property u'left': u'red'
INFO    Property: No CSS2 Property: u'x'. [1:30: x]
a{color:red;top:2px;left:red;x:1}
  

programmatically

To parse an existing stylesheet (string, file or URL) and work with the resulting CSSStyleSheet object use cssutils.CSSParser or the helper functions in the cssutils package. cssutils.parseFile(filename, encoding=None) for example parses a given file. The encoding defaults to UTF-8, encoding found in @charset rules or a BOM is used.

example
>>> import cssutils
>>> sheet = cssutils.parseString('@import url(example.css); body { color: red }')
WARNING [Error 2] The system cannot find the file specified: u'I:\\...\\example.css'
WARNING CSSImportRule: While processing imported style sheet href=u'example.css': IOError('Cannot read Stylesheet or it is empty.',)
>>> print sheet.cssText
@import url(example.css);
body {
color: red
}
  

Resolving of imports may be customized. In the above example example.css cannot be read as in the current context (which is os.getcwd()( since 0.9.5b3) the file is not present. For details about customizing the URL fetching please see the docs.

error logging

The log of the cssutils parser may be configured (or replaced completely which should seldom be needed though).

>>> import logging, StringIO, cssutils
>>> mylog = StringIO.StringIO()
>>> h = logging.StreamHandler(mylog)
>>> h.setFormatter(logging.Formatter('%(levelname)s %(message)s'))
>>> cssutils.log.addHandler(h)
>>> cssutils.log.setLevel(logging.INFO)
>>> sheet = cssutils.parseString('a { x: 1; } @import "http://example.com/x";')
>>> print mylog.getvalue()
INFO Property: No CSS2 Property: u'x'. [1:5: x]
WARNING HTTPError opening url=u'http://example.com/x': 404 Not Found
WARNING CSSImportRule: While processing imported style sheet href=u'http://example.com/x': IOError('Cannot read Stylesheet.',)
ERROR CSSStylesheet: CSSImportRule not allowed here. [1:13: @import]
  

serializing

cssutils uses a global serializer. To adjust the default serializer change the preferences via attribute cssutils.ser.prefs .
(You may use your own serializer which must implement cssutils.CSSSerializer by setting it via cssutils.setSerializer(newserializer) . The preferences available should suffice for most cases though.)

Quite a few preference options are available, for more details see the docs:

>>> css = '@import "example.css"; body { color: red }'
>>> sheet = cssutils.parseString(css)
>>> cssutils.ser.prefs.indent = 2*' '
>>> # used to set indentation string, default is 4*' '
>>> cssutils.ser.prefs.importHrefFormat = 'uri'
>>> # or 'string', defaults to the format used in parsed stylesheet
>>> cssutils.ser.prefs.lineNumbers = True
>>> print sheet.cssText
1: @import url(example.css);
2: body {
3:   color: red
4:   }
  

work with or build a new CSSStyleSheet

To build a new CSS stylesheet from scratch use the classes in packages cssutils.css and cssutils.stylesheets . Some simple examples:

>>> from cssutils import css, stylesheets
>>> sheet = css.CSSStyleSheet()
>>> sheet.cssText = u'@import url(example.css) tv;'
>>> print sheet.cssText
@import url(example.css) tv;
>>> style = css.CSSStyleDeclaration()
>>> style['color'] = 'red' # until 0.9.5: setProperty(u'color', u'red')
>>> stylerule = css.CSSStyleRule(selectorText=u'body', style=style)
>>> sheet.add(stylerule) # use this from 0.9.5 which always succeeds
1
>>> # OR THIS IS THE OFFICIAL DOM METHOD IF YOU WANT TO USE IT:
>>> # sheet.insertRule(stylerule, 0) # try before @import
>>> # xml.dom.HierarchyRequestErr: CSSStylesheet: Found @charset, @import or @namespace before index 0.
>>> # sheet.insertRule(stylerule) # at end of rules, returns index
>>> print sheet.cssText
@import url(example.css) tv;
body {
color: red
}
>>> # returns if new Medium is wellformed and has been added
>>> sheet.cssRules[0].media.appendMedium('print')
True
>>> # returns the new Selector:
>>> sheet.cssRules[1].selectorList.appendSelector('a')
cssutils.css.Selector(selectorText=u'a')
>>> print sheet.cssText
@import url(example.css) tv, print;
body, a {
color: red
}