From 69c7d261c9b9376f653774e440c4aea20ac67161 Mon Sep 17 00:00:00 2001
From: Kristina Mazur <kristina.mazur@tum.de>
Date: Tue, 3 Dec 2024 14:54:58 +0100
Subject: [PATCH] Enhance it

---
 scripts/document_aircraft_xml.py | 157 +++++++------------------------
 1 file changed, 36 insertions(+), 121 deletions(-)

diff --git a/scripts/document_aircraft_xml.py b/scripts/document_aircraft_xml.py
index 453ee3c..06c53f9 100644
--- a/scripts/document_aircraft_xml.py
+++ b/scripts/document_aircraft_xml.py
@@ -1,104 +1,49 @@
-#!python
-# Copyright (c) 2023 S. Oberschwendtner.
-#
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-"""! @brief Script for converting an aircraft XML file to a content page."""
-##
-# @file document_aircraft_xml.py
-#
-# @brief Script for converting an aircraft XML file to a content page for the UNICADO homepage.
-#
-# @section description_document_aircraft_xml Description
-# This script parse the entries of an aircraft XML file and extracts
-# the entries and documents them using their description tags.
-# The output is a markdown file which can be used for the documentation.
-#
-# @section libraries_document_aircraft_xml Libraries/Modules
-# - argparse standard library (https://docs.python.org/3/library/argparse.html)
-#   - Parser for command-line options, arguments and sub-commands.
-# - xml standard library (https://docs.python.org/3/library/xml.html)
-#   - XML Processing Modules.
-# - pathlib standard library (https://docs.python.org/3/library/pathlib.html)
-#   - Object-oriented filesystem paths.
-#
-# @section notes_document_aircraft_xml Notes
-# - None.
-#
-# @section todo_document_aircraft_xml TODO
-# - None.
-#
-# @section authors_document_aircraft_xml Author(s)
-# - Created by S. Oberschwendtner on 19/09/2023.
-
-# === Imports ===
 import argparse
 import xml.etree.ElementTree as ET
 from pathlib import Path
 
 # === Configuration ===
-# Define the format of the output
 FORMAT = {
-    "Header": "\n## {:s}\n> **Description**: {:s}\n",
+    "Header": "\n{}## {:s}\n> **Description**: {:s}\n",
     "Unit": "> **Unit**: {:s}\n",
     "TableHeader": "| Relative XML Path | Unit | Description |\n|:---|:---:|:---|",
     "Table": "| <nobr>`{:s}` | *{:s}* | {:s} |",
 }
 
-# Which keys are used in the XML attributes for which information
 KEYS = {
-    "Description": "description",  # Match the 'description' key from XML
-    "Unit": "unit",                # Match the 'unit' key from XML
+    "Description": "description",
+    "Unit": "unit",
 }
 
+# Define specific levels for each child node of "requirements_and_specifications"
+CUSTOM_LEVELS = {
+    "general": 2,
+    "mission_files": 2,
+    "design_specification": 4,
+    "requirements": 3,
+}
 
-
-# === Classes ===
 class Page:
-    """Class for a page.
-
-    A page is one top section of the aircraft XML file.
-    """
-
-    @property
-    def max_level_reached(self) -> bool:
-        """Returns whether the maximum level has been reached."""
-        return self.current_level >= self.max_header_level
-
-    def __init__(self, title, max_level):
-        """Constructor of the class.
-
-        Args:
-            title (str): Title of the page.
-            max_level (int): Maximum level of the headers.
-        """
+    def __init__(self, title):
         self.title = title
-        self.max_header_level = max_level
         self.current_level = 0
         self.table_started = False
         self.current_path = Path(".")
         self.sections = [[]]
 
-    def create(self, node: ET.Element):
-        """Creates the page from the given node, summarizing nested elements properly.
-
-        Args:
-            node (ET.Element): Node to start from.
-        """
-        # Add header if appropriate
-        if not self.max_level_reached:
+    def create(self, node: ET.Element, level=None):
+        # Set the level based on custom levels if provided
+        if node.tag in CUSTOM_LEVELS:
+            level = CUSTOM_LEVELS[node.tag]
+        elif level is None:
+            level = self.current_level + 1
+        
+        # Update current level and path
+        if level <= 4:
+            self.current_level = level
+            self.current_path /= node.tag
+
+            # Add header if appropriate
             self.make_header_entry(node)
 
         # Treat node attributes and values as part of the parent row
@@ -110,28 +55,25 @@ class Page:
 
             # Process child elements recursively, skipping common attributes like 'value', 'unit', etc.
             for child in node:
-                if child.tag in ["value", "unit", "lower_boundary", "upper_boundary"]:
-                    continue
-                self.create(child)
+                if child.tag not in ["value", "unit", "lower_boundary", "upper_boundary"]:
+                    self.create(child, level + 1)
 
+        # Restore previous path after processing
+        self.current_path = self.current_path.parent
 
     def make_header_entry(self, node: ET.Element):
-        """Creates a header entry.
-
-        Args:
-            node (ET.Element): The current node element.
-        """
         # Reset the table when creating a new header
         self.table_started = False
 
-        # Fetch description
+        # Fetch description and adjust header level format
         description = node.attrib.get(KEYS["Description"], "None")
+        header_level_prefix = "#" * min(self.current_level, 4)
 
         # Create the header with description
         print(
             "\n"
-            + self.current_level * "#"
-            + FORMAT["Header"].format(node.tag, description)
+            + header_level_prefix
+            + FORMAT["Header"].format(self.current_level, node.tag, description)
         )
 
         # Try to add a unit description
@@ -140,11 +82,6 @@ class Page:
             print(FORMAT["Unit"].format(unit))
 
     def make_table_entry(self, node: ET.Element):
-        """Creates a table entry for the current node, embedding child attributes into the parent node's row.
-
-        Args:
-            node (ET.Element): The current node element.
-        """
         # Check if the table has already been started
         if not self.table_started:
             self.table_started = True
@@ -153,29 +90,14 @@ class Page:
         # Generate a relative XML path for the current node
         path_name = str(self.current_path / node.tag).replace("\\", "/")
 
-        # Fetch parent description and unit
+        # Fetch the description and unit
         description = node.attrib.get(KEYS["Description"], f"No description for {node.tag}")
         unit = node.attrib.get(KEYS["Unit"], "No unit specified")
 
-        # Collect all child attributes
-        child_details = []
-        for child in node:
-            child_desc = child.attrib.get(KEYS["Description"], f"No description for {child.tag}")
-            child_unit = child.attrib.get(KEYS["Unit"], "No unit specified")
-            child_details.append(f"{child.tag}: {child_desc} (unit: {child_unit})")
-
-        # Combine parent description with child attributes
-        combined_description = description + " | " + " | ".join(child_details)
-
-        # Print the table row for the parent node
-        print(FORMAT["Table"].format(path_name, unit, combined_description))
+        # Print the table row for the current node
+        print(FORMAT["Table"].format(path_name, unit, description))
 
-# === Main ===
 def main():
-    """
-    Main function of the script.
-    """
-    # Create argument parser
     parser = argparse.ArgumentParser(
         description="Converts an aircraft XML file to a markdown file. The output is streamed to stdout and can be piped to a file."
     )
@@ -192,12 +114,6 @@ def main():
         type=str,
         help="The title of the output page. This also sets the root node which is used to create the document.",
     )
-    parser.add_argument(
-        "--level",
-        metavar="level",
-        type=int,
-        help="The maximum level nodes to be used as headers.",
-    )
 
     # Parse the arguments
     args = parser.parse_args()
@@ -207,7 +123,7 @@ def main():
     root = tree.getroot()
 
     # Get the configuration parameters
-    page = Page(args.title, args.level)
+    page = Page(args.title)
     node = root.find(page.title)
 
     # Check whether the node exists
@@ -217,6 +133,5 @@ def main():
     # Start creating the page
     page.create(node)
 
-
 if __name__ == "__main__":
     main()
-- 
GitLab