python libxml2 xpath extensions

S

shaun roe

I am coming to libxml2 python binding for the first time and find I have
to make an xpath extension function. The standard examples at
http://xmlsoft.org/python.html
are a little too simple. I might have expected, given those examples, to
be able to do this:

import sys
import libxml2

def foo(ctx, x):
return x + 1

doc = libxml2.parseFile("channels.xml")
ctxt = doc.xpathNewContext()
libxml2.registerXPathFunction(ctxt._o, "foo", None, foo)
res = ctxt.xpathEval("/channels/channel/value[1]/foo(1)")[0]
print res

(yes, its a silly example) which would return the value 2 . However,
this crashes and burns at the evaluation. I am guessing that

a) There is some magic in the return value whereby it needs to be added
to the result tree manually

and

b) That when I try the next stage with foo(.) it will again crash
because I need to get the value from the context node. (here I am
confused by the difference between the 'xpath context' and 'xpath parser
context')

can anyone enlighten me?

cheers

shaun

ps my source document format is like this:

<channels>
<channel id="0">
<value name="myval">67</value>
</channel>
.
.
.

</channels>
 
P

Pavel Lepin

shaun roe said:
import sys
import libxml2

def foo(ctx, x):
return x + 1

doc = libxml2.parseFile("channels.xml")
ctxt = doc.xpathNewContext()
libxml2.registerXPathFunction(ctxt._o, "foo", None, foo)
res =
ctxt.xpathEval("/channels/channel/value[1]/foo(1)")[0]
print res

Ah... well, it won't work that way. This little bit of
kludgery should:

res = ctxt.xpathEval("foo(number(/channels/channel/value))")

Not sure if this helps you, and the proper reference seems
to be either non-existent or extremely well-hidden, so good
luck trying to juggle contexts.
a) There is some magic in the return value whereby it
needs to be added to the result tree manually

Um, no, that doesn't make sense.
b) That when I try the next stage with foo(.) it will
again crash because I need to get the value from the
context node. (here I am confused by the difference
between the 'xpath context' and 'xpath parser context')

Have you found any sort of reference for context interfaces?
That would probably make things a bit more clear.
 
S

shaun roe

Pavel Lepin <[email protected]> said:
shaun roe said:
import sys
import libxml2

def foo(ctx, x):
return x + 1

doc = libxml2.parseFile("channels.xml")
ctxt = doc.xpathNewContext()
libxml2.registerXPathFunction(ctxt._o, "foo", None, foo)
res =
ctxt.xpathEval("/channels/channel/value[1]/foo(1)")[0]
print res

Ah... well, it won't work that way. This little bit of
kludgery should:

res = ctxt.xpathEval("foo(number(/channels/channel/value))")

I found this which helped me a bit:
http://www.xmldatabases.org/movabletype/archives/000291.html
and now I can:

def my(ctx,x):
rc="0"
node = libxml2.xmlNode(_obj=x[0])
if ('RunNumber' in node.content):
# dummy return for now, so my xpath condition will always be true
rc="1"
return rc

doc = libxml2.parseFile("channels.xml")
ctxt = doc.xpathNewContext()

libxml2.registerXPathFunction(ctxt._o, "my", None, my)

ress = ctxt.xpathEval("/channels/channel/value[my(@name)='1']")
if ress:
result=ress[0]

doc.freeDoc()
ctxt.xpathFreeContext()


The trick was to 'cast' the x to a node. I still haven't quite worked
out how to insert things into the result tree, though.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,225
Members
46,815
Latest member
treekmostly22

Latest Threads

Top