Repository: miurahr/aqtinstall
Pull request #533 (2022-06-09 15:36:42)

Introduce Updates.xml data class and parser
1. Introduce Updates.xml data class and parser

- PackageUpdate data class to hold a packageupdate section of Updates.xml 
- Updates data class to hold Updates.xml data

2. Use Updates class to handle Updates.xml in archvies package

Signed-off-by: Hiroshi Miura <miurahr@linux.com>



Patch:
diff --git a/aqt/archives.py b/aqt/archives.py
index fdb141a..eb694f8 100644
--- a/aqt/archives.py
+++ b/aqt/archives.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 #
 # Copyright (C) 2018 Linus Jahn <lnj@kaidan.im>
-# Copyright (C) 2019-2021 Hiroshi Miura <miurahr@linux.com>
+# Copyright (C) 2019-2022 Hiroshi Miura <miurahr@linux.com>
 #
 # Permission is hereby granted, free of charge, to any person obtaining a copy of
 # this software and associated documentation files (the "Software"), to deal in
@@ -112,6 +112,150 @@ class ModuleToPackage:
         return str(sorted(set(self._modules_to_packages.keys())))
 
 
+@dataclass
+class PackageUpdate:
+    """
+    Data class to hold package data.
+    key is its name.
+    """
+
+    name: str
+    display_name: str
+    description: str
+    release_date: str
+    full_version: str
+    dependencies: List[str]
+    auto_dependon: Optional[List[str]]
+    downloadable_archives: Optional[List[str]]
+    default: bool
+    virtual: bool
+    base: str
+
+    @property
+    def version(self):
+        return Version.permissive(self.full_version)
+
+    @property
+    def arch(self):
+        return self.name.split(".")[-1]
+
+    def is_base_package(self) -> bool:
+        return self.name in (
+            f"qt.qt{self.version.major}.{self._version_str()}.{self.arch}",
+            f"qt.{self._version_str()}.{self.arch}",
+        )
+
+    def _version_str(self) -> str:
+        return ("{0.major}{0.minor}" if self.version == Version("5.9.0") else "{0.major}{0.minor}{0.patch}").format(
+            self.version
+        )
+
+
+@dataclass(init=False)
+class Updates:
+    package_updates: List[PackageUpdate]
+
+    def __init__(self):
+        self.package_updates = []
+
+    def extend(self, other):
+        self.package_updates.extend(other.package_updates)
+
+    @staticmethod
+    def fromstring(base, update_xml_text: str):
+        try:
+            update_xml = ElementTree.fromstring(update_xml_text)
+        except ElementTree.ParseError as perror:
+            raise ArchiveListError(f"Downloaded metadata is corrupted. {perror}") from perror
+        updates = Updates()
+        for packageupdate in update_xml.iter("PackageUpdate"):
+            pkg_name = updates._get_text(packageupdate.find("Name"))
+            display_name = updates._get_text(packageupdate.find("DisplayName"))
+            full_version = updates._get_text(packageupdate.find("Version"))
+            package_desc = updates._get_text(packageupdate.find("Description"))
+            release_date = updates._get_text(packageupdate.find("ReleaseDate"))
+            dependencies = updates._get_list(packageupdate.find("Dependencies"))
+            auto_dependon = updates._get_list(packageupdate.find("AutoDependOn"))
+            archives = updates._get_list(packageupdate.find("DownloadableArchives"))
+            default = updates._get_boolean(packageupdate.find("Default"))
+            virtual = updates._get_boolean(packageupdate.find("Virtual"))
+            updates.package_updates.append(
+                PackageUpdate(
+                    pkg_name,
+                    display_name,
+                    package_desc,
+                    release_date,
+                    full_version,
+                    dependencies,
+                    auto_dependon,
+                    archives,
+                    default,
+                    virtual,
+                    base,
+                )
+            )
+        return updates
+
+    def get(self, target: Optional[str] = None):
+        if target is None:
+            return self.package_updates
+        for update in self.package_updates:
+            if update.name == target:
+                return update
+        return None
+
+    def get_from(self, arch: str, is_include_base: bool, target_packages: Optional[ModuleToPackage] = None):
+        result = []
+        for update in self.package_updates:
+            # If we asked for `--noarchives`, we don't want the base module
+            if not is_include_base and update.is_base_package():
+                continue
+            if target_packages is not None and not target_packages.has_package(update.name):
+                continue
+            if arch in update.name:
+                result.append(update)
+        return result
+
+    def merge(self, other):
+        self.package_updates.extend(other.package_updates)
+
+    def get_depends(self, target: str):
+        # initialize
+        filo = [target]
+        packages = []
+        visited = []
+        # dfs look-up
+        while len(filo) > 0:
+            next = filo.pop()
+            packages.append(next)
+            for entry in self.package_updates:
+                if entry.name == next:
+                    visited.append(next)
+                    if entry.dependencies is not None:
+                        for depend in entry.dependencies:
+                            if depend not in visited:
+                                filo.append(depend)
+        return packages
+
+    def _get_text(self, item):
+        if item is not None and item.text is not None:
+            return item.text
+        else:
+            return ""
+
+    def _get_list(self, item):
+        if item is not None and item.text is not None:
+            return ssplit(item.text)
+        else:
+            return None
+
+    def _get_boolean(self, item):
+        if "true" == item:
+            return True
+        else:
+            return False
+
+
 class QtArchives:
     """Download and hold Qt archive packages list.
     It access to download.qt.io site and get Update.xml file.
@@ -212,18 +356,31 @@ class QtArchives:
         return target_packages
 
     def _get_archives(self):
-        # Get packages index
+        self._get_archives_base(f"qt{self.version.major}_{self._version_str()}{self._arch_ext()}", self._target_packages())
 
-        # os_target_folder: online/qtsdkrepository/windows_x86/desktop/qt5_59_src_doc_examples
+    def _append_depends_tool(self, arch, tool_name):
         os_target_folder = posixpath.join(
             "online/qtsdkrepository",
             self.os_name + ("_x86" if self.os_name == "windows" else "_x64"),
             self.target,
-            f"qt{self.version.major}_{self._version_str()}{self._arch_ext()}",
+            tool_name,
         )
-        update_xml_path = posixpath.join(os_target_folder, "Updates.xml")
-        update_xml_text = self._download_update_xml(update_xml_path)
-        self._parse_update_xml(os_target_folder, update_xml_text, self._target_packages())
+        update_xml_url = posixpath.join(os_target_folder, "Updates.xml")
+        update_xml_text = self._download_update_xml(update_xml_url)
+        update_xml = Updates.fromstring(self.base, update_xml_text)
+        self._append_tool_update(os_target_folder, update_xml, arch, None)
+
+    def _get_archives_base(self, name, target_packages):
+        os_target_folder = posixpath.join(
+            "online/qtsdkrepository",
+            self.os_name + ("_x86" if self.os_name == "windows" else "_x64"),
+            self.target,
+            # tools_ifw/
+            name,
+        )
+        update_xml_url = posixpath.join(os_target_folder, "Updates.xml")
+        update_xml_text = self._download_update_xml(update_xml_url)
+        self._parse_update_xml(os_target_folder, update_xml_text, target_packages)
 
     def _download_update_xml(self, update_xml_path):
         """Hook for unit test."""
@@ -233,38 +390,18 @@ class QtArchives:
     def _parse_update_xml(self, os_target_folder, update_xml_text, target_packages: Optional[ModuleToPackage]):
         if not target_packages:
             target_packages = ModuleToPackage({})
-        try:
-            self.update_xml = ElementTree.fromstring(update_xml_text)
-        except ElementTree.ParseError as perror:
-            raise ArchiveListError(f"Downloaded metadata is corrupted. {perror}") from perror
-
-        for packageupdate in self.update_xml.iter("PackageUpdate"):
-            pkg_name = packageupdate.find("Name").text
-            downloads_text = packageupdate.find("DownloadableArchives").text
-            if not downloads_text:
-                continue
-            # If we asked for `--noarchives`, we don't want the base module
-            if not self.is_include_base_package and pkg_name in self._base_package_names():
-                continue
-            # Need to filter archives to download when we want all extra modules
-            if self.all_extra:
-                # Check platform
-                name_last_section = pkg_name.split(".")[-1]
-                if name_last_section in self.arch_list and self.arch != name_last_section:
-                    continue
-                # Check doc/examples
-                if self.arch in ["doc", "examples"]:
-                    if self.arch not in pkg_name:
-                        continue
-            elif not target_packages.has_package(pkg_name):
-                continue
-            else:
-                target_packages.remove_module_for_package(pkg_name)
-            full_version = packageupdate.find("Version").text
-            package_desc = packageupdate.find("Description").text
-            should_filter_archives: bool = self.subarchives and self.should_filter_archives(pkg_name)
-
-            for archive in ssplit(downloads_text):
+        update_xml = Updates.fromstring(self.base, update_xml_text)
+        base_url = self.base
+        if self.all_extra:
+            package_updates = update_xml.get_from(self.arch, self.is_include_base_package)
+        else:
+            package_updates = update_xml.get_from(self.arch, self.is_include_base_package, target_packages)
+        for packageupdate in package_updates:
+            if not self.all_extra:
+                target_packages.remove_module_for_package(packageupdate.name)
+            should_filter_archives: bool = self.subarchives and self.should_filter_archives(packageupdate.name)
+
+            for archive in packageupdate.downloadable_archives:
                 archive_name = archive.split("-", maxsplit=1)[0]
                 if should_filter_archives and archive_name not in self.subarchives:
                     continue
@@ -272,26 +409,60 @@ class QtArchives:
                     # online/qtsdkrepository/linux_x64/desktop/qt5_5150/
                     os_target_folder,
                     # qt.qt5.5150.gcc_64/
-                    pkg_name,
+                    packageupdate.name,
                     # 5.15.0-0-202005140804qtbase-Linux-RHEL_7_6-GCC-Linux-RHEL_7_6-X86_64.7z
-                    full_version + archive,
+                    packageupdate.full_version + archive,
                 )
                 self.archives.append(
                     QtPackage(
                         name=archive_name,
-                        base_url=self.base,
+                        base_url=base_url,
                         archive_path=archive_path,
                         archive=archive,
-                        package_desc=package_desc,
-                        pkg_update_name=pkg_name,  # For testing purposes
+                        package_desc=packageupdate.description,
+                        pkg_update_name=packageupdate.name,  # For testing purposes
                     )
                 )
-
         # if we have located every requested package, then target_packages will be empty
-        if len(target_packages) > 0:
+        if not self.all_extra and len(target_packages) > 0:
             message = f"The packages {target_packages} were not found while parsing XML of package information!"
             raise NoPackageFound(message, suggested_action=self.help_msg(target_packages.get_modules()))
 
+    def _append_tool_update(self, os_target_folder, update_xml, target, tool_version_str):
+        packageupdate = update_xml.get(target)
+        if packageupdate is None:
+            message = f"The package '{self.arch}' was not found while parsing XML of package information!"
+            raise NoPackageFound(message, suggested_action=self.help_msg())
+        name = packageupdate.name
+        named_version = packageupdate.full_version
+        if tool_version_str and named_version != tool_version_str:
+            message = f"The package '{self.arch}' has the version '{named_version}', not the requested '{self.version}'."
+            raise NoPackageFound(message, suggested_action=self.help_msg())
+        package_desc = packageupdate.description
+        downloadable_archives = packageupdate.downloadable_archives
+        if not downloadable_archives:
+            message = f"The package '{self.arch}' contains no downloadable archives!"
+            raise NoPackageFound(message)
+        for archive in downloadable_archives:
+            archive_path = posixpath.join(
+                # online/qtsdkrepository/linux_x64/desktop/tools_ifw/
+                os_target_folder,
+                # qt.tools.ifw.41/
+                name,
+                #  4.1.1-202105261130ifw-linux-x64.7z
+                f"{named_version}{archive}",
+            )
+            self.archives.append(
+                QtPackage(
+                    name=name,
+                    base_url=self.base,
+                    archive_path=archive_path,
+                    archive=archive,
+                    package_desc=package_desc,
+                    pkg_update_name=name,  # Redundant
+                )
+            )
+
     def help_msg(self, missing_modules: Iterable[str]) -> Iterable[str]:
         base_cmd = f"aqt list-qt {self.os_name} {self.target}"
         arch = f"Please use '{base_cmd} --arch {self.version}' to show architectures available."
@@ -428,60 +599,11 @@ class ToolArchives(QtArchives):
         raise ArchiveListError(msg, suggested_action=[help_msg]) from e
 
     def _get_archives(self):
-        os_target_folder = posixpath.join(
-            "online/qtsdkrepository",
-            # linux_x64/
-            self.os_name + ("_x86" if self.os_name == "windows" else "_x64"),
-            # desktop/
-            self.target,
-            # tools_ifw/
-            self.tool_name,
-        )
-        update_xml_url = posixpath.join(os_target_folder, "Updates.xml")
-        update_xml_text = self._download_update_xml(update_xml_url)  # call super method.
-        self._parse_update_xml(os_target_folder, update_xml_text, None)
+        self._get_archives_base(self.tool_name, None)
 
     def _parse_update_xml(self, os_target_folder, update_xml_text, *ignored):
-        try:
-            self.update_xml = ElementTree.fromstring(update_xml_text)
-        except ElementTree.ParseError as perror:
-            raise ArchiveListError(f"Downloaded metadata is corrupted. {perror}") from perror
-
-        try:
-            packageupdate = next(filter(lambda x: x.find("Name").text == self.arch, self.update_xml.iter("PackageUpdate")))
-        except StopIteration:
-            message = f"The package '{self.arch}' was not found while parsing XML of package information!"
-            raise NoPackageFound(message, suggested_action=self.help_msg())
-
-        name = packageupdate.find("Name").text
-        named_version = packageupdate.find("Version").text
-        if self.tool_version_str and named_version != self.tool_version_str:
-            message = f"The package '{self.arch}' has the version '{named_version}', not the requested '{self.version}'."
-            raise NoPackageFound(message, suggested_action=self.help_msg())
-        package_desc = packageupdate.find("Description").text
-        downloadable_archives = packageupdate.find("DownloadableArchives").text
-        if not downloadable_archives:
-            message = f"The package '{self.arch}' contains no downloadable archives!"
-            raise NoPackageFound(message)
-        for archive in ssplit(downloadable_archives):
-            archive_path = posixpath.join(
-                # online/qtsdkrepository/linux_x64/desktop/tools_ifw/
-                os_target_folder,
-                # qt.tools.ifw.41/
-                name,
-                #  4.1.1-202105261130ifw-linux-x64.7z
-                f"{named_version}{archive}",
-            )
-            self.archives.append(
-                QtPackage(
-                    name=name,
-                    base_url=self.base,
-                    archive_path=archive_path,
-                    archive=archive,
-                    package_desc=package_desc,
-                    pkg_update_name=name,  # Redundant
-                )
-            )
+        update_xml = Updates.fromstring(self.base, update_xml_text)
+        self._append_tool_update(os_target_folder, update_xml, self.arch, self.tool_version_str)
 
     def help_msg(self, *args) -> Iterable[str]:
         return [f"Please use 'aqt list-tool {self.os_name} {self.target} {self.tool_name}' to show tool variants available."]


Test patch:
diff --git a/tests/data/windows-620-android-armv7-update.xml b/tests/data/windows-620-android-armv7-update.xml
new file mode 100644
index 0000000..c8e7e0d
--- /dev/null
+++ b/tests/data/windows-620-android-armv7-update.xml
@@ -0,0 +1,682 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qt3d</Name>
+  <DisplayName>Qt 3D</DisplayName>
+  <Description>Qt 3D Prebuilt Components for Qt 6.2.0. Qt 3D provides functionality for near-realtime simulation systems with support for 2D and 3D rendering in both Qt C++ and Qt Quick applications.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qt3d, qt.qt6.620.examples.qt3d</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>24d9d9023ec770d0a9b7975c89a2b60bc52b7429</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qt3d.android_armv7</Name>
+  <DisplayName>Qt 3D for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qt3d, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qt3d-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="1856413" OS="Any" UncompressedSize="11961143"/>
+  <SHA1>9b94de52bec3443a74d2291464d5796986002702</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtcharts</Name>
+  <DisplayName>Qt Charts</DisplayName>
+  <Description>The Qt Charts API lets you easily create interactive and dynamic 2D charts using C++ and/or Qt Quick.&lt;br>&lt;br>This component is available under commercial licenses from The Qt Company, or under GPL v3. For open source use, please note the additional requirements compared to LGPL v3.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtcharts, qt.qt6.620.examples.qtcharts</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>78f143c904807ebc270bf958f02638e6953a5e96</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtcharts.android_armv7</Name>
+  <DisplayName>Qt Charts for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtcharts, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtcharts-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="527532" OS="Any" UncompressedSize="3595616"/>
+  <SHA1>89c4d30fbe08a5fba40e735e429b7471160af2f2</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtconnectivity</Name>
+  <DisplayName>Qt Connectivity</DisplayName>
+  <Description>This component includes two Qt modules. The two modules provide access to Bluetooth and NFC hardware.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtbluetooth, qt.qt6.620.doc.qtnfc, qt.qt6.620.examples.qtconnectivity</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>219000422fa00283dc1eed70c3d5f9934f64207d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtconnectivity.android_armv7</Name>
+  <DisplayName>Qt Connectivity for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtconnectivity, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtconnectivity-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="242524" OS="Any" UncompressedSize="1200522"/>
+  <SHA1>c775cbb4284db249da6671346cab862947b31711</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtdatavis3d</Name>
+  <DisplayName>Qt Data Visualization</DisplayName>
+  <Description>Qt Data Visualization is a module which provides a way to visualize data in 3D. There are C++ classes and QML types for displaying bar graphs, scatter graphs, surface graphs and ways of manipulating the 3D scene. In addition, the graphs are fully customizable with different themes.&lt;br>&lt;br>This component is available under commercial licenses from The Qt Company, or under GPL v3. For open source use, please note the additional requirements compared to LGPL v3.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtdatavis3d, qt.qt6.620.examples.qtdatavis3d</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>ed0a8d323450de05cc46f7ab7b9f8c53c2ea938d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtdatavis3d.android_armv7</Name>
+  <DisplayName>Qt Data Visualization for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtdatavis3d, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtdatavis3d-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="422662" OS="Any" UncompressedSize="2321778"/>
+  <SHA1>dd3d366122457c02338cc986fe423182809b9e0d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtimageformats</Name>
+  <DisplayName>Qt Image Formats</DisplayName>
+  <Description>The Qt Image Formats  provides optional support for other image file formats. The core Qt Gui library by default supports reading and writing image files of the most common file formats: PNG, JPEG, BMP, GIF and a few more.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtimageformats, qt.qt6.620.examples.qtimageformats</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>407e9d02cb4f057c5f20c884c541aad294e5bd8d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtimageformats.android_armv7</Name>
+  <DisplayName>Qt Image Formats for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtimageformats, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtimageformats-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="244532" OS="Any" UncompressedSize="653201"/>
+  <SHA1>81b832c32de6c230b6f06b9e7954cf99ffff730d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtlottie</Name>
+  <DisplayName>Qt Lottie Animation</DisplayName>
+  <Description>Qt Lottie Animation provides a QML API for rendering graphics and animations that are exported in JSON format by the Bodymovin plugin for Adobe After Effects.&lt;br>&lt;br>This component is available under commercial licenses from The Qt Company, or under GPL v3. For open source use, please note the additional requirements compared to LGPL v3.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtlottie, qt.qt6.620.examples.qtlottie</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>303e59b5ddf9582cd993a0186c3d598e3b774e08</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtlottie.android_armv7</Name>
+  <DisplayName>Qt Lottie Animation for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtlottie, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtlottie-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="87196" OS="Any" UncompressedSize="353104"/>
+  <SHA1>01521a13562e077ab94ef75f5e6b746524c89f68</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtmultimedia</Name>
+  <DisplayName>Qt Multimedia</DisplayName>
+  <Description>Qt Multimedia provides a rich set of QML types and C++ classes to handle multimedia content.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtmultimedia, qt.qt6.620.examples.qtmultimedia</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>bd25e82d51ff56000924e1b31dbccde6cbfd2473</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtmultimedia.android_armv7</Name>
+  <DisplayName>Qt Multimedia for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtmultimedia, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtmultimedia-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="372963" OS="Any" UncompressedSize="2233753"/>
+  <SHA1>bed56dd5472634564a55aa682f7e0240b790f2dd</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtnetworkauth</Name>
+  <DisplayName>Qt Network Authorization</DisplayName>
+  <Description>Qt Network Authorization provides a set of APIs that enable Qt applications to obtain limited access to online accounts and HTTP services without exposing users' passwords.&lt;br>&lt;br>This component is available under commercial licenses from The Qt Company, or under GPL v3. For open source use, please note the additional requirements compared to LGPL v3.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtnetworkauth, qt.qt6.620.examples.qtnetworkauth</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>8862cb872938cc8317af07059c9eb2e5e13a2524</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtnetworkauth.android_armv7</Name>
+  <DisplayName>Qt Network Authorization for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtnetworkauth, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtnetworkauth-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="55777" OS="Any" UncompressedSize="253083"/>
+  <SHA1>93d644ffa23ed10b710cf10d6a988a7ec6f2f491</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtpositioning</Name>
+  <DisplayName>Qt Positioning</DisplayName>
+  <Description>The Qt Positioning API provides positioning information via QML and C++ interfaces.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtpositioning, qt.qt6.620.examples.qtpositioning</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>e74cf611cd992ae6d3cd921fa7a283091c0f3751</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtpositioning.android_armv7</Name>
+  <DisplayName>Qt Positioning for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtpositioning, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtlocation-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="247882" OS="Any" UncompressedSize="1243729"/>
+  <SHA1>242824b3ea124913eb8fdff1800121771f188601</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtremoteobjects</Name>
+  <DisplayName>Qt Remote Objects</DisplayName>
+  <Description>Qt Remote Objects is an add-on library that provides an easy way to share Qt APIs between processes/devices.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtremoteobjects, qt.qt6.620.examples.qtremoteobjects</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>fb8da532b17ef805537ef9c07205facd2613305e</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtremoteobjects.android_armv7</Name>
+  <DisplayName>Qt Remote Objects ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtremoteobjects, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtremoteobjects-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="210059" OS="Any" UncompressedSize="1028312"/>
+  <SHA1>ac9098f995ce79f066575a2e236c90ddb0ddc880</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtscxml</Name>
+  <DisplayName>Qt State Machines</DisplayName>
+  <Description>The Qt State Machines package provides API's and execution models that can be used to effectively embed the elements and semantics of statecharts in Qt applications. For advanced use cases the state machines can even be created from State Chart XML (SCXML) files.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtscxml, qt.qt6.620.examples.qtscxml</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>3332fa6c9dec243f55f77037f5ac7e552b98538a</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtscxml.android_armv7</Name>
+  <DisplayName>Qt State Machine for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtscxml, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtscxml-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="237593" OS="Any" UncompressedSize="1308204"/>
+  <SHA1>9a3b224e913d2f697cc7ea450edf0d1b74770837</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtsensors</Name>
+  <DisplayName>Qt Sensors</DisplayName>
+  <Description>Qt Sensors provides classes for reading sensor data.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtsensors, qt.qt6.620.examples.qtsensors</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>57cc88ab6050083e7f356d26459a45e0f666ef6d</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtsensors.android_armv7</Name>
+  <DisplayName>Qt Sensors ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtsensors, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtsensors-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="133521" OS="Any" UncompressedSize="989760"/>
+  <SHA1>15f3165faef4d53281b4d5a6434250cc4c1fc06c</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtserialbus</Name>
+  <DisplayName>Qt Serial Bus</DisplayName>
+  <Description>The Qt Serial Bus API provides classes and functions to access the various industrial serial buses and protocols, such as CAN, ModBus, and others.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtserialbus, qt.qt6.620.examples.qtserialbus</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>c03484e5562f17f29b7d0eab04c5c663cfdae02c</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtserialbus.android_armv7</Name>
+  <DisplayName>Qt SerialBus ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtserialbus, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtserialbus-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="118161" OS="Any" UncompressedSize="553256"/>
+  <SHA1>6835b3db8e1dcbd15e1d893979c1722416fcb6f4</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtserialport</Name>
+  <DisplayName>Qt Serial Port</DisplayName>
+  <Description>Qt Serial Port provides the basic functionality, which includes configuring, I/O operations, getting and setting the control signals of the RS-232 pinouts.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtserialport, qt.qt6.620.examples.qtserialport</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>9339712d26cf2455e99bfb2bb7081664dc4724e6</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtserialport.android_armv7</Name>
+  <DisplayName>Qt SerialPort ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtserialport, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtserialport-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="38595" OS="Any" UncompressedSize="154475"/>
+  <SHA1>5227861940fa56356d52c6f6b3b590c2318be660</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtvirtualkeyboard</Name>
+  <DisplayName>Qt Virtual Keyboard</DisplayName>
+  <Description>The Qt Virtual Keyboard is a Qt Quick virtual keyboard that you can plug in to your platform or application. You can extend it with your ownlayouts and styles.&lt;br>&lt;br>This component is available under commercial licenses from The Qt Company, or under GPL v3. For open source use, please note the additional requirements compared to LGPL v3.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtvirtualkeyboard, qt.qt6.620.examples.qtvirtualkeyboard</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>f54bbbf14da76ba8d58e56f55ce44986c3e1ff97</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtvirtualkeyboard.android_armv7</Name>
+  <DisplayName>Qt Virtual Keyboard for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtvirtualkeyboard, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtvirtualkeyboard-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="2001544" OS="Any" UncompressedSize="4491867"/>
+  <SHA1>9055acbc65c6dacd3b9f22ec754365baa2eafc95</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtwebchannel</Name>
+  <DisplayName>Qt WebChannel</DisplayName>
+  <Description>Qt WebChannel enables peer-to-peer communication between a server (QML/C++ application) and a client (HTML/JavaScript or QML application). It is supported out of the box by Qt WebEngine. In addition it can work on all browsers that support WebSockets, enabling Qt WebChannel clients to run in any JavaScript environment (including QML). This requires the implementation of a custom transport based on Qt WebSockets.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtwebchannel, qt.qt6.620.examples.qtwebchannel</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>9b19486db6276081fc6e068e7259c8d19c066ef2</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtwebchannel.android_armv7</Name>
+  <DisplayName>Qt WebChannel for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtwebchannel, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtwebchannel-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="69249" OS="Any" UncompressedSize="269827"/>
+  <SHA1>525fda02673646aeff2d795412a8a965b12f952b</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtwebsockets</Name>
+  <DisplayName>Qt WebSockets</DisplayName>
+  <Description>WebSocket is a web-based protocol designed to enable two-way communication between a client application and a remote host. It enables the two entities to send data back and forth if the initial handshake succeeds. WebSocket is the solution for applications that struggle to get real-time data feeds with less network latency and minimum data exchange.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtwebsockets, qt.qt6.620.examples.qtwebsockets</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>efd3baf28e0bf65fa373a72aaf40686658dffcf6</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtwebsockets.android_armv7</Name>
+  <DisplayName>Qt WebSockets for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtwebsockets, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtwebsockets-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="68585" OS="Any" UncompressedSize="314348"/>
+  <SHA1>4ca4155694e4f61a4d820e990dc9eaaca6801346</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtwebview</Name>
+  <DisplayName>Qt WebView</DisplayName>
+  <Description>Qt WebView provides a way to display web content in a QML application without necessarily including a full web browser stack by using native APIs where it makes sense. This is useful on mobile platforms such as Android, iOS, and UWP (Universal Windows Platform); especially on iOS, where policy dictates that all web content is displayed using the operating system's web view. On Windows, Linux, and macOS, Qt WebView depends on the Qt WebEngine module to render content.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtwebview, qt.qt6.620.examples.qtwebview</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>2fbc5f725f03244090c4aaf01d4fcffd391ab7a9</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.addons.qtwebview.android_armv7</Name>
+  <DisplayName>Qt WebView for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.addons.qtwebview, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtwebview-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="64683" OS="Any" UncompressedSize="287687"/>
+  <SHA1>b87b63ca4b1c0d039c9fdccbc7d9c31466cce8aa</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.android_armv7</Name>
+  <DisplayName>Android ARMv7</DisplayName>
+  <Description>Qt 6.2.0 Prebuilt Components for Android ARMv7</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator, qt.qt6.620.doc, qt.qt6.620.examples</Dependencies>
+  <AutoDependOn/>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority>250</SortingPriority>
+  <DownloadableArchives>qtbase-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z, qtsvg-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z, qtdeclarative-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z, qttools-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z, qttranslations-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z, x86_64-8.1.0-release-posix-seh-rt_v6-rev0-runtime.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="40812178" OS="Any" UncompressedSize="320312244"/>
+  <SHA1>9a336d012d8579d8b202e20ce61a0d0b3cdffe3e</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.qt5compat</Name>
+  <DisplayName>Qt 5 Compatibility Module</DisplayName>
+  <Description>Qt 5 Compatibility Module Prebuilt Components for Qt 6.2.0. Qt 5 Compatibility Module allows to continue using some dedicated functionality which has been removed in Qt 6.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qt5compat, qt.qt6.620.examples.qt5compat</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>aef50f57c43f6957cd77dff9ae9b9cd74383ead1</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.qt5compat.android_armv7</Name>
+  <DisplayName>Qt 5 Compatibility Module for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.qt5compat, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qt5compat-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="494273" OS="Any" UncompressedSize="1499925"/>
+  <SHA1>820e285d800592b5716de2fae9e6e06fa044e893</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.qtquick3d</Name>
+  <DisplayName>Qt Quick 3D</DisplayName>
+  <Description>Qt Quick 3D provides high-level 3D API for Qt Quick.&lt;br>&lt;br>This component is available under commercial licenses from The Qt Company, or under GPL v3. For open source use, please note the additional requirements compared to LGPL v3.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>89</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtquick3d, qt.qt6.620.examples.qtquick3d, qt.qt6.620.qtshadertools, qt.qt6.620.qtquicktimeline</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>7c725e1b4c6753e7830de67f02c5b3a2f6930e38</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.qtquick3d.android_armv7</Name>
+  <DisplayName>Qt Quick 3D for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.qtquick3d, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtquick3d-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="1100385" OS="Any" UncompressedSize="5407601"/>
+  <SHA1>0fb0448629e34445d1315d56a156715048df83b6</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.qtquicktimeline</Name>
+  <DisplayName>Qt Quick Timeline</DisplayName>
+  <Description>The Qt Quick Timeline module enables keyframe-based animations and parameterization. It takes a tooling-friendly approach, and is therefore directly supported by Qt Design Studio and Qt Quick Designer that contain a timeline editor for creating keyframe based animations.&lt;br>&lt;br>This component is available under commercial licenses from The Qt Company, or under GPL v3. For open source use, please note the additional requirements compared to LGPL v3.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>0</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtquicktimeline, qt.qt6.620.examples.qtquicktimeline</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>7e9cc3491d60249f414f90ec95a868f41200da26</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.qtquicktimeline.android_armv7</Name>
+  <DisplayName>Qt Quick Timeline for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.qtquicktimeline, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtquicktimeline-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="34013" OS="Any" UncompressedSize="158729"/>
+  <SHA1>a4e14084809defc2277928989c378e9fdd508468</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.qtshadertools</Name>
+  <DisplayName>Qt Shader Tools</DisplayName>
+  <Description>Qt Shader conditioning tool Prebuilt Components for Qt 6.2.0.&lt;br>&lt;br>This component is available under commercial licenses from The Qt Company, or under GPL v3. For open source use, please note the additional requirements compared to LGPL v3.</Description>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <Default>false</Default>
+  <SortingPriority>9</SortingPriority>
+  <Dependencies>qt.qt6.620.doc.qtshadertools, qt.qt6.620.examples.qtshadertools</Dependencies>
+  <AutoDependOn/>
+  <Script>installscript.qs</Script>
+  <DownloadableArchives/>
+  <UpdateFile CompressedSize="0" OS="Any" UncompressedSize="0"/>
+  <SHA1>0199297b4ebfd40e83a66773d58e64a8b169c7f4</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.qt6.620.qtshadertools.android_armv7</Name>
+  <DisplayName>Qt Shader Tools for Android ARMv7</DisplayName>
+  <Description/>
+  <Version>6.2.0-0-202109261630</Version>
+  <ReleaseDate>2021-09-26</ReleaseDate>
+  <AutoDependOn>qt.qt6.620.qtshadertools, qt.qt6.620.android_armv7</AutoDependOn>
+  <Dependencies>qt.qt6.620.android_armv7</Dependencies>
+  <Virtual>true</Virtual>
+  <Script>installscript.qs</Script>
+  <SortingPriority/>
+  <DownloadableArchives>qtshadertools-Windows-Windows_10-Clang-Android-Android_ANY-ARMv7.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="756822" OS="Any" UncompressedSize="2391868"/>
+  <SHA1>31d87b11ccc81aeeff68292dd09f942e296a3bb7</SHA1>
+ </PackageUpdate>
+ <SHA1>0e91c773aa4056097d68662866e237e14260ddd3</SHA1>
+ <MetadataName>2021-09-26-1631_meta.7z</MetadataName>
+</Updates>
diff --git a/tests/data/windows-desktop-tools-mingw-updates.xml b/tests/data/windows-desktop-tools-mingw-updates.xml
new file mode 100644
index 0000000..56463eb
--- /dev/null
+++ b/tests/data/windows-desktop-tools-mingw-updates.xml
@@ -0,0 +1,145 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+  <Name>qt.tools.mingw47</Name>
+  <DisplayName>MinGW 4.7 32-bit</DisplayName>
+  <Description>MinGW-builds 4.7.2 32-bit toolchain.</Description>
+  <Version>4.7.2-1-1</Version>
+  <ReleaseDate>2013-07-01</ReleaseDate>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>472</SortingPriority>
+  <DownloadableArchives>x32-4.7.2-release-posix-sjlj-rev8.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="46087680" OS="Any" UncompressedSize="375492053"/>
+  <SHA1>35551be9daa226d6e440bb3404d8a7b84dab9447</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.win32_mingw48</Name>
+  <DisplayName>MinGW 4.8 32-bit</DisplayName>
+  <Description>MinGW-builds 4.8.0 32-bit toolchain.</Description>
+  <Version>4.8.0-1-1</Version>
+  <ReleaseDate>2013-07-01</ReleaseDate>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>480</SortingPriority>
+  <DownloadableArchives>x32-4.8.0-release-posix-dwarf-rev2.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="40118669" OS="Any" UncompressedSize="277848804"/>
+  <SHA1>6e51046425e89ee00d18ed6fc9bfcb429f3c9806</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.win32_mingw482</Name>
+  <DisplayName>MinGW 4.8.2 32-bit</DisplayName>
+  <Description>MinGW-builds 4.8.2 rev3 32-bit toolchain.</Description>
+  <Version>4.8.2</Version>
+  <ReleaseDate>2014-05-08</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator</Dependencies>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>482</SortingPriority>
+  <DownloadableArchives>i686-4.8.2-release-posix-dwarf-rt_v3-rev3.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="59488669" OS="Any" UncompressedSize="434107538"/>
+  <SHA1>1bed2c8bfce60958f30c8a16407d585bd8ea9ce1</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.win32_mingw491</Name>
+  <DisplayName>MinGW 4.9.1 32-bit</DisplayName>
+  <Description>MinGW-builds 4.9.1 32-bit toolchain.</Description>
+  <Version>4.9.1-3</Version>
+  <ReleaseDate>2016-05-31</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator</Dependencies>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>491</SortingPriority>
+  <DownloadableArchives>i686-4.9.1-release-posix-dwarf-rt_v3-rev2.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="71162187" OS="Any" UncompressedSize="467998718"/>
+  <SHA1>f74b6c79360f33d1d6eea4098117da3d4565fd38</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.win32_mingw492</Name>
+  <DisplayName>MinGW 4.9.2 32-bit</DisplayName>
+  <Description>MinGW-builds 4.9.2 32-bit toolchain.</Description>
+  <Version>4.9.2-1</Version>
+  <ReleaseDate>2016-05-31</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator</Dependencies>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>492</SortingPriority>
+  <DownloadableArchives>i686-4.9.2-release-posix-dwarf-rt_v3-rev1.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="71397942" OS="Any" UncompressedSize="468388919"/>
+  <SHA1>93e0b609e760ba3d01ba227d264e59fe3db5fdc2</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.win32_mingw530</Name>
+  <DisplayName>MinGW 5.3.0 32-bit</DisplayName>
+  <Description>MinGW-builds 5.3.0 32-bit toolchain.</Description>
+  <Version>5.3.0-2</Version>
+  <ReleaseDate>2017-04-27</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator</Dependencies>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>530</SortingPriority>
+  <DownloadableArchives>i686-5.3.0-release-posix-dwarf-rt_v4-rev0.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="59516049" OS="Any" UncompressedSize="400664148"/>
+  <SHA1>4d77bf0da2051b2e69cbcf5763dec99518743469</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.win32_mingw730</Name>
+  <DisplayName>MinGW 7.3.0 32-bit</DisplayName>
+  <Description>MinGW-builds 7.3.0 32-bit toolchain.</Description>
+  <Version>7.3.0-1-202004170606</Version>
+  <ReleaseDate>2020-04-17</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator</Dependencies>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>730</SortingPriority>
+  <DownloadableArchives>i686-7.3.0-release-posix-dwarf-rt_v5-rev0.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="66719936" OS="Any" UncompressedSize="443373513"/>
+  <SHA1>11f21cf2086decebf4ce53aa585d101234a5a941</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.win32_mingw810</Name>
+  <DisplayName>MinGW 8.1.0 32-bit</DisplayName>
+  <Description>MinGW-builds 8.1.0 32-bit toolchain.</Description>
+  <Version>8.1.0-1-202004170606</Version>
+  <ReleaseDate>2020-04-17</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator</Dependencies>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>810</SortingPriority>
+  <DownloadableArchives>i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="69090583" OS="Any" UncompressedSize="429560326"/>
+  <SHA1>7a9a48058b5ee71fde511638327f74caa0b90aec</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.win64_mingw730</Name>
+  <DisplayName>MinGW 7.3.0 64-bit</DisplayName>
+  <Description>MinGW-builds 7.3.0 64-bit toolchain.</Description>
+  <Version>7.3.0-1-202004170606</Version>
+  <ReleaseDate>2020-04-17</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator</Dependencies>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>730</SortingPriority>
+  <DownloadableArchives>x86_64-7.3.0-release-posix-seh-rt_v5-rev0.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="70370688" OS="Any" UncompressedSize="472170606"/>
+  <SHA1>50b1ced1e1f86d8470b178672da0973dc9b0a2d8</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.win64_mingw810</Name>
+  <DisplayName>MinGW 8.1.0 64-bit</DisplayName>
+  <Description>MinGW-builds 8.1.0 64-bit toolchain.</Description>
+  <Version>8.1.0-1-202004170606</Version>
+  <ReleaseDate>2020-04-17</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator</Dependencies>
+  <Default>false</Default>
+  <Script>installscript.qs</Script>
+  <SortingPriority>810</SortingPriority>
+  <DownloadableArchives>x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z</DownloadableArchives>
+  <UpdateFile CompressedSize="71560572" OS="Any" UncompressedSize="457580500"/>
+  <SHA1>54ada35db54725586bc33cab5f04577a37a90077</SHA1>
+ </PackageUpdate>
+ <MetadataName>2020-08-21-1951_meta.7z</MetadataName>
+ <SHA1>ca18024129a66d26be2359ef598a11476c6f1075</SHA1>
+</Updates>
diff --git a/tests/data/windows-desktop-tools-qtcreator-updates.xml b/tests/data/windows-desktop-tools-qtcreator-updates.xml
new file mode 100644
index 0000000..c226f71
--- /dev/null
+++ b/tests/data/windows-desktop-tools-qtcreator-updates.xml
@@ -0,0 +1,58 @@
+<Updates>
+ <ApplicationName>{AnyApplication}</ApplicationName>
+ <ApplicationVersion>1.0.0</ApplicationVersion>
+ <Checksum>true</Checksum>
+ <PackageUpdate>
+  <Name>qt.tools.qtcreator</Name>
+  <DisplayName>Qt Creator 7.0.2</DisplayName>
+  <Description>IDE for Qt application development</Description>
+  <Version>7.0.2-0-202205230351</Version>
+  <ReleaseDate>2022-05-23</ReleaseDate>
+  <Script>installscript.qs</Script>
+  <Dependencies/>
+  <SortingPriority>1000</SortingPriority>
+  <ForcedInstallation>true</ForcedInstallation>
+  <DownloadableArchives>qtcreator.7z, wininterrupt32.7z, wininterrupt64.7z, qtcreator_sdktool.7z, jom.7z</DownloadableArchives>
+  <UpdateFile UncompressedSize="715894544" CompressedSize="175213170" OS="Any"/>
+  <UserInterfaces>associatecommonfiletypesform.ui,launchqtcreatorcheckboxform.ui</UserInterfaces>
+  <Translations>fr.qm,es.qm,ja.qm,pt.qm,ru.qm,ar.qm,de.qm</Translations>
+  <SHA1>a3fc075e1c5f1839db14acd6bdbcec25cc9f05d3</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.qtcreatorcdbext</Name>
+  <DisplayName>Qt Creator 7.0.2 CDB Debugger Support</DisplayName>
+  <Description>CDB Debugger support for Qt Creator</Description>
+  <Version>7.0.2-0-202205230351</Version>
+  <ReleaseDate>2022-05-23</ReleaseDate>
+  <Dependencies>qt.tools.qtcreator,qt.license.python</Dependencies>
+  <SortingPriority>999</SortingPriority>
+  <Default>true</Default>
+  <DownloadableArchives>qtcreatorcdbext32.7z, qtcreatorcdbext64.7z</DownloadableArchives>
+  <UpdateFile UncompressedSize="13148876" CompressedSize="4886053" OS="Any"/>
+  <SHA1>c6fd6fba900923a806f6a9cbadaccf4f0d16f555</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.qtcreatordbg</Name>
+  <DisplayName>Qt Creator 7.0.2 Debug Symbols</DisplayName>
+  <Description>Additional symbol files required to debug Qt Creator</Description>
+  <Version>7.0.2-0-202205230351</Version>
+  <ReleaseDate>2022-05-23</ReleaseDate>
+  <SortingPriority>994</SortingPriority>
+  <DownloadableArchives>qtcreator-debug.7z</DownloadableArchives>
+  <UpdateFile UncompressedSize="1682272296" CompressedSize="246461731" OS="Any"/>
+  <SHA1>44cd4751fc9ea64a44547bfa1e0bf7da33ecdabd</SHA1>
+ </PackageUpdate>
+ <PackageUpdate>
+  <Name>qt.tools.qtcreatordev</Name>
+  <DisplayName>Qt Creator 7.0.2 Plugin Development</DisplayName>
+  <Description>Headers and libs required to develop additional plugins</Description>
+  <Version>7.0.2-0-202205230351</Version>
+  <ReleaseDate>2022-05-23</ReleaseDate>
+  <SortingPriority>990</SortingPriority>
+  <DownloadableArchives>qtcreator_dev.7z</DownloadableArchives>
+  <UpdateFile UncompressedSize="122459312" CompressedSize="10277961" OS="Any"/>
+  <SHA1>8bc060e6b0e925901eccb62e354c1e38952892df</SHA1>
+ </PackageUpdate>
+ <SHA1>6a135848ba16020da7f6b05aa3946b611212e03c</SHA1>
+ <MetadataName>2022-05-23-0407_meta.7z</MetadataName>
+</Updates>
diff --git a/tests/test_archives.py b/tests/test_archives.py
index 2a42a6c..4e22eb2 100644
--- a/tests/test_archives.py
+++ b/tests/test_archives.py
@@ -8,7 +8,7 @@ from typing import Dict, Iterable, List, Set
 
 import pytest
 
-from aqt.archives import ModuleToPackage, QtArchives, QtPackage, SrcDocExamplesArchives, ToolArchives
+from aqt.archives import ModuleToPackage, QtArchives, QtPackage, SrcDocExamplesArchives, ToolArchives, Updates
 from aqt.exceptions import ArchiveListError, NoPackageFound
 from aqt.helper import Settings
 from aqt.metadata import Version
@@ -346,6 +346,35 @@ qt_doc_5152_xml_weird_module = """
  </PackageUpdate>
 </Updates>
 """
+qt_example_5152_xml_module = """
+<Updates>
+<PackageUpdate>
+<Name>qt.qt5.5152.examples</Name>
+<DisplayName>Qt 5.15.2 Examples</DisplayName>
+<Description>Qt 5.15.2 Examples</Description>
+<Version>5.15.2-0-202011130614</Version>
+<ReleaseDate>2020-11-13</ReleaseDate>
+<Dependencies>qt.tools</Dependencies>
+<Virtual>true</Virtual>
+<SortingPriority>1</SortingPriority>
+<DownloadableArchives>tqtc-qt5-examples.7z, qtbase-examples.7z, qtdoc-examples.7z</DownloadableArchives>
+<UpdateFile OS="Any" UncompressedSize="150199927" CompressedSize="112808235"/>
+<SHA1>8bb69229612cc0ff129e854a9fa9834731fd584d</SHA1>
+</PackageUpdate>
+<PackageUpdate>
+<Name>qt.qt5.5152.examples.qtcharts</Name>
+<DisplayName>Examples for Qt 5.15.2 GPLv3 components (QtCharts)</DisplayName>
+<Description>Examples for Qt 5.15.2 GPLv3 components (QtCharts)</Description>
+<Version>5.15.2-0-202011130614</Version>
+<ReleaseDate>2020-11-13</ReleaseDate>
+<Virtual>true</Virtual>
+<SortingPriority>1</SortingPriority>
+<DownloadableArchives>qtcharts-examples.7z</DownloadableArchives>
+<UpdateFile OS="Any" UncompressedSize="529204" CompressedSize="52228"/>
+<SHA1>b40e53660ad4762c4867a4ebf9945029e988c01b</SHA1>
+</PackageUpdate>
+</Updates>
+"""
 
 
 def make_qt_archives(subarchives, modules, is_include_base) -> QtArchives:
@@ -376,6 +405,20 @@ def make_doc_archives(subarchives, modules, is_include_base) -> SrcDocExamplesAr
     )
 
 
+def make_example_archives(subarchives, modules, is_include_base) -> SrcDocExamplesArchives:
+    return SrcDocExamplesArchives(
+        flavor="examples",
+        os_name="linux",
+        target="desktop",
+        version="5.15.2",
+        base="www.example.com",
+        subarchives=subarchives,
+        modules=modules,
+        all_extra="all" in modules,
+        is_include_base_package=is_include_base,
+    )
+
+
 @pytest.mark.parametrize(
     "subarchives, modules, is_include_base, xml, make_archives_fn, expect_archives",
     (
@@ -431,6 +474,7 @@ def make_doc_archives(subarchives, modules, is_include_base) -> SrcDocExamplesAr
         (["tqtc"], [], False, qt_doc_5152_xml_weird_module, make_doc_archives, set()),
         (["tqtc"], ["all"], False, qt_doc_5152_xml_weird_module, make_doc_archives, {"weird-qtcharts-docs.7z"}),
         (["tqtc"], ["qtcharts"], False, qt_doc_5152_xml_weird_module, make_doc_archives, {"weird-qtcharts-docs.7z"}),
+        (["qtdoc"], ["qtcharts"], False, qt_example_5152_xml_module, make_example_archives, {"qtcharts-examples.7z"}),
     ),
 )
 def test_archives_weird_module_7z_name(
@@ -448,3 +492,80 @@ def test_archives_weird_module_7z_name(
     qt_archives = make_archives_fn(subarchives, modules, is_include_base)
     archives = {pkg.archive for pkg in qt_archives.archives}
     assert archives == expect_archives
+
+
+@pytest.mark.parametrize(
+    "in_file,expect_out_file",
+    [
+        ("windows-5140-update.xml", "windows-5140-expect.json"),
+    ],
+)
+def test_parse_updates(in_file: str, expect_out_file: str):
+    xml = (Path(__file__).parent / "data" / in_file).read_text("utf-8")
+    expect_all = json.loads((Path(__file__).parent / "data" / expect_out_file).read_text("utf-8"))
+    base = ""
+    architectures = expect_all["architectures"]
+    update_xml = Updates.fromstring(base, xml)
+    expect_metadata = expect_all["modules_metadata_by_arch"]
+    for arch in architectures:
+        expect_update = expect_metadata[arch]
+        updates = update_xml.get_from(arch, True)
+        for entry in updates:
+            for expect in expect_update:
+                if expect["Name"] == entry.name:
+                    assert entry.full_version == expect["Version"]
+                    assert entry.release_date == expect["ReleaseDate"]
+                    assert entry.description == expect["Description"]
+                    count = 0
+                    for item in entry.downloadable_archives:
+                        count += 1
+                        assert item in expect["DownloadableArchives"]
+                    assert count == len(expect["DownloadableArchives"])
+                    count = 0
+                    for item in entry.auto_dependon:
+                        count += 1
+                        assert item in expect["AutoDependOn"]
+                    assert count == len(expect["AutoDependOn"])
+                    for item in entry.dependencies:
+                        assert item in [expect["Dependencies"]]
+
+
+@pytest.mark.parametrize(
+    "target,base,in_file,tool_file,expect",
+    [
+        (
+            "qt.qt6.620.qt5compat.android_armv7",
+            "https://download.qt.io/online/qtsdkrepository/windows_x86/android/",
+            "windows-620-android-armv7-update.xml",
+            "windows-desktop-tools-qtcreator-updates.xml",
+            "qt.tools.qtcreator",
+        ),
+    ],
+)
+def test_parse_and_get_packages(target: str, base, in_file: str, tool_file: str, expect: str):
+    xml = (Path(__file__).parent / "data" / in_file).read_text("utf-8")
+    tool = (Path(__file__).parent / "data" / tool_file).read_text("utf-8")
+    update_xml = Updates.fromstring(base, xml)
+    tool_xml = Updates.fromstring(base, tool)
+    update_xml.merge(tool_xml)
+    packages = update_xml.get_depends(target)
+    assert expect in packages
+    assert len(packages) == 5
+
+
+@pytest.mark.parametrize(
+    "target,in_file,expect_depend",
+    [
+        ("qt.qt5.5140.qtcharts.win32_mingw73", "windows-5140-update.xml", "qt.tools.win32_mingw730"),
+    ],
+)
+def test_get_module_to_package(target: str, in_file: str, expect_depend: str):
+    xml = (Path(__file__).parent / "data" / in_file).read_text("utf-8")
+    base = ""
+    update_xml = Updates.fromstring(base, xml)
+    module = target.split(".")[-2]
+    #
+    packages = update_xml.get_depends(target)
+    module_to_package = ModuleToPackage({module: packages})
+    assert module_to_package.has_package(target)
+    assert module_to_package.has_package(expect_depend)