Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
unicado.gitlab.io
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
UNICADO
unicado.gitlab.io
Commits
69c7d261
Commit
69c7d261
authored
4 months ago
by
Kristina Mazur
Browse files
Options
Downloads
Patches
Plain Diff
Enhance it
parent
762694f6
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
scripts/document_aircraft_xml.py
+36
-121
36 additions, 121 deletions
scripts/document_aircraft_xml.py
with
36 additions
and
121 deletions
scripts/document_aircraft_xml.py
+
36
−
121
View file @
69c7d261
#!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
()
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment