Frank Millman wrote: > Hi all > > I usually send lxml queries to the lxml mailing list, but it appears to > be not working, so I thought I would try here. > > This is a minor issue, and I have found an ugly workaround, but I > thought I would mention it.
Like this? children = list(xml) for y in children: print(etree.tostring(y)) if y.get('z') == 'c': child = etree.Element('y', attrib={'z': 'd'}) xml.append(child) children.append(child) It doesn't look /that/ ugly to me. > In Python I can iterate through a list, and on a certain condition > append a new item to the list, which is then included in the iteration. Personally I follow the rule "never mutate a list you are iterating over", even for appends, where the likelihood of problems is small: items = ["a"] for item in items: if item == "a": items.append("a") > >>> x = ['a', 'b', 'c'] > >>> for y in x: > ... print(y) > ... if y == 'b': > ... x.append('d') > ... > a > b > c > d > >>> x > ['a', 'b', 'c', 'd'] > >>> > > The same thing works in lxml - > > >>> lmx = '<x><y z="a"/><y z="b"/><y z="c"/></x>' > >>> xml = etree.fromstring(lmx) > >>> for y in xml: > ... print(etree.tostring(y)) > ... if y.get('z') == 'b': > ... xml.append(etree.Element('y', attrib={'z': 'd'})) > ... > b'<y z="a"/>' > b'<y z="b"/>' > b'<y z="c"/>' > b'<y z="d"/>' > >>> etree.tostring(xml) > b'<x><y z="a"/><y z="b"/><y z="c"/><y z="d"/></x>' > > However, if it happens that the condition is met on the last item in the > list, Python still works, but lxml does not include the appended item in > the iteration. In the following, the only change is checking for 'c' > instead of 'b'. > > >>> x = ['a', 'b', 'c'] > >>> for y in x: > ... print(y) > ... if y == 'c': > ... x.append('d') > ... > a > b > c > d > >>> x > ['a', 'b', 'c', 'd'] > >>> > > >>> lmx = '<x><y z="a"/><y z="b"/><y z="c"/></x>' > >>> xml = etree.fromstring(lmx) > >>> for y in xml: > ... print(etree.tostring(y)) > ... if y.get('z') == 'c': > ... xml.append(etree.Element('y', attrib={'z': 'd'})) > ... > b'<y z="a"/>' > b'<y z="b"/>' > b'<y z="c"/>' > >>> etree.tostring(xml) > b'<x><y z="a"/><y z="b"/><y z="c"/><y z="d"/></x>' > > As you can see, the last element is correctly appended, but is not > included in the iteration. > > Is there any chance that this can be looked at, or is it just the way it > works? File a bug report and see if the author is willing to emulate the list behaviour. > BTW, I see that ElementTree in the standard library does not have this > problem. Maybe uses a list under the hood. -- https://mail.python.org/mailman/listinfo/python-list