Edgewall Software

Opened 11 years ago

Last modified 4 years ago

#81 new defect

local-name() doesn't work with attributes

Reported by: dackze+genshi@… Owned by: cmlenz
Priority: major Milestone:
Component: XPath support Version: devel
Keywords: Cc: james.harris@…, remy.blank@…



<html xmlns="http://www.w3.org/1999/xhtml"
  <foo py:match="foo">
    ${select('@*[local-name() = "c"]')}

  <foo a="1" b="2" c="3" />

The following is produced:

<html xmlns="http://www.w3.org/1999/xhtml">

But you'd expect:

<html xmlns="http://www.w3.org/1999/xhtml">

select('@*[local-name() = "c"]') should be equivalent to select('@c').

Attachments (1)

xpath.patch (22.2 KB) - added by Carsten Klein <carsten.klein@…> 7 years ago.
Work in progress, just for review and comment

Download all attachments as: .zip

Change History (10)

comment:1 Changed 11 years ago by dackze+genshi@…

Here's a simpler test case:

from genshi.template import MarkupTemplate
a = list(MarkupTemplate('<z a="1" />').generate().select('@*[local-name() = "a"]'))
b = list(MarkupTemplate('<z a="1" />').generate().select('@a'))
assert a == b

comment:2 Changed 11 years ago by cmlenz

Oops, predicates don't take the axis of the node test into account :-P

Thanks for reporting this, I'll look into it.

comment:3 Changed 10 years ago by cmlenz

  • Milestone changed from 0.4 to 0.5

Not for 0.4, sorry.

comment:4 Changed 10 years ago by anonymous

  • Cc james.harris@… added

comment:5 Changed 10 years ago by cmlenz

  • Milestone 0.5 deleted

This one's going to be tricky… postponing so some future version.

comment:6 Changed 9 years ago by anonymous

This bug is very important, because there is no way to exclude an attribute from an attribute list in a match template.

Maybe you should use the XPATH 2.0 exclude operator for this purpose.

comment:7 Changed 7 years ago by Carsten Klein <carsten.klein@…>

I am currently working on this. Here is an initial, still incomplete proposal for a patch.

Currently the OP's original testcase will work.

The testcase in comment1 I consider invalid since the @* attribute axis selected is actually empty, see xpath spec. since we do not have a context element here. In the original testcase the context element is foo since that is being matched.

I also added the named axis parameter to the functions, but I think that this is redundant and can be omitted.

The operators definitely need additional work.

I am posting this here, so you can also have a look at it, perhaps providing additional information a/o continuing work on the patch.

comment:8 Changed 7 years ago by Carsten Klein <carsten.klein@…>

Testcase I am using is:

from genshi.template import MarkupTemplate
tpl = MarkupTemplate("""
<html xmlns="http://www.w3.org/1999/xhtml"
  <foo py:match="foo">
    ${select('@*[local-name() = "c" or local-name() = "b"]')}

  <foo a="1" b="2" c="3" />

And the output (stream) is as follows:

[('START_NS', ('', u'http://www.w3.org/1999/xhtml'), (None, 2, 0)), ('START', (QName('http://www.w3.org/1999/xhtml}html'), Attrs()), (None, 2, 0)), ('TEXT', u'\n  ', (None, 3, -1)), ('TEXT', u'\n\n  ', (None, 6, -1)), ('START', (QName('http://www.w3.org/1999/xhtml}foo'), Attrs()), (None, 4, 2)), ('TEXT', u'\n    ', (None, 4, -1)), ('TEXT', u'32', (None, -1, -1)), ('TEXT', u'\n  ', (None, 5, 57)), ('END', QName('http://www.w3.org/1999/xhtml}foo'), (None, 6, 2)), ('TEXT', u'\n', (None, 9, -1)), ('END', QName('http://www.w3.org/1999/xhtml}html'), (None, 9, 0)), ('END_NS', '', (None, 9, 0))]

As you can see, both attribute c and b are being selected and their values appear in the stream as ('TEXT', u'32', (None, -1, -1)).

IMPORTANT: The patch is considered work in progress and definitely breaks existing functionality, i.e. previously working templates will no longer work.

Changed 7 years ago by Carsten Klein <carsten.klein@…>

Work in progress, just for review and comment

comment:9 Changed 6 years ago by rblank

  • Cc remy.blank@… added

I stumbled upon this issue while trying to replace the value of an attribute in an element with a py:match:

<textarea py:match="form[@id='propertyform']//textarea[@id='comment']"
          py:attrs="select('@*[local-name()!=\'rows\']')" rows="20">

Is there another way to replace the value of a single attribute of an element than to copy the whole element except the attribute, and adding the new attribute?

Add Comment

Modify Ticket

Change Properties
Set your email in Preferences
as new The owner will remain cmlenz.
as The resolution will be set. Next status will be 'closed'.
to The owner will be changed from cmlenz to the specified user. Next status will be 'new'.
The owner will be changed from cmlenz to anonymous. Next status will be 'assigned'.

E-mail address and user name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.