Esempio n. 1
0
    def assertXMLEqual(self, s1, s2, entity=None):
        """Assert that the two XML fragments are equal, tolerating the following
        variations:
          * whitespace outside of element content and attribute values.
          * order of attributes.
          * order of certain child elements (see `sort_elements` in this
            function).

        Parameters:
          * s1 and s2 are string representations of an XML fragment. The
            strings may be Unicode strings or UTF-8 encoded byte strings.
            The strings may contain an encoding declaration even when
            they are Unicode strings.

            Note: An encoding declaration is the `encoding` attribute in the
            XML declaration (aka XML processing statement), e.g.:
                <?xml version="1.0" encoding="utf-8" ?>
        """

        # Ensure Unicode strings and remove encoding from XML declaration
        encoding_pattern = re.compile(
            r'^<\?xml +(([a-zA-Z0-9_]+=".*")?) +' +
            r'encoding="utf-8" +(([a-zA-Z0-9_]+=".*")?) *\?>')
        encoding_repl = r'<?xml \1 \3 ?>'
        s1 = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s1))
        s2 = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s2))

        parser = etree.XMLParser(remove_blank_text=True)
        x1 = etree.XML(s1, parser=parser)
        x2 = etree.XML(s2, parser=parser)

        # Sort certain elements

        def sort_children(root, sort_elements):
            for tag, attr in sort_elements:
                # elems is a list of elements with this tag name
                elems = root.xpath("//*[local-name() = $tag]", tag=tag)
                if len(elems) > 0:
                    parent = elems[0].getparent()
                    first = None
                    after = None
                    for i in range(0, len(parent)):
                        if parent[i].tag == tag and first is None:
                            first = i
                        if parent[i].tag != tag and first is not None:
                            after = i
                    # The following changes the original XML tree:
                    # The following pylint warning can safely be disabled, see
                    # http://stackoverflow.com/a/25314665
                    # pylint: disable=cell-var-from-loop
                    parent[first:after] = sorted(elems,
                                                 key=lambda e: e.attrib[attr])

        sort_elements = [
            # Sort sibling elements with <first> tag by its <second> attribute
            ("IPARAMVALUE", "NAME"),
            ("PROPERTY", "NAME"),
            ("PARAMETER", "NAME"),
        ]
        sort_children(x1, sort_elements)
        sort_children(x2, sort_elements)

        ns1 = _ensure_unicode(etree.tostring(x1))
        ns2 = _ensure_unicode(etree.tostring(x2))

        checker = doctestcompare.LXMLOutputChecker()
        # This tolerates differences in whitespace and attribute order
        if not checker.check_output(ns1, ns2, 0):
            diff = checker.output_difference(doctest.Example("", ns1), ns2, 0)
            raise AssertionError("XML is not as expected in %s: %s"%\
                                 (entity, diff))
Esempio n. 2
0
    def assertXMLEqual(self, s1, s2, entity=None):
        """Assert that the two XML fragments are equal, tolerating the following
        variations:
          * whitespace outside of element content and attribute values.
          * order of attributes.
          * order of certain child elements (see `sort_elements` in this
            function).

        Parameters:
          * s1 and s2 are string representations of an XML fragment. The
            strings may be Unicode strings or UTF-8 encoded byte strings.
            The strings may contain an encoding declaration even when
            they are Unicode strings.

            Note: An encoding declaration is the `encoding` attribute in the
            XML declaration (aka XML processing statement), e.g.:
                <?xml version="1.0" encoding="utf-8" ?>
        """

        # Ensure Unicode strings and remove encoding from XML declaration
        encoding_pattern = re.compile(
            r'^<\?xml +(([a-zA-Z0-9_]+=".*")?) +' +
            r'encoding="utf-8" +(([a-zA-Z0-9_]+=".*")?) *\?>')
        encoding_repl = r'<?xml \1 \3 ?>'
        s1 = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s1))
        s2 = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s2))

        parser = etree.XMLParser(remove_blank_text=True)
        x1 = etree.XML(s1, parser=parser)
        x2 = etree.XML(s2, parser=parser)

        # Sort certain elements

        def sort_children(root, sort_elements):
            for tag, attr in sort_elements:
                # elems is a list of elements with this tag name
                elems = root.xpath("//*[local-name() = $tag]", tag=tag)
                if len(elems) > 0:
                    parent = elems[0].getparent()
                    first = None
                    after = None
                    for i in range(0, len(parent)):
                        if parent[i].tag == tag and first is None:
                            first = i
                        if parent[i].tag != tag and first is not None:
                            after = i
                    # The following changes the original XML tree:
                    # The following pylint warning can safely be disabled, see
                    # http://stackoverflow.com/a/25314665
                    # pylint: disable=cell-var-from-loop
                    parent[first:after] = sorted(elems,
                                                 key=lambda e: e.attrib[attr])

        sort_elements = [
            # Sort sibling elements with <first> tag by its <second> attribute
            ("IPARAMVALUE", "NAME"),
            ("PROPERTY", "NAME"),
            ("PARAMETER", "NAME"),
        ]
        sort_children(x1, sort_elements)
        sort_children(x2, sort_elements)

        ns1 = _ensure_unicode(etree.tostring(x1))
        ns2 = _ensure_unicode(etree.tostring(x2))

        checker = doctestcompare.LXMLOutputChecker()
        # This tolerates differences in whitespace and attribute order
        if not checker.check_output(ns1, ns2, 0):
            diff = checker.output_difference(doctest.Example("", ns1), ns2, 0)
            raise AssertionError("XML is not as expected in %s: %s"%\
                                 (entity, diff))
Esempio n. 3
0
    def assertXMLEqual(s_act, s_exp, entity=None):
        """Assert that the two XML fragments are equal, tolerating the following
        variations:
          * whitespace outside of element content and attribute values.
          * order of attributes.
          * order of certain child elements (see `sort_elements` in this
            function).

        Parameters:
          * s_act and s_exp are string representations of an XML fragment. The
            strings may be Unicode strings or UTF-8 encoded byte strings.
            The strings may contain an encoding declaration even when
            they are Unicode strings.

            Note: An encoding declaration is the `encoding` attribute in the
            XML declaration (aka XML processing statement), e.g.:
                <?xml version="1.0" encoding="utf-8" ?>
        """

        # Ensure Unicode strings and remove encoding from XML declaration
        encoding_pattern = re.compile(
            r'^<\?xml +(([a-zA-Z0-9_]+=".*")?) +' +
            r'encoding="utf-8" +(([a-zA-Z0-9_]+=".*")?) *\?>')
        encoding_repl = r'<?xml \1 \3 ?>'
        s_act = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s_act))
        s_exp = re.sub(encoding_pattern, encoding_repl, _ensure_unicode(s_exp))

        parser = etree.XMLParser(remove_blank_text=True)
        x_act = etree.XML(s_act, parser=parser)
        x_exp = etree.XML(s_exp, parser=parser)

        def sort_embedded(root, sort_elements):
            """
            Helper function for `sort_children()`, in support of embedded
            objects. This function invokes sort_children() on each embedded
            object in `root`, after unembedding the embedded object.

            Parameters:
              root (etree.Element):
                XML tree of the CIM-XML representation of the CIM element that
                contains an embedded CIM object (e.g. the CIM element may be
                an INSTANCE XML element and one of its PROPERTY child elements
                has a value that is an embedded CIM instance).
            """
            emb_elems = root.xpath("//*[@EmbeddedObject or @EMBEDDEDOBJECT]"
                                   "/*[local-name() = 'VALUE' or "
                                   "local-name() = 'VALUE.ARRAY']")
            for emb_elem in emb_elems:
                elem = xml_unembed(emb_elem.text)
                sort_children(elem, sort_elements)
                emb_elem.text = xml_embed(elem)

        def sort_children(root, sort_elements):
            """Sort certain elements in the `root` parameter to facilitate
               comparison of two XML documents.

               In addition, make sure this is also applied to any embedded
               objects (in their unembedded state).
            """
            sort_embedded(root, sort_elements)
            for tag, attr in sort_elements:
                # elems is a list of elements with this tag name
                elems = root.xpath("//*[local-name() = $tag]", tag=tag)
                if elems:
                    parent = elems[0].getparent()
                    first = None
                    after = None
                    for i in range(0, len(parent)):
                        if parent[i].tag == tag and first is None:
                            first = i
                        if parent[i].tag != tag and first is not None:
                            after = i
                    # The following changes the original XML tree:
                    # The following pylint warning can safely be disabled, see
                    # http://stackoverflow.com/a/25314665
                    # pylint: disable=cell-var-from-loop
                    parent[first:after] = sorted(elems,
                                                 key=lambda e: e.attrib[attr])

        sort_elements = [
            # Sort sibling elements with <first> tag by its <second> attribute
            ("IPARAMVALUE", "NAME"),
            ("PROPERTY", "NAME"),
            ("PROPERTY.ARRAY", "NAME"),
            ("PARAMETER", "NAME"),
            ("KEYBINDING", "NAME"),
        ]
        sort_children(x_act, sort_elements)
        sort_children(x_exp, sort_elements)

        ns_act = _ensure_unicode(etree.tostring(x_act))
        ns_exp = _ensure_unicode(etree.tostring(x_exp))

        checker = doctestcompare.LXMLOutputChecker()

        # This tolerates differences in whitespace and attribute order
        if not checker.check_output(ns_act, ns_exp, 0):
            diff = checker.output_difference(doctest.Example("", ns_exp),
                                             ns_act, 0)
            raise AssertionError("XML is not as expected in %s: %s" %
                                 (entity, diff))