Re: [xsl] CSSXX to XML

Subject: Re: [xsl] CSSXX to XML
From: Emmanuel Bégué <medusis@xxxxxxxxx>
Date: Sun, 31 Mar 2013 22:18:21 +0200
On Sat, Mar 30, 2013 at 8:03 PM, Dorothy Hoskins
<dorothy.hoskins@xxxxxxxxx> wrote:
>
> HI, I have an interesting problem in that I am trying to figure out
> how to load and process a CSS file to grab content from CSS class
> definitions and poke them into XML files.
(...)
> The commonalities of the CSS text are that a
> line which contains "{" has the information I want for the
> class/@element and class/@name.

CSS parsing is difficult; it's usually better to use an existing
library that deals with all the quirks that real-life css can have. In
Python, 'cssutils' is pretty good.

This Python code (10 lines) will do a basic xml encoding of css rules:

# start Python code
import cssutils, gnosis.xml.pickle

css = {}
sheet = cssutils.parseFile("yourcssfile.css")

for rule in sheet:
  if rule.type == rule.STYLE_RULE:
    css[rule.selectorText] = {}
    for property in rule.style:
      css[rule.selectorText][property.name] = property.value

print gnosis.xml.pickle.dumps(css)
# end Python code

When applied to this css:

pre {
    padding: 5px;
    background-color: #eeffcc;
    color: #333333;
    line-height: 120%;
    border: 1px solid #ac9;
    border-left: none;
    border-right: none;
}
tt {
    background-color: #ecf0f3;
    padding: 0 1px 0 1px;
    font-size: 0.95em;
}
th {
    background-color: #ede;
}
.warning tt {
    background: #efc2c2;
}
.note tt {
    background: #d6d6d6;
}
.viewcode-back {
    font-family: sans-serif;
}
div.viewcode-block:target {
    background-color: #f4debf;
    border-top: 1px solid #ac9;
    border-bottom: 1px solid #ac9;
}

It will produce this xml:

<?xml version="1.0"?>
<!DOCTYPE PyObject SYSTEM "PyObjects.dtd">
<PyObject family="obj" type="builtin_wrapper"  class="_EmptyClass">
<attr name="__toplevel__" type="dict" id="3068659748" >
  <entry>
    <key type="string">pre</key>
    <val type="dict" id="3068659068" >
      <entry>
        <key type="string">color</key>
        <val type="string">#333</val>
      </entry>
      <entry>
        <key type="string">border-right</key>
        <val type="string">none</val>
      </entry>
      <entry>
        <key type="string">padding</key>
        <val type="string">5px</val>
      </entry>
      <entry>
        <key type="string">border-left</key>
        <val type="string">none</val>
      </entry>
      <entry>
        <key type="string">border</key>
        <val type="string">1px solid #ac9</val>
      </entry>
      <entry>
        <key type="string">line-height</key>
        <val type="string">120%</val>
      </entry>
      <entry>
        <key type="string">background-color</key>
        <val type="string">#efc</val>
      </entry>
    </val>
  </entry>
  <entry>
    <key type="string">tt</key>
    <val type="dict" id="3068660428" >
      <entry>
        <key type="string">padding</key>
        <val type="string">0 1px 0 1px</val>
      </entry>
      <entry>
        <key type="string">font-size</key>
        <val type="string">0.95em</val>
      </entry>
      <entry>
        <key type="string">background-color</key>
        <val type="string">#ecf0f3</val>
      </entry>
    </val>
  </entry>
  <entry>
    <key type="string">div.viewcode-block:target</key>
    <val type="dict" id="3069557180" >
      <entry>
        <key type="string">border-top</key>
        <val type="string">1px solid #ac9</val>
      </entry>
      <entry>
        <key type="string">background-color</key>
        <val type="string">#f4debf</val>
      </entry>
      <entry>
        <key type="string">border-bottom</key>
        <val type="string">1px solid #ac9</val>
      </entry>
    </val>
  </entry>
  <entry>
    <key type="string">.warning tt</key>
    <val type="dict" id="3069532468" >
      <entry>
        <key type="string">background</key>
        <val type="string">#efc2c2</val>
      </entry>
    </val>
  </entry>
  <entry>
    <key type="string">th</key>
    <val type="dict" id="3069554868" >
      <entry>
        <key type="string">background-color</key>
        <val type="string">#ede</val>
      </entry>
    </val>
  </entry>
  <entry>
    <key type="string">.viewcode-back</key>
    <val type="dict" id="3068661516" >
      <entry>
        <key type="string">font-family</key>
        <val type="string">sans-serif</val>
      </entry>
    </val>
  </entry>
  <entry>
    <key type="string">.note tt</key>
    <val type="dict" id="3068658388" >
      <entry>
        <key type="string">background</key>
        <val type="string">#d6d6d6</val>
      </entry>
    </val>
  </entry>
</attr>
</PyObject>

- - -

It's a really simple start; some things that are easy to improve --
the resulting xml is not very pretty, but that can be improved with
either further XSLT processing ("entry" elements that have
"val[@type='dict']" children are CSSrules; "entry" elements that only
have string vals as children are properties) or a custom XML
serializer (Gnosis is a little antique anyway).

Also, we only retrieve rules and properties from the parsed css, but
there can be many other things (priority, imports, etc. etc.)

The main problem, regarding your requirements, is that css selectors
can be complex, and AFAIK cssutils doesn't parse selector expressions
(it does parse multiple selectors into list of selectors, but not
selector elements into element|class|name|child|descendant etc.)

Hope this helps.

Regards,
Emmanuel BC)guC)


PS: I'm not sure, but I think Saxon-CE directly exposes some css
properties; that may also help?

Current Thread