ElementTree - findall以递归方式选择所有子元素

时间:2015-05-07 10:08:54

标签: python xml python-2.7 recursion

Python代码:

import xml.etree.ElementTree as ET
root = ET.parse("h.xml")
print root.findall('saybye')

h.xml代码:

<hello>
  <saybye>
   <saybye>
   </saybye>
  </saybye>
  <saybye>
  </saybye>
</hello>

代码输出,

[<Element 'saybye' at 0x7fdbcbbec690>, <Element 'saybye' at 0x7fdbcbbec790>]
此处未选择

saybye这是另一个saybye的孩子。那么,如何指示findall递归地向下走DOM树并收集所有三个saybye元素?

4 个答案:

答案 0 :(得分:7)

从版本2.7开始,您可以使用.go-button { position: absolute; top: 4.6rem; margin-left: -3rem; } .project { flex-grow: 1; max-width: 30rem; background-size: auto 16.9rem; background-repeat: no-repeat; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; align-items: flex-end; background-position: center; justify-content: center; position: relative; }

xml.etree.ElementTree.Element.iter

请参阅19.7. xml.etree.ElementTree — The ElementTree XML API

答案 1 :(得分:2)

引用findall

  

>>> import xml.etree.ElementTree as ET >>> >>> def find_rec(node, element, result): ... for item in node.findall(element): ... result.append(item) ... find_rec(item, element, result) ... return result ... >>> find_rec(ET.parse("h.xml"), 'saybye', []) [<Element 'saybye' at 0x7f4fce206710>, <Element 'saybye' at 0x7f4fce206750>, <Element 'saybye' at 0x7f4fce2067d0>] 仅查找带有标记的元素,这些元素是当前元素的直接子元素。

由于它只找到直接子节点,我们需要递归地找到其他子节点,比如

>>> def find_rec(node, element):
...     for item in node.findall(element):
...         yield item
...         for child in find_rec(item, element):
...             yield child
... 
>>> list(find_rec(ET.parse("h.xml"), 'saybye'))
[<Element 'saybye' at 0x7f4fce206a50>, <Element 'saybye' at 0x7f4fce206ad0>, <Element 'saybye' at 0x7f4fce206b10>]

更好的是,使它成为一个生成器函数,就像这样

modulename.directive('passwordCheck', function () {

    return {
        restrict: 'A', // only activate on element attribute
        require: '?ngModel', // get a hold of NgModelController
        link: function (scope, elem, attrs, ngModel) {
            if (!ngModel) return; // do nothing if no ng-model

            var Value = null;

            // watch own value and re-validate on change
            scope.$watch(attrs.ngModel, function (val) {
                Value = val;


                validate();
            });

            // observe the other value and re-validate on change
            attrs.$observe('passwordCheck', function () {
                validate();
            });

            var validate = function () {

                // values
                var val1 = Value;
                var val2 = attrs.passwordCheck;

                // set validity

                if (val1 != '' && val1 != undefined) {
                    ngModel.$setValidity('passwordCheck', val1 == val2);

                }

                else {
                    ngModel.$setValidity('passwordCheck', true);
                }
            };
        }
    }
});

答案 2 :(得分:1)

如果您不怕XPath,可以使用//语法,该语法表示找到任何后代节点:

import xml.etree.ElementTree as ET
root = ET.parse("h.xml")
print root.findall('.//saybye')

不支持完整的XPath,但是下面是列表: https://docs.python.org/2/library/xml.etree.elementtree.html#supported-xpath-syntax

答案 3 :(得分:0)

  

Element.findall()仅查找带有标记的元素,这些元素是当前元素的直接子元素。

我们需要以递归方式遍历所有子节点,以找到与您的元素匹配的元素。

def find_rec(node, element):
    def _find_rec(node, element, result):
        for el in node.getchildren():
            _find_rec(el, element, result)
        if node.tag == element:
            result.append(node)
    res = list()
    _find_rec(node, element, res)
    return res