Edgewall Software

Opened 11 years ago

Closed 11 years ago

#572 closed defect (fixed)

QualifiedNameTest sets output attributes to `None`

Reported by: Olemis Lang <olemis+trac@…> Owned by: hodgestar
Priority: blocker Milestone: 0.7
Component: XPath support Version: devel
Keywords: qualified attribute name, XPath attribute axis Cc: jcasado81@…

Description

Consider the following script

'''
Created on Jul 9, 2013

@author: olemis
'''

from pprint import pprint

from genshi.template.markup import MarkupTemplate

if __name__ == '__main__':
    template_source = """<?xml version="1.0" encoding="utf-8"?>
    <element xmlns:nspc1="http://foo.org"
        nspc1:attribute="value">
    </element>
    """

    data = {}

    # XML stream
    template = MarkupTemplate(template_source)
    stream = template.generate(**data)

    for ev in stream.select('./@nspc1:attribute', {'nspc1' : 'http://foo.org'}):
        pprint(ev)

By executing it it's possible to notice how XPath expressions will always evaluate to None when matching qualified attribute names.

$ ./test_select1.py
Attrs([('attribute', None)])

After modifying QualifiedNameTest.__call__ like shown below ...

    def __call__(self, kind, data, pos, namespaces, variables):
        qname = QName('%s}%s' % (namespaces.get(self.prefix), self.name))
        if kind is START:
            if self.principal_type is ATTRIBUTE and qname in data[1]:
                return Attrs([(self.name, data[1].get(qname))])
            else:
                return data[0] == qname

... the result looks better

$ ./test_select1.py
Attrs([('attribute', u'value')])

Moreover this version will preserve namespace information

    def __call__(self, kind, data, pos, namespaces, variables):
        qname = QName('%s}%s' % (namespaces.get(self.prefix), self.name))
        if kind is START:
            if self.principal_type is ATTRIBUTE and qname in data[1]:
                return Attrs([(self.name, data[1].get(qname))])
            else:
                return data[0] == qname

Results

$ ./test_select1.py
Attrs([(QName('http://foo.org}attribute'), u'value')])

IMO the last one is the most accurate considering that this may be used to insert attributes in elements (e.g. py:attrs="select('@*')" in Genshi tutorial).

BTW , I set version=develop in the ticket because this issue was detected using both 0.7 and 0.6, and there's no option to select the former.

priority=blocker because IMO this ticket only is a good reason to release 0.7.1

Change History (5)

comment:1 Changed 11 years ago by jcasado81@…

  • Cc jcasado81@… added

comment:2 in reply to: ↑ description Changed 11 years ago by Olemis Lang <olemis+trac@…>

Replying to Olemis Lang <olemis+trac@…>:

Moreover this version will preserve namespace information

I pasted the same code snippet twice . The code preserving namespace prefix should have been written as follows

    def __call__(self, kind, data, pos, namespaces, variables):
        qname = QName('%s}%s' % (namespaces.get(self.prefix), self.name))
        if kind is START:
            if self.principal_type is ATTRIBUTE and qname in data[1]:
                return Attrs([(qname, data[1].get(qname))])
            else:
                return data[0] == qname

Results

$ ./test_select1.py
Attrs([(QName('http://foo.org}attribute'), u'value')])

comment:3 Changed 11 years ago by Olemis Lang <olemis+trac@…>

  • Keywords qualified attribute name XPath attribute axis added

comment:4 Changed 11 years ago by hodgestar

  • Owner changed from cmlenz to hodgestar
  • Status changed from new to assigned

comment:5 Changed 11 years ago by hodgestar

  • Resolution set to fixed
  • Status changed from assigned to closed

Thanks for the detailed bug report and suggestion for fix. Fix with properly namespaced attribute name committed to trunk in r1269 and backported to 0.7.x (r1270) and 0.6.x (r1271).

Note: See TracTickets for help on using tickets.