[libcroco-list] new example



hi there,

in an attempt to familiarize myself with libcroco,
I wrote a new example, which reports all properties
for a given node.
In the hope that it may be useful, may be even serve
for unit testing, I'm posting it here. Feel free to
include it into the repository.

It is run as

./report report.xml report.css <xpath expression>

and it will report the properties that apply for
the first matching node. The node path is reported
for convenience.

With a variety of documents and stylesheets it
can be used to test the selection mechanism of
libcroco.

Regards,
		Stefan

PS: It is written with release 0.3, in case it needs
    some adjustments for the latest CVS...
/**
 * This example looks up a node from a document with an
 * xpath expression, then reports all properties that apply
 * from a given stylesheet.
 *
 * To compile it using gcc, type
 *
 * gcc `croco-config --cflags`  `croco-config --libs` -o report report.c
 *
 * @author Stefan Seefeld <seefeld sympatico ca>
 */

#include <libcroco.h>
#include <libxml/tree.h>
#include <libxml/xpath.h>

void usage_and_exit(char *progname)
{
  fprintf(stderr, "Usage: %s <xml doc> <stylesheet> <xpath>\n", progname);
  exit(-1);
}

struct workspace
{
  xmlDoc *document;
  xmlXPathContext *xpath; 
  xmlXPathObject *result; 
  CRStyleSheet *stylesheet;
  CRCascade *cascade;
  CRSelEng *selector;
};

// construct workspace members in order...
//
// return 0 on success and -1 on error
//
int init(struct workspace *ws, char **args)
{
  short i = 0;
  enum CRStatus status = CR_OK;

  ws->document = 0;
  ws->xpath = 0;
  ws->result = 0;
  ws->stylesheet = 0;
  ws->cascade = 0;
  ws->selector = 0;


  ws->document = xmlParseFile(args[0]);
  if (!ws->document)
  {
    fprintf(stderr, "could not parse the document %s", args[0]);
    return -1;
  }
  ws->xpath = xmlXPathNewContext(ws->document);
  if (!ws->xpath)
  {
    fprintf(stderr, "Error: unable to create new XPath context\n");
    return -1;
  }
  ws->result = xmlXPathEvalExpression((xmlChar *)args[2], ws->xpath);
  if (!ws->result)
  {
    fprintf(stderr, "Error: unable to evaluate xpath expression\n");
    return -1;
  }
  if (ws->result->type != XPATH_NODESET || !ws->result->nodesetval)
  {
    fprintf(stderr, "Error: xpath does not evaluate to a node set\n");
    return -1;
  }

  status = cr_om_parser_simply_parse_file(args[1] /*sheet*/,
                                          CR_ASCII /*the encoding*/,
                                          &ws->stylesheet);
  if (status != CR_OK || !ws->stylesheet)
  {
    fprintf(stderr, "could not parse the stylesheet %s", args[1]);
    return -1;
  }
  ws->cascade = cr_cascade_new(ws->stylesheet, 0, 0);
  ws->selector = cr_sel_eng_new();
}

// ...and destruct in reverse order
void fini(struct workspace *ws)
{
  if (ws->selector) cr_sel_eng_destroy(ws->selector);
  if (ws->cascade) cr_cascade_destroy(ws->cascade);
  if (ws->stylesheet) cr_stylesheet_destroy(ws->stylesheet);
  if (ws->result) xmlXPathFreeObject(ws->result);
  if (ws->xpath) xmlXPathFreeContext(ws->xpath); 
  if (ws->document) xmlFreeDoc(ws->document);
}

void print_property(gpointer name, gpointer decl, gpointer data)
{
  CRDeclaration *declaration = (CRDeclaration *)decl;
  printf("%s\n", (char *)cr_declaration_to_string(declaration, 0));
}

void print_properties(struct workspace *ws)
{
  enum CRStatus status;
  GHashTable *table = g_hash_table_new(g_str_hash, g_str_equal);
  xmlNode *node = ws->result->nodesetval->nodeTab[0];
  if (!table)
  {
    fprintf(stderr, "unable to allocate a hash table\n");
    return;
  }
  status = cr_sel_eng_get_matched_properties_from_cascade(ws->selector,
                                                          ws->cascade,
                                                          node,
                                                          &table);
  if (status != CR_OK)
    fprintf(stderr, "Error retrieving properties\n");
  else
  {
    printf("properties for node %s :\n", (char *)xmlGetNodePath(node));
    g_hash_table_foreach(table, print_property, 0);
  }
  g_hash_table_destroy(table);
}

int main(int argc, char **argv)
{
  struct workspace ws;
  if (argc != 4) usage_and_exit(argv[0]);
  if (!init(&ws, argv + 1)) fini(&ws);

  if (ws.result->nodesetval->nodeNr == 0)
    printf("no matching nodes found\n");
  else
    print_properties(&ws);

  fini(&ws);
  return 0;
}
<?xml version="1.0" ?>
<report>
  <entry type="notice">
    <note id="foo"/>
    <note id="bar"/>
  </entry>
  <entry>
    <note/>
    <note id="foo"/>
    <note id="bar"/>
  </entry>
</report>
report
{ 
  color : red;
}

report > entry
{ 
  color : blue;
}

note
{ 
  color : green;
  frame : solid;
}

note[id]
{ 
  color : blue;
  frame : solid;
}

note[id=bar]
{ 
  margin : 5px;
}

entry[type=notice] note[id=bar]
{ 
  padding : 5px;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]