This commit is contained in:
Kyle Maxwell 2009-02-24 21:23:44 -08:00
parent b35c157126
commit 466c18e55e
11 changed files with 146 additions and 45 deletions

View File

@ -47,4 +47,5 @@ check-am:
@echo "optional..."; ./dexter test/optional.dex test/optional.html | diff test/optional.json - && echo " success."
@echo "malformed-function..."; ./dexter test/malformed-function.dex test/malformed-function.html | diff test/malformed-function.json - && echo " success."
@echo "empty..."; ./dexter test/empty.dex test/empty.html | diff test/empty.json - && echo " success."
@echo "hn..."; ./dexter test/hn.dex test/hn.html | diff test/hn.json - && echo " success."

View File

@ -750,6 +750,7 @@ check-am:
@echo "optional..."; ./dexter test/optional.dex test/optional.html | diff test/optional.json - && echo " success."
@echo "malformed-function..."; ./dexter test/malformed-function.dex test/malformed-function.html | diff test/malformed-function.json - && echo " success."
@echo "empty..."; ./dexter test/empty.dex test/empty.html | diff test/empty.json - && echo " success."
@echo "hn..."; ./dexter test/hn.dex test/hn.html | diff test/hn.json - && echo " success."
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@ -223,6 +223,7 @@ static contextPtr new_context(struct json_object * json, struct printbuf *buf) {
c->string = 0;
c->flags = 0;
c->keys = NULL;
c->zipped = 0;
return c;
}
@ -280,6 +281,14 @@ static char* optional(contextPtr c) {
return (c->flags & DEX_OPTIONAL) ? " optional=\"true\"" : "";
}
static bool
all_strings(struct json_object * json) {
json_object_object_foreach(json, key, val) {
if(!json_object_is_type(val, json_type_string)) return false;
}
return true;
}
void __dex_recurse(contextPtr context) {
// printf("a\n");
char* tmp;
@ -290,79 +299,89 @@ void __dex_recurse(contextPtr context) {
c = deeper_context(context, key, val);
sprintbuf(c->buf, "<%s%s>\n", c->tag, optional(c));
if(c->string) {
if(c->array) {
if(c->array || context->zipped) {
if(c->filter){
// printf("b\n");
sprintbuf(c->buf, "<dexter:groups optional=\"true\"><xsl:for-each select=\"%s\"><dexter:group optional=\"true\">\n", c->filter);
sprintbuf(c->buf, "<xsl:value-of select=\"%s\" />\n", c->raw_expr);
sprintbuf(c->buf, "</dexter:group></xsl:for-each></dexter:groups>\n");
} else {
// printf("c\n");
sprintbuf(c->buf, "<dexter:groups optional=\"true\"><xsl:for-each select=\"%s\"><dexter:group optional=\"true\">\n", c->expr);
sprintbuf(c->buf, "<xsl:value-of select=\".\" />\n");
sprintbuf(c->buf, "</dexter:group></xsl:for-each></dexter:groups>\n");
}
} else {
if(c->filter){
// printf("d\n");
sprintbuf(c->buf, "<xsl:for-each select=\"%s\"><xsl:if test=\"position()=1\">\n", c->filter);
sprintbuf(c->buf, "<xsl:value-of select=\"%s\" />\n", c->raw_expr);
sprintbuf(c->buf, "</xsl:if></xsl:for-each>\n");
} else {
// printf("e\n");
sprintbuf(c->buf, "<xsl:value-of select=\"%s\" />\n", c->expr);
}
}
} else { // if c->object !string
if(c->array) { // scoped
if(c->filter != NULL) {
// printf("e\n");
// printf("f\n");
sprintbuf(c->buf, "<dexter:groups optional=\"true\"><xsl:for-each select=\"%s\"><dexter:group optional=\"true\">\n", c->filter);
__dex_recurse(c);
sprintbuf(c->buf, "</dexter:group></xsl:for-each></dexter:groups>\n");
} else { // magic
// printf("f\n");
sprintbuf(c->buf, "<xsl:variable name=\"%s__context\" select=\".\"/>\n", c->name);
dex_parsing_context = c;
char * str = inner_key_of(c->json);
if(str != NULL) {
tmp = myparse(astrdup(str));
sprintbuf(c->buf, "<dexter:groups optional=\"true\"><xsl:for-each select=\"%s\">\n", filter_intersection(context->magic, tmp));
} else { // magic
if(all_strings(c->json)) {
c->magic = NULL;
c->zipped = 1;
sprintbuf(c->buf, "<dexter:zipped>\n");
__dex_recurse(c);
sprintbuf(c->buf, "</dexter:zipped>\n");
} else {
// printf("h\n");
sprintbuf(c->buf, "<xsl:variable name=\"%s__context\" select=\".\"/>\n", c->name);
dex_parsing_context = c;
char * str = inner_key_of(c->json);
if(str != NULL) {
// printf("i\n");
tmp = myparse(astrdup(str));
sprintbuf(c->buf, "<dexter:groups optional=\"true\"><xsl:for-each select=\"%s\">\n", filter_intersection(context->magic, tmp));
// keys
keys = dex_alloc(sizeof(key_node));
keys->name = c->name;
keys->use = full_expr(c, tmp);
keys->next = c->keys;
c->keys = keys;
// keys
keys = dex_alloc(sizeof(key_node));
keys->name = c->name;
keys->use = full_expr(c, tmp);
keys->next = c->keys;
c->keys = keys;
buf = printbuf_new();
buf = printbuf_new();
sprintbuf(buf, "concat(");
while(keys != NULL){
sprintbuf(buf, "count(set:intersection(following::*, %s)), '-',", keys->use);
keys = keys->next;
}
sprintbuf(buf, "'')");
tmp = astrdup(buf->buf);
printbuf_free(buf);
sprintbuf(buf, "concat(");
while(keys != NULL){
sprintbuf(buf, "count(set:intersection(following::*, %s)), '-',", keys->use);
keys = keys->next;
}
sprintbuf(buf, "'')");
tmp = astrdup(buf->buf);
printbuf_free(buf);
sprintbuf(c->key_buf, "<xsl:key name=\"%s__key\" match=\"%s\" use=\"%s\"/>\n", c->name,
full_expr(c, "./descendant-or-self::*"),
tmp
);
sprintbuf(c->key_buf, "<xsl:key name=\"%s__key\" match=\"%s\" use=\"%s\"/>\n", c->name,
full_expr(c, "./descendant-or-self::*"),
tmp
);
sprintbuf(c->buf, "<xsl:variable name=\"%s__index\" select=\"%s\"/>\n", c->name, tmp);
sprintbuf(c->buf, "<xsl:for-each select=\"$%s__context\"><dexter:group optional=\"true\">\n", c->name);
__dex_recurse(c);
sprintbuf(c->buf, "</dexter:group></xsl:for-each></xsl:for-each></dexter:groups>\n");
}
sprintbuf(c->buf, "<xsl:variable name=\"%s__index\" select=\"%s\"/>\n", c->name, tmp);
sprintbuf(c->buf, "<xsl:for-each select=\"$%s__context\"><dexter:group optional=\"true\">\n", c->name);
__dex_recurse(c);
sprintbuf(c->buf, "</dexter:group></xsl:for-each></xsl:for-each></dexter:groups>\n");
}
}
}
} else {
// printf("c\n");
// printf("j\n");
if(c->filter == NULL) {
__dex_recurse(c);
} else {
} else {
// printf("k\n");
sprintbuf(c->buf, "<xsl:for-each select=\"%s\"><xsl:if test=\"position() = 1\">\n", c->filter);
__dex_recurse(c);
sprintbuf(c->buf, "</xsl:if></xsl:for-each>\n");

View File

@ -53,6 +53,7 @@ typedef struct __dex_context {
int array;
int string;
int flags;
int zipped;
} dex_context;
typedef dex_context * contextPtr;

View File

@ -2,7 +2,7 @@
# libtool - Provide generalized library-building support services.
# Generated automatically by config.status (dexterc) 1.0
# Libtool was configured on host kyle-maxwells-macbook.local:
# Libtool was configured on host 111.flood.pivotallabs.com:
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
#
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,

View File

@ -230,8 +230,6 @@ PrimaryExpr
FunctionCall
: FunctionName LPAREN Arguments RPAREN { $$ = astrcat4(xpath_alias($1), $2, $3, $4); }
| FunctionName LPAREN Arguments { yyerror("Unclosed parenthesis"); }
| FunctionName LPAREN Arguments RPAREN RPAREN { yyerror("Too many parenthesis"); }
;
Arguments
: ArgumentSet

8
test/hn.dex Normal file
View File

@ -0,0 +1,8 @@
{
"articles": [ {
"title": ".title a",
"link": ".title a @href",
"comment_count(.subtext a:nth-child(3))": "number(regex:match(., '[0-9]+', ''))",
"comment_link": ".subtext a:nth-child(3) @href"
} ]
}

32
test/hn.html Normal file

File diff suppressed because one or more lines are too long

1
test/hn.json Normal file

File diff suppressed because one or more lines are too long

3
util.c
View File

@ -107,7 +107,8 @@ char* sprintbuf_dex_header(struct printbuf *buf) {
sprintbuf(buf, " xmlns:exsl=\"http://exslt.org/common\"");
sprintbuf(buf, " xmlns:saxon=\"http://icl.com/saxon\"");
sprintbuf(buf, " xmlns:regexp=\"http://exslt.org/regular-expressions\"");
sprintbuf(buf, " extension-element-prefixes=\"dex str math set func dyn exsl saxon user date regexp\"");
sprintbuf(buf, " xmlns:regex=\"http://exslt.org/regular-expressions\"");
sprintbuf(buf, " extension-element-prefixes=\"dex str math set func dyn exsl saxon user date regexp regex\"");
sprintbuf(buf, ">\n");
sprintbuf(buf, "<xsl:output method=\"xml\" indent=\"yes\"/>\n");
sprintbuf(buf, "<xsl:strip-space elements=\"*\"/>\n");

View File

@ -1,7 +1,11 @@
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/debugXML.h>
#include <json/json.h>
#include "xml2json.h"
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
static struct json_object * _xml2json(xmlNodePtr xml) {
if(xml == NULL) return NULL;
@ -20,7 +24,42 @@ static struct json_object * _xml2json(xmlNodePtr xml) {
child = child->next;
}
} else if(!strcmp(xml->ns->prefix, "dexter")) {
if(!strcmp(xml->name, "groups")) {
if(!strcmp(xml->name, "zipped")) {
int len = 0;
xmlNodePtr ptr = xml->children;
while(ptr != NULL){
len++;
ptr = ptr->next;
}
xmlNodePtr *ptrs = (xmlNodePtr *) malloc(len * sizeof(xmlNodePtr));
char **names = (char**) malloc(len * sizeof(char*));
for(int i = 0; i < len; i++) {
// zip named groups
ptrs[i] = child->children->children;
names[i] = child->name;
child = child->next;
}
json = json_object_new_array();
bool legit = true;
while(legit) {
for(int i = 0; i < len; i++) {
// fprintf(stderr, "name: %s\n", names[i]);
// xmlDebugDumpNode(stderr, ptrs[i], 2);
// exit(1);
legit &= ptrs[i] != NULL;
}
if(legit) {
struct json_object * inner = json_object_new_object();
for(int i = 0; i < len; i++) {
json_object_object_add(inner, names[i], xml2json(ptrs[i]->children));
ptrs[i] = ptrs[i]->next;
}
json_object_array_add(json, inner);
}
}
free(ptrs);
free(names);
} else if(!strcmp(xml->name, "groups")) {
json = json_object_new_array();
while(child != NULL) {
json_object_array_add(json, xml2json(child->children));