Edgewall Software

Opened 14 years ago

Last modified 3 years ago

#386 new defect

py:match error when XPath selection returns multiple nodes

Reported by: anonymous Owned by: cmlenz
Priority: minor Milestone: 0.9
Component: Template processing Version: devel
Keywords: Cc: wyuenho@…

Description

I'm trying to figure out what is the expected behavior in a py:match template when the XPath selection returns more then 1 node. In Genshi 0.5.1, this wouldn't cause an error in lenient mode but I get an odd exception in 0.6. Is this an expected behavior, a regression, or undefined? I'm testing with this contrived template:

<head> 
  <meta py:match="head/meta" /> 
  <meta name="foo" content="bar" /> 
  <meta name="baz" content="boo" /> 

... I get this back:

Traceback (most recent call last): 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/CherryPy-3.1.2-py2.6.egg/cherrypy/_cprequest.py", line 606, 
in respond 
    cherrypy.response.body = self.handler() 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/CherryPy-3.1.2-py2.6.egg/cherrypy/_cpdispatch.py", line 25, 
in __call__ 
    return self.callable(*self.args, **self.kwargs) 
  File "<string>", line 2, in index 
  File "/Users/wyuenho/Documents/spiralup/spiralup/spiralup/views.py", 
line 223, in wrapper 
    *self.filters, **mapping) 
  File "/Users/wyuenho/Documents/spiralup/spiralup/spiralup/views.py", 
line 264, in render 
    return stream.render(method=format, doctype=doctype, 
encoding=encoding) 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/core.py", line 183, in render 
    return encode(generator, method=method, encoding=encoding, 
out=out) 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/output.py", line 57, in encode 
    return _encode(''.join(list(iterator))) 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/output.py", line 339, in __call__ 
    for kind, data, pos in stream: 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/output.py", line 826, in __call__ 
    for kind, data, pos in stream: 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/output.py", line 670, in __call__ 
    for kind, data, pos in stream: 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/output.py", line 771, in __call__ 
    for kind, data, pos in chain(stream, [(None, None, None)]): 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/output.py", line 586, in __call__ 
    for ev in stream: 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/core.py", line 288, in _ensure 
    for event in stream: 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/template/base.py", line 605, in 
_include 
    for event in stream: 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/template/markup.py", line 349, in 
_match 
    test(event, namespaces, ctxt, updateonly=True) 
  File "/Users/wyuenho/Documents/spiralup/spiralup/lib/python2.6/site- 
packages/Genshi-0.6-py2.6.egg/genshi/path.py", line 129, in _test 
    pos_queue = deque([(pos, cou, []) for pos, cou in stack[-1]]) 
IndexError: list index out of range 

This used to just return nothing in 0.5.1 under lenient mode.

Change History (8)

comment:1 Changed 14 years ago by wyuenho@…

  • Cc wyuenho@… added

comment:2 Changed 14 years ago by cmlenz

Can you please include a full “executable” example exposing the problem?

I've tried your example and it works for me, so I guess I'm just missing something.

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

I would consider this a won't fix.

Apart from that, if the user knows that there could be multiple nodes of the same element name, then he should do a for loop on all of those nodes.

comment:4 follow-up: Changed 14 years ago by Yuen Ho Wong <wyuenho@…>

I'm sorry for the delayed response and for a mistake in the XPATH.

It should be <meta py:match="head/meta[@name!='whatever']" />

Let me know if this still doesn't help.

comment:5 in reply to: ↑ 4 Changed 14 years ago by Carsten Klein <carsten.klein@…>

Replying to Yuen Ho Wong <wyuenho@…>:

I'm sorry for the delayed response and for a mistake in the XPATH.

It should be <meta py:match="head/meta[@name!='whatever']" />

Let me know if this still doesn't help.

Actually this is the same, you will get a number of meta elements back from the match expression, so you should rather loop over them instead of simply trying to output a single meta element.

Actually, I think that you have something like that in your template:

<py:match path="head">

  ...

</py:match>

So why not solve your problem by for example using a similar approach to the below untested example

<py:match path="head">

  ${select('meta[@name!="whatever"]')}

</py:match>

See also http://genshi.edgewall.org/wiki/Documentation/xml-templates.html#id5 for more information.

Still I would not consider this a bug since you instructed genshi to output a single element and selected multiple elements from your expression.

comment:6 Changed 14 years ago by wyuenho@…

As I've said in the description, the only thing that I think this is a bug is that I don't actually know what is the expected behavior when I do that under lenient and strict mode.

I actually have solved this problem using exactly your solution in my production code but that still doesn't tell me what exactly should happen when I'm matching with an XPATH that returns multiple elements.

The fact that Genshi 0.5.X and 0.6 give different bahavior is further indication that this behavior is undefined IMHO. So as long as it is defined, documented, and if the defined behavior is an exception, output a useful error, I'd be satisfied.

comment:7 Changed 13 years ago by hodgestar

  • Priority changed from critical to minor

comment:8 Changed 7 years ago by hodgestar

  • Milestone changed from 0.6.1 to 0.9

Move to milestone 0.9.

Note: See TracTickets for help on using tickets.