あー……なんだか,最近忙しいもんで,なかなか自前のモノを作る機会がありません。……とか,言っていてもどうにもならないので,一応,昨日書いた,CSS 作りの道具を上げてみます。てか,骨組みしかないし……。
ソースは後掲を参照してもらうとして,コンパイルはこんな風にします(ファイル名は style.c)。コンパイルするには,LibXML2 が必要なので,適宜インストールしてからビルドすることになります。あとは,聞くまでもないですけど,当然,UN*X 環境ですよね?うちでは FreeBSD 6.1R で動かしました。
% cc style.c `xml2-config --cflags` `xml2-config --libs` -o style
どうやって使うかというと,こんな風に XHTML を食べさせます。標準出力に CSS の雛形が出力されるという寸法です。
% ./style sample.html
sample.html は,XML を使っていることが前提になっているので,XHTML に準拠した HTML を書いてください。id や class なんかをボチボチ見ながら,それっぽく読んで,その HTML に必要そうな CSS の雛形をそれっぽく出力してくれます(あくまでもそれっぽく)。
そういうわけで,ソースはこちら。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/xmlstring.h>
static void
printSelector(const xmlNodePtr cur)
{
xmlChar *xmlString = NULL;
printf("%s", cur->name);
if ((xmlString = xmlGetProp(cur, "id")) != NULL) {
printf("#%s", xmlString);
xmlFree(xmlString);
xmlString = NULL;
}
if ((xmlString = xmlGetProp(cur, "class")) != NULL) {
printf(".%s", xmlString);
xmlFree(xmlString);
xmlString = NULL;
}
printf(" ");
return;
}
static void
printDefaultProp(void)
{
puts(" margin : ");
puts(" padding : ");
puts(" border : ");
puts(" background : ");
puts(" font : ");
return;
}
static void
printElementStyles(const xmlNodePtr parent)
{
xmlNodePtr cur = NULL;
for (cur = parent; cur != NULL; cur = cur->next) {
if (cur->type == XML_ELEMENT_NODE) {
printSelector(cur);
puts("{");
printDefaultProp();
puts("}");
}
printElementStyles(cur->children);
}
return;
}
static xmlNodePtr
getElementByName(const xmlNodePtr parent, const xmlChar *name)
{
xmlNodePtr cur = NULL;
xmlNodePtr ret = NULL;
for (cur = parent; cur != NULL; cur = cur->next) {
if (cur->type == XML_ELEMENT_NODE &&
xmlStrcmp(name, cur->name) == 0) {
ret = cur;
break;
}
ret = getElementByName(cur->children, name);
}
return ret;
}
int
main(int argc, char *argv[])
{
xmlDocPtr doc = NULL;
xmlNodePtr root = NULL;
xmlNodePtr cur = NULL;
if (argc < 2) {
fprintf(stderr, "arg error\n");
exit(-1);
}
doc = xmlParseFile(argv[1]);
root = xmlDocGetRootElement(doc);
if (root == NULL) {
fprintf(stderr, "parse error\n");
exit(-1);
}
cur = getElementByName(root, "body");
printElementStyles(cur);
xmlFreeDoc(doc);
xmlCleanupParser();
return 0;
}
普通に DOM ツリーを走査しているだけなので,あまり難しいことはしていません。てか,Perl なんかで書いた方が楽だったかも。
ソースは昨日書いたままイヂッテないので,今日考えたあれこれは,これからボチボチ作っていこうと思います。けど,なんだか,「道具作ってる暇があるならモノを作れ」な感じになっているような,いないような……。