Трансформация XML при помощи XSLT на LUA

luaxslt.c

#include <errno.h>
#include <lualib.h>
#include <lauxlib.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>

int luaopen_luaxsltlib (lua_State *L);

#define LUA_EXTRALIBS { "luaxsltlib", luaopen_luaxsltlib },

static int l_transform(lua_State *L) {
    int n = lua_gettop(L);
    const char *s = luaL_checkstring(L, 1);
    const char *ss = luaL_checkstring(L, 2);

    const char *params[16 + 1];
    char *out;
    int nbparams = 0;
    int len = 9999;
    xsltStylesheetPtr cur = NULL;
    xmlDocPtr doc, res;
    int i = 0;


    if (n > 2 && (n/2)*2 == n ) {
        for (i = 3; i <= n; i++) {
            params[nbparams++] = luaL_checkstring(L, i);
        }
    }

    params[nbparams] = NULL;
    xmlSubstituteEntitiesDefault(0);
    xmlLoadExtDtdDefaultValue = 1;
    cur = xsltParseStylesheetFile((const xmlChar *)ss);

    doc = xmlParseDoc((const xmlChar *)s);
    res = xsltApplyStylesheet(cur, doc, params);
    xsltSaveResultToString(&out,&len, res, cur);

    out[len] = NULL;

    xsltFreeStylesheet(cur);
    xmlFreeDoc(res);
    xmlFreeDoc(doc);

    lua_pushstring(L,out);
    lua_pushnumber(L,len);

    xmlFree(out);

    xsltCleanupGlobals();
    xmlCleanupParser();


    return 2;
}


static const struct luaL_reg luaxsltlib [] = {
      {"transform", l_transform},
      {NULL, NULL}
};


int luaopen_luaxsltlib (lua_State *L) {
      luaL_openlib(L, "luaxsltlib", luaxsltlib, 0);
      return 1;
}

lxslt.lua

require("luaxsltlib")

xml = [[
<root><child/></root>
]]

local result,result_length = luaxsltlib.transform(xml,"test.xslt","string_param","'test value'","number_param",111)
print(result)

test.xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="string_param" />
<xsl:param name="number_param" />
  <xsl:template match="/">
    <html>
      <head>
    <title>LuaXslt test</title>
      </head>

      <body>
      <xsl:value-of select="count(./descendant-or-self::*)" />|<xsl:value-of select="$string_param" />|<xsl:value-of select="$number_param" />
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>

build.sh

# gcc -Wall -O2 -I /usr/include/lua5.1/ -I/usr/include/libxml2 -I/usr/include -c luaxslt.c  
# gcc -shared -o luaxsltlib.so -llua5.1 -lm -ldl -lxslt -lxml2 -lz -lpthread luaxslt.o