Opened 15 years ago
Last modified 4 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 15 years ago by wyuenho@…
- Cc wyuenho@… added
comment:2 Changed 15 years ago by cmlenz
comment:3 Changed 15 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: ↓ 5 Changed 15 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 15 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 15 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 8 years ago by hodgestar
- Milestone changed from 0.6.1 to 0.9
Move to milestone 0.9.
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.