Re: Using XML Namespaces in XPath Expressions from Python

JonTom Kittredge <[email protected]>
Newsgroups gmane.comp.python.xml
Message-ID <[email protected]>
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
_______________________________________________
XML-SIG maillist  -  [email protected]
http://mail.python.org/mailman/listinfo/xml-sig
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.