Example #1
0
    def removeChild(self, child, end_tag_too=True):
        """
        Remove subelement (`child`) specified by reference.

        Note:
            This can't be used for removing subelements by value! If you want
            to do such thing, try::

                for e in dom.find("value"):
                    dom.removeChild(e)

        Args:
            child (obj): :class:`HTMLElement` instance which will be removed
                         from this element.
            end_tag_too (bool, default True): Remove also `child` endtag.
        """
        # if there are multiple childs, remove them
        if _is_iterable(child):
            map(lambda x: self.removeChild(x, end_tag_too), child)
            return

        if not self.childs:
            return

        end_tag = None
        if end_tag_too:
            end_tag = child.endtag

        for e in self.childs:
            if e != child:
                e.removeChild(child, end_tag_too)
                continue

            if end_tag_too and end_tag in self.childs:
                self.childs.remove(end_tag)

            self.childs.remove(e)
Example #2
0
    def match(self, *args, **kwargs):
        """
        :meth:`wfind` is nice function, but still kinda long to use, because
        you have to manually chain all calls together and in the end, you get
        :class:`HTMLElement` instance container.

        This function recursively calls :meth:`wfind` for you and in the end,
        you get list of matching elements::

            xe = dom.match("root", "some", "something", "xe")

        is alternative to::

            xe = dom.wfind("root").wfind("some").wfind("something").wfind("xe")

        You can use all arguments used in :meth:`wfind`::

            dom = dhtmlparser.parseString('''
                <root>
                    <div id="1">
                        <div id="5">
                            <xe id="wanted xe" />
                        </div>
                        <div id="10">
                            <xe id="another wanted xe" />
                        </div>
                        <xe id="another xe" />
                    </div>
                    <div id="2">
                        <div id="20">
                            <xe id="last wanted xe" />
                        </div>
                    </div>
                </root>
            ''')

            xe = dom.match(
                "root",
                {"tag_name": "div", "params": {"id": "1"}},
                ["div", {"id": "5"}],
                "xe"
            )

            assert len(xe) == 1
            assert xe[0].params["id"] == "wanted xe"

        Args:
            *args: List of :meth:`wfind` parameters.
            absolute (bool, default None): If true, first element will be
                     searched from the root of the DOM. If None,
                     :attr:`_container` attribute will be used to decide value
                     of this argument. If False, :meth:`find` call will be run
                     first to find first element, then :meth:`wfind` will be
                     used to progress to next arguments.

        Returns:
            list: List of matching elements (empty list if no matching element\
                  is found).
        """
        if not args:
            return self.childs

        # pop one argument from argument stack (tuples, so .pop() won't work)
        act = args[0]
        args = args[1:]

        # this is used to define relative/absolute root of the first element
        def wrap_find(*args, **kwargs):
            """
            Find wrapper, to allow .wfind() to be substituted witřh .find()
            call, which normally returns blank array instead of blank
            `container` element.
            """
            el = self.__class__()  # HTMLElement()
            el.childs = self.find(*args, **kwargs)
            return el

        # if absolute is not specified (ie - next recursive call), use
        # self._container, which is set to True by .wfind(), so next search
        # will be absolute from the given element
        absolute = kwargs.get("absolute", None)
        if absolute is None:
            absolute = self._container

        find_func = self.wfind if absolute else wrap_find

        result = None
        if _is_iterable(act):
            result = find_func(*act)
        elif _is_dict(act):
            result = find_func(**act)
        elif _is_str(act):
            result = find_func(act)
        else:
            raise KeyError(
                "Unknown parameter type '%s': %s" % (type(act), act)
            )

        if not result.childs:
            return []

        match = result.match(*args)

        # just to be sure return always blank array, when the match is
        # False/None and so on (it shouldn't be, but ..)
        return match if match else []