Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions src/lua_xpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#define LUA_XPATH_NAME "xpath"
#define LUA_XPATH_MT_NAME "xpath_mt"

#define MAX_XPATH_PREFIX_NUM 20

typedef struct xpath_selector_s {
struct xpath_selector_s *root;
Expand Down Expand Up @@ -204,11 +205,13 @@ __parse_file(xpath_selector_t *sel, char const *fname)


static void **
__eval_xpath(lua_State *L, xpath_selector_t *sel, char const *xpath)
__eval_xpath(lua_State *L, xpath_selector_t *sel, char const *xpath, const xmlChar * nsList[])
{
int i;
xmlXPathObject *result = NULL;
xmlXPathContext *ctxt = NULL;
const xmlChar* prefix = NULL;
const xmlChar* href = NULL;
void **nodes = NULL;


Expand All @@ -223,6 +226,14 @@ __eval_xpath(lua_State *L, xpath_selector_t *sel, char const *xpath)
break;
}

for (i = 0 ; prefix = nsList[i++];) {
if ((href = nsList[i])
&& (xmlXPathRegisterNs(ctxt, prefix, href) != 0)) {
__set_error(sel, NULL, "add namespace to xpath context error");
break;
}
}

/* the current node */
ctxt->node = sel->node;

Expand Down Expand Up @@ -460,6 +471,7 @@ xpath_eval_xpath(lua_State *L)
size_t length;
void **nodes;
const char *xpath;
const xmlChar* nsList[MAX_XPATH_PREFIX_NUM];
xpath_selector_t *sel, *node;


Expand All @@ -477,8 +489,29 @@ xpath_eval_xpath(lua_State *L)
lua_pushstring(L, "xpath pattern needed");
return 2;
}
{
int n, top = lua_gettop(L);
i = 1;
if (top > 2) { //optionally prefix/href array for xpath
if (lua_type(L, 3) != LUA_TTABLE) {
lua_pushnil(L);
lua_pushstring(L, "prefix/href array is expected");
return 2;
}
if ((n = luaL_getn(L, 3)) > MAX_XPATH_PREFIX_NUM) {
lua_pushnil(L);
lua_pushstring(L, "too much prefixes");
return 2;
}
for (; i <= n; i++) {
lua_rawgeti(L, 3, i);
nsList[i - 1] = luaL_optlstring(L, -1, NULL, &length);
}
}
nsList[i - 1] = 0;
}

nodes = (void **) __eval_xpath(L, sel, xpath);
nodes = (void **) __eval_xpath(L, sel, xpath, nsList);
if (nodes == NULL) {
lua_pushnil(L);
lua_pushstring(L, __get_error(sel, "eval xpath error"));
Expand Down
2 changes: 2 additions & 0 deletions src/lua_xpath.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/parserInternals.h>
#include <libxml/xpathInternals.h>


#include <stdint.h>

Expand Down
41 changes: 40 additions & 1 deletion tests/api.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package.cpath = "/home/duhoobo/prj/amateur/lua-xpath/src/?.so;" .. package.cpath
package.cpath = "/home/akh/local/lua-xpath/src/?.so;" .. package.cpath

local xpath = require("xpath")

Expand All @@ -12,6 +12,17 @@ xml = [[
<sex>male</sex>
</body>
</html>]]
xmlns = [[
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:message="http://org.mycomp">
<soapenv:Header/>
<soapenv:Body>
<message:SomeMessage>
<message:SomeField>4</message:SomeField>
</message:SomeMessage>
</soapenv:Body>
</soapenv:Envelope>
]]



function test_xpath()
Expand Down Expand Up @@ -40,6 +51,33 @@ function test_xpath()
print "\n--- leave test_xpath ---"
end

function test_xpath_with_ns()
print "--- enter test_xpath_with_ns ---\n"

local sel, err = xpath.loads(xmlns)

if not sel then
print(sel, err)
return
end

print(sel)

local ls, err = sel:xpath("/soap:Envelope/soap:Body//message:SomeField[text()=4]",
{"soap", "http://schemas.xmlsoap.org/soap/envelope/", "message", "http://org.mycomp"})

if not ls then
print(ls, err)
return
end

for k, v in pairs(ls) do
print(k, v, v:extract())
end

print "\n--- leave test_xpath_with_ns ---"
end


function test_relative_xpath()
print "--- enter test_relative_xpath ---\n"
Expand Down Expand Up @@ -214,6 +252,7 @@ end


test_xpath()
test_xpath_with_ns()
test_relative_xpath()
test_re()
test_css()
Expand Down