[grilo-plugins] lua-factory: Add XML parser
- From: Victor Toso de Carvalho <victortoso src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [grilo-plugins] lua-factory: Add XML parser
- Date: Mon, 12 Oct 2015 07:19:55 +0000 (UTC)
commit 069d5927b65649643a88fc15bc225aa1462a2e38
Author: Victor Toso <me victortoso com>
Date: Sun Sep 27 23:34:49 2015 +0200
lua-factory: Add XML parser
Implement with libxml2 an XML parser similar to the one offered by:
http://doc.lubyk.org/xml.html
XML parsing from Bastien Nocera
https://bugzilla.gnome.org/show_bug.cgi?id=755556
configure.ac | 9 +-
src/lua-factory/Makefile.am | 1 +
src/lua-factory/grl-lua-library.c | 4 +
src/lua-factory/lua-library/lua-libraries.h | 4 +-
src/lua-factory/lua-library/lua-xml.c | 200 +++++++++++++++++++++++++++
5 files changed, 214 insertions(+), 4 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 3b58a96..f4f302a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -663,11 +663,14 @@ AC_ARG_ENABLE(lua_factory,
if test "x$HAVE_JSON_GLIB" = "xno"; then
AC_MSG_ERROR([json-glib-1.0 not found, install it or use --disable-lua-factory])
fi
+ if test "x$HAVE_XML" = "xno"; then
+ AC_MSG_ERROR([libxml-2.0 not found, install it or use --disable-lua-factory])
+ fi
;;
esac
],
[
- if test "x$HAVE_LUA" = "xyes" -a "x$HAVE_ARCHIVE" = "xyes" -a "x$HAVE_GRLNET" = "xyes" -a
"x$HAVE_JSON_GLIB" = "xyes"; then
+ if test "x$HAVE_LUA" = "xyes" -a "x$HAVE_ARCHIVE" = "xyes" -a "x$HAVE_GRLNET" = "xyes" -a
"x$HAVE_JSON_GLIB" = "xyes" -a "x$HAVE_XML" = "xyes"; then
enable_lua_factory=yes
else
enable_lua_factory=no
@@ -685,12 +688,12 @@ LUA_FACTORY_PLUGIN_ID="grl-lua-factory"
AC_SUBST(LUA_FACTORY_PLUGIN_ID)
AC_DEFINE_UNQUOTED([LUA_FACTORY_PLUGIN_ID], ["$LUA_FACTORY_PLUGIN_ID"], [Lua Factory plugin ID])
-DEPS_LUA_FACTORY_CFLAGS="$DEPS_CFLAGS $LUA_CFLAGS $ARCHIVE_CFLAGS $GRLNET_CFLAGS $JSON_CFLAGS
$TOTEM_PL_PARSER_MINI_CFLAGS"
+DEPS_LUA_FACTORY_CFLAGS="$DEPS_CFLAGS $LUA_CFLAGS $ARCHIVE_CFLAGS $GRLNET_CFLAGS $JSON_CFLAGS
$TOTEM_PL_PARSER_MINI_CFLAGS $XML_CFLAGS"
if test "x$enable_goa" = "xyes"; then
DEPS_LUA_FACTORY_CFLAGS="$DEPS_LUA_FACTORY_CFLAGS $GOA_CFLAGS"
fi
AC_SUBST(DEPS_LUA_FACTORY_CFLAGS)
-DEPS_LUA_FACTORY_LIBS="$DEPS_LIBS $LUA_LIBS $ARCHIVE_LIBS $GRLNET_LIBS $JSON_LIBS $TOTEM_PL_PARSER_MINI_LIBS"
+DEPS_LUA_FACTORY_LIBS="$DEPS_LIBS $LUA_LIBS $ARCHIVE_LIBS $GRLNET_LIBS $JSON_LIBS $TOTEM_PL_PARSER_MINI_LIBS
$XML_LIBS"
if test "x$enable_goa" = "xyes"; then
DEPS_LUA_FACTORY_LIBS="$DEPS_LUA_FACTORY_LIBS $GOA_LIBS"
fi
diff --git a/src/lua-factory/Makefile.am b/src/lua-factory/Makefile.am
index d4810d9..8887db7 100644
--- a/src/lua-factory/Makefile.am
+++ b/src/lua-factory/Makefile.am
@@ -36,6 +36,7 @@ libgrlluafactory_la_SOURCES = \
lua-library/htmlentity.c \
lua-library/htmlentity.h \
lua-library/lua-json.c \
+ lua-library/lua-xml.c \
lua-library/lua-libraries.h
extdir = $(GRL_PLUGINS_DIR)
diff --git a/src/lua-factory/grl-lua-library.c b/src/lua-factory/grl-lua-library.c
index 66ba2ae..da61eb3 100644
--- a/src/lua-factory/grl-lua-library.c
+++ b/src/lua-factory/grl-lua-library.c
@@ -1542,6 +1542,10 @@ luaopen_grilo (lua_State *L)
luaopen_json (L);
lua_settable (L, -3);
+ lua_pushstring (L, GRILO_LUA_LIBRARY_XML);
+ luaopen_xml (L);
+ lua_settable (L, -3);
+
/* Load inspect.lua and save object in global environment table */
lua_getglobal (L, LUA_ENV_TABLE);
if (load_gresource_library (L, URI_LUA_LIBRARY_INSPECT) &&
diff --git a/src/lua-factory/lua-library/lua-libraries.h b/src/lua-factory/lua-library/lua-libraries.h
index 3af5f55..8fce92a 100644
--- a/src/lua-factory/lua-library/lua-libraries.h
+++ b/src/lua-factory/lua-library/lua-libraries.h
@@ -33,8 +33,10 @@
#define URI_LUA_LIBRARY_INSPECT GRESOURCE_LIBRARY_PREFIX "inspect.lua"
#define GRILO_LUA_LIBRARY_INSPECT "inspect"
-#define GRILO_LUA_LIBRARY_JSON "json"
+#define GRILO_LUA_LIBRARY_JSON "json"
+#define GRILO_LUA_LIBRARY_XML "xml"
gint luaopen_json (lua_State *L);
+gint luaopen_xml (lua_State *L);
#endif /* _GRL_LUA_LIBRARY_JSON_H_ */
diff --git a/src/lua-factory/lua-library/lua-xml.c b/src/lua-factory/lua-library/lua-xml.c
new file mode 100644
index 0000000..15d6466
--- /dev/null
+++ b/src/lua-factory/lua-library/lua-xml.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2015 Bastien Nocera <hadess hadess net>
+ *
+ * Contact: Victor Toso <me victortoso com>
+ * Bastien Nocera <hadess hadess net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "lua-libraries.h"
+
+#include <string.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+/* ================== Lua-Library Json Handlers ============================ */
+static void build_table_from_xml_reader (lua_State *L,
+ xmlDocPtr doc,
+ xmlNodePtr parent);
+
+static void
+build_table_recursively (lua_State *L,
+ xmlDocPtr doc,
+ xmlNodePtr parent)
+{
+ gboolean is_root_node;
+ xmlNodePtr node;
+ GHashTable *ht;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ if (parent == NULL) {
+ is_root_node = TRUE;
+ node = xmlDocGetRootElement (doc);
+ } else {
+ is_root_node = FALSE;
+ node = parent->children;
+ }
+
+ /* We need to iterate in the xml nodes by its name so we can attach
+ * nodes with same name to the same array (table). */
+ ht = g_hash_table_new (g_str_hash, g_str_equal);
+ for (; node != NULL; node = node->next) {
+ GList *list;
+
+ if (node->name == NULL || g_str_equal (node->name, "text"))
+ continue;
+
+ list = g_hash_table_lookup (ht, (gchar *) node->name);
+ list = g_list_prepend (list, node);
+ g_hash_table_insert (ht, (gchar *) node->name, list);
+ }
+
+ g_hash_table_iter_init (&iter, ht);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ GList *it = g_list_reverse (value);
+ guint len = g_list_length (it);
+ guint i;
+ xmlNodePtr node;
+
+ if (len == 1) {
+ /* Only one node, no array needed */
+ node = it->data;
+ node = (is_root_node) ? node : node->children;
+ lua_pushstring (L, (gchar *) key);
+ lua_newtable (L);
+ build_table_from_xml_reader (L, doc, it->data);
+ } else {
+ /* node-name will have an array of tables here */
+ lua_pushstring (L, (gchar *) key);
+ lua_createtable (L, len, 0);
+ for (i = 0; i < len; i++) {
+ node = it->data;
+ node = (is_root_node) ? node : node->children;
+ lua_pushinteger (L, i + 1);
+ lua_newtable (L);
+ build_table_from_xml_reader (L, doc, it->data);
+ lua_settable(L, -3);
+ it = it->next;
+ }
+ }
+ lua_settable(L, -3);
+ g_list_free (value);
+ }
+ g_hash_table_destroy (ht);
+}
+
+/* Save key/values on the table in the stack if the value is an
+ * object or an array, it calls recursively the function again.
+ *
+ * @param L, pointer to the L with nil on top of it;
+ * @param reader, pointed to the first element of main object;
+ *
+ * returns: the table in the stack with all xml values
+ */
+static void
+build_table_from_xml_reader (lua_State *L,
+ xmlDocPtr doc,
+ xmlNodePtr parent)
+{
+ xmlChar *str;
+ xmlAttrPtr attr;
+
+ if (parent == NULL) {
+ /* In the root element we check for sibilings and start the recursive
+ * procedure to map the lua table. */
+ build_table_recursively (L, doc, NULL);
+ return;
+ }
+
+ str = xmlNodeListGetString (doc, parent->xmlChildrenNode, 1);
+ if (str) {
+ /* We use xml to the value as it is a forbidden node name */
+ lua_pushstring (L, "xml");
+ lua_pushstring (L, (gchar *) str);
+ lua_settable(L, -3);
+ xmlFree (str);
+ }
+
+ for (attr = parent->properties; attr != NULL; attr = attr->next) {
+ xmlChar *val;
+
+ if (!attr->name)
+ continue;
+
+ val = xmlGetProp (parent, (const xmlChar *) attr->name);
+ if (val) {
+ lua_pushstring (L, (gchar *) attr->name);
+ lua_pushstring (L, (gchar *) val);
+ lua_settable(L, -3);
+ xmlFree (val);
+ } else {
+ GRL_WARNING ("xml-parser not handling empty properties as %s", attr->name);
+ }
+ }
+
+ build_table_recursively (L, doc, parent);
+}
+
+/* grl.lua.xml.string_to_table
+ *
+ * @xml_str: (string) XML as a string.
+ *
+ * @return: All XML content as a table.
+ */
+static gint
+grl_xml_parse_string (lua_State *L)
+{
+ xmlDocPtr doc;
+ const gchar *xml_str = NULL;
+ int len;
+
+ luaL_argcheck (L, lua_isstring (L, 1), 1, "xml string expected");
+ xml_str = lua_tostring (L, 1);
+
+ len = strlen (xml_str);
+ doc = xmlParseMemory (xml_str, len);
+ if (!doc)
+ doc = xmlRecoverMemory (xml_str, len);
+
+ if (!doc) {
+ GRL_DEBUG ("Can't parse XML string");
+ return 0;
+ }
+
+ /* See "Traversing the tree" at:
+ * http://www.xmlsoft.org/library.html */
+ lua_newtable (L);
+ build_table_from_xml_reader (L, doc, NULL);
+
+ xmlFreeDoc (doc);
+
+ return 1;
+}
+
+gint
+luaopen_xml (lua_State *L)
+{
+ static const luaL_Reg xml_library_fn[] = {
+ {"string_to_table", &grl_xml_parse_string},
+ {NULL, NULL}
+ };
+
+ luaL_newlib (L, xml_library_fn);
+ return 1;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]