[XML-SIG] Using XML Namespaces in XPath Expressions from Python
JonTom Kittredge
jontom at itasoftware.com
Mon Jun 13 16:29:45 CEST 2005
Uche, Thanks for your response. My comments are below.
On 2005-06-09 at 06:26, Uche Ogbuji wrote:
> On Wed, 2005-06-08 at 10:27 -0400, JonTom Kittredge wrote:
> > I'm having trouble using PyXML to evaluate XPath expressions that
> > include namespace references.
> >
> > Here is a sample Python snipped:
> >
> > #!/usr/bin/env pystart
> >
> > import sys
> > import xml.dom.minidom
> >
> > from xml.xpath.Context import Context
> > from xml.xpath import Evaluate
> > from xml.xpath.NamespaceNode import NamespaceNode
> >
> >
> > if __name__ == "__main__":
> > sys.stderr.write("XPathTest: 18\n")
> >
> > inputDom = xml.dom.minidom.parse(open("xpathtest-input.xml"))
> >
> > sys.stderr.write("Node: %s\n" % (inputDom.documentElement))
> > outContext = Context(inputDom.documentElement)
>
> Where are you passing in the NS mapping here? Did I miss a PyXML XPath
> update that defaults mappings to in-scope namespaces on the node passed
> in?
That's the nub of my question. How do I pass namespace mappings into
Evaluate()?
The only thing I could see to try, from looking at the documentation,
was to use the context argument. The Context object holds namespace
objects, so I thought that that might be the way to pass in my
definition.
As you can see from the output, the Context I get from the document
node already has the "dbq" namespace defined (since it appears in the
input), before I call Evaluate(). However, it apparently gets reset
during the call to Evaluate().
>
> > sys.stderr.write("NSes=%s\n" % (outContext.nss()))
> >
> > result = Evaluate("count(/dbq:Contract)",
> > contextNode=inputDom.documentElement,
>
> I think this line is your problem. It overrides the next (probably not
> sensible, which is why we reversed that priority in 4Suite ages ago).
>
> > context=outContext)
>
OK. If I leave out that line and instead do the following:
result = Evaluate("count(/dbq:Contract)",
contextNode=inputDom.documentElement)
I still get the following error:
Node: <DOM Element: dbq:Contract at 0x82ac2e4>
Traceback (most recent call last):
File "xpathtest-1.py", line 20, in ?
contextNode=inputDom.documentElement)
File "/ita/python-2.2.2/lib/python2.2/site-packages/_xmlplus/xpath/__init__.py", line 70, in Evaluate
retval = parser.new().parse(expr).evaluate(con)
File "/ita/python-2.2.2/lib/python2.2/site-packages/_xmlplus/xpath/ParsedExpr.py", line 179, in evaluate
arg0 = self._arg0.evaluate(context)
File "/ita/python-2.2.2/lib/python2.2/site-packages/_xmlplus/xpath/ParsedAbsoluteLocationPath.py", line 26, in evaluate
rt = self._child.select(context)
File "/ita/python-2.2.2/lib/python2.2/site-packages/_xmlplus/xpath/ParsedStep.py", line 32, in evaluate
(node_set, reverse) = self._axis.select(context, self._nodeTest.match)
File "/ita/python-2.2.2/lib/python2.2/site-packages/_xmlplus/xpath/ParsedAxisSpecifier.py", line 114, in select
list(context.node.childNodes))
File "/ita/python-2.2.2/lib/python2.2/site-packages/_xmlplus/xpath/ParsedAxisSpecifier.py", line 112, in <lambda>
rt = filter(lambda node, test=nodeTest, context=context, pt=self.principalType:
File "/ita/python-2.2.2/lib/python2.2/site-packages/_xmlplus/xpath/ParsedNodeTest.py", line 168, in match
self._prefix)
xml.xpath.RuntimeException: Undefined namespace prefix: "dbq".
Which me leaves my initial question: how do I use xml.xpath.Evaluate()
on an XPath expression that refers to namespaces?
>
> --
> Uche Ogbuji Fourthought, Inc.
> http://uche.ogbuji.net http://fourthought.com
> http://copia.ogbuji.net http://4Suite.org
> Use CSS to display XML, part 2 - http://www-128.ibm.com/developerworks/edu/x-dw-x-xmlcss2-i.html
> XML Output with 4Suite & Amara - http://www.xml.com/pub/a/2005/04/20/py-xml.html
> Use XSLT to prepare XML for import into OpenOffice Calc - http://www.ibm.com/developerworks/xml/library/x-oocalc/
> Schema standardization for top-down semantic transparency - http://www-128.ibm.com/developerworks/xml/library/x-think31.html
For completeness, here is my Python:
import sys
import traceback
import xml.dom.minidom
from xml.xpath.Context import Context
from xml.xpath import Evaluate
from xml.xpath.NamespaceNode import NamespaceNode
sys.stderr.write("XPathTest: 1\n")
inputDom = xml.dom.minidom.parse(open("xpathtest-input.xml"))
sys.stderr.write("Node: %s\n" % (inputDom.documentElement))
result = Evaluate("count(/dbq:Contract)",
contextNode=inputDom.documentElement)
sys.stderr.write("Eval xpath \"count(/dbq:Contract)\": %d\n" % result)
and here is my input:
<?xml version="1.0"?>
<dbq:Contract
xmlns:dbq="http://dtd.itasoftware.com/Dubuque">
<dbq:RuleContent/>
</dbq:Contract>
Yours, JonTom
JT Kittredge
ITA Software, Inc.
Cambridge, Massachusetts
More information about the XML-SIG
mailing list