Refactored XML export code between management command and view
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 56s
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 56s
This commit is contained in:
@@ -1,40 +1,7 @@
|
|||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from datetime import datetime
|
from dokumente.models import Dokument
|
||||||
from dokumente.models import Dokument, Vorgabe, VorgabeKurztext, VorgabeLangtext, Checklistenfrage
|
from dokumente.utils import build_dokument_xml_element, prettify_xml
|
||||||
|
|
||||||
|
|
||||||
def _parse_markdown_table(markdown_content):
|
|
||||||
"""
|
|
||||||
Parse markdown table content and return XML element with <table><header><row><column> structure
|
|
||||||
"""
|
|
||||||
lines = [line.strip() for line in markdown_content.strip().split('\n') if line.strip()]
|
|
||||||
if not lines:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Create table element
|
|
||||||
table = ET.Element('table')
|
|
||||||
|
|
||||||
# Parse first row as header
|
|
||||||
header_row = [cell.strip() for cell in lines[0].split('|') if cell.strip()]
|
|
||||||
header = ET.SubElement(table, 'header')
|
|
||||||
for cell in header_row:
|
|
||||||
column = ET.SubElement(header, 'column')
|
|
||||||
column.text = cell
|
|
||||||
|
|
||||||
# Parse remaining rows (skip separator row if it exists)
|
|
||||||
for line in lines[2:] if len(lines) > 1 and all(c in '-| ' for c in lines[1]) else lines[1:]:
|
|
||||||
# Check if this is a separator row
|
|
||||||
if all(c in '-| ' for c in line):
|
|
||||||
continue
|
|
||||||
|
|
||||||
row = ET.SubElement(table, 'row')
|
|
||||||
row_cells = [cell.strip() for cell in line.split('|') if cell.strip()]
|
|
||||||
for cell in row_cells:
|
|
||||||
column = ET.SubElement(row, 'column')
|
|
||||||
column.text = cell
|
|
||||||
|
|
||||||
return table
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
@@ -49,7 +16,7 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
dokumente = Dokument.objects.filter(aktiv=True).prefetch_related(
|
dokumente = Dokument.objects.filter(aktiv=True).prefetch_related(
|
||||||
'autoren', 'pruefende', 'vorgaben__thema',
|
'autoren', 'pruefende', 'vorgaben__thema',
|
||||||
'vorgaben__referenzen', 'vorgaben__stichworte',
|
'vorgaben__referenzen', 'vorgaben__stichworte',
|
||||||
'vorgaben__checklistenfragen', 'vorgaben__vorgabekurztext_set',
|
'vorgaben__checklistenfragen', 'vorgaben__vorgabekurztext_set',
|
||||||
'vorgaben__vorgabelangtext_set', 'geltungsbereich_set',
|
'vorgaben__vorgabelangtext_set', 'geltungsbereich_set',
|
||||||
@@ -59,147 +26,14 @@ class Command(BaseCommand):
|
|||||||
root = ET.Element('Vorgabendokumente')
|
root = ET.Element('Vorgabendokumente')
|
||||||
|
|
||||||
for dokument in dokumente:
|
for dokument in dokumente:
|
||||||
doc_element = ET.SubElement(root, 'Vorgabendokument')
|
build_dokument_xml_element(dokument, root)
|
||||||
|
|
||||||
ET.SubElement(doc_element, 'Typ').text = dokument.dokumententyp.name if dokument.dokumententyp else ""
|
|
||||||
ET.SubElement(doc_element, 'Nummer').text = dokument.nummer
|
|
||||||
ET.SubElement(doc_element, 'Name').text = dokument.name
|
|
||||||
|
|
||||||
autoren_element = ET.SubElement(doc_element, 'Autoren')
|
|
||||||
for autor in dokument.autoren.all():
|
|
||||||
ET.SubElement(autoren_element, 'Autor').text = autor.name
|
|
||||||
|
|
||||||
pruefende_element = ET.SubElement(doc_element, 'Pruefende')
|
|
||||||
for pruefender in dokument.pruefende.all():
|
|
||||||
ET.SubElement(pruefende_element, 'Pruefender').text = pruefender.name
|
|
||||||
|
|
||||||
gueltigkeit_element = ET.SubElement(doc_element, 'Gueltigkeit')
|
|
||||||
ET.SubElement(gueltigkeit_element, 'Von').text = dokument.gueltigkeit_von.strftime("%Y-%m-%d") if dokument.gueltigkeit_von else ""
|
|
||||||
ET.SubElement(gueltigkeit_element, 'Bis').text = dokument.gueltigkeit_bis.strftime("%Y-%m-%d") if dokument.gueltigkeit_bis else None
|
|
||||||
|
|
||||||
ET.SubElement(doc_element, 'SignaturCSO').text = dokument.signatur_cso
|
|
||||||
|
|
||||||
geltungsbereich_sections = dokument.geltungsbereich_set.all().order_by('order')
|
|
||||||
if geltungsbereich_sections:
|
|
||||||
geltungsbereich_element = ET.SubElement(doc_element, 'Geltungsbereich')
|
|
||||||
for gb in geltungsbereich_sections:
|
|
||||||
section_type = gb.abschnitttyp.abschnitttyp if gb.abschnitttyp else "text"
|
|
||||||
if section_type in ('tabelle', 'table'):
|
|
||||||
table = _parse_markdown_table(gb.inhalt)
|
|
||||||
if table is not None:
|
|
||||||
abschnitt_element = ET.SubElement(geltungsbereich_element, 'Abschnitt')
|
|
||||||
abschnitt_element.set('typ', section_type)
|
|
||||||
abschnitt_element.append(table)
|
|
||||||
else:
|
|
||||||
abschnitt_element = ET.SubElement(geltungsbereich_element, 'Abschnitt')
|
|
||||||
abschnitt_element.set('typ', section_type)
|
|
||||||
abschnitt_element.text = gb.inhalt
|
|
||||||
|
|
||||||
einleitung_sections = dokument.einleitung_set.all().order_by('order')
|
|
||||||
if einleitung_sections:
|
|
||||||
einleitung_element = ET.SubElement(doc_element, 'Einleitung')
|
|
||||||
for ei in einleitung_sections:
|
|
||||||
section_type = ei.abschnitttyp.abschnitttyp if ei.abschnitttyp else "text"
|
|
||||||
if section_type in ('tabelle', 'table'):
|
|
||||||
table = _parse_markdown_table(ei.inhalt)
|
|
||||||
if table is not None:
|
|
||||||
abschnitt_element = ET.SubElement(einleitung_element, 'Abschnitt')
|
|
||||||
abschnitt_element.set('typ', section_type)
|
|
||||||
abschnitt_element.append(table)
|
|
||||||
else:
|
|
||||||
abschnitt_element = ET.SubElement(einleitung_element, 'Abschnitt')
|
|
||||||
abschnitt_element.set('typ', section_type)
|
|
||||||
abschnitt_element.text = ei.inhalt
|
|
||||||
|
|
||||||
ET.SubElement(doc_element, 'Ziel').text = ""
|
|
||||||
ET.SubElement(doc_element, 'Grundlagen').text = ""
|
|
||||||
|
|
||||||
changelog_element = ET.SubElement(doc_element, 'Changelog')
|
|
||||||
for cl in dokument.changelog.all().order_by('-datum'):
|
|
||||||
entry = ET.SubElement(changelog_element, 'Eintrag')
|
|
||||||
ET.SubElement(entry, 'Datum').text = cl.datum.strftime("%Y-%m-%d")
|
|
||||||
autoren = ET.SubElement(entry, 'Autoren')
|
|
||||||
for autor in cl.autoren.all():
|
|
||||||
ET.SubElement(autoren, 'Autor').text = autor.name
|
|
||||||
ET.SubElement(entry, 'Aenderung').text = cl.aenderung
|
|
||||||
|
|
||||||
anhaenge_element = ET.SubElement(doc_element, 'Anhaenge')
|
|
||||||
ET.SubElement(anhaenge_element, 'Anhang').text = dokument.anhaenge
|
|
||||||
|
|
||||||
ET.SubElement(doc_element, 'Verantwortlich').text = "Information Security Management BIT"
|
|
||||||
ET.SubElement(doc_element, 'Klassifizierung').text = ""
|
|
||||||
|
|
||||||
glossar_element = ET.SubElement(doc_element, 'Glossar')
|
|
||||||
|
|
||||||
vorgaben_element = ET.SubElement(doc_element, 'Vorgaben')
|
|
||||||
|
|
||||||
for vorgabe in dokument.vorgaben.all().order_by('order'):
|
|
||||||
vorgabe_el = ET.SubElement(vorgaben_element, 'Vorgabe')
|
|
||||||
|
|
||||||
ET.SubElement(vorgabe_el, 'Nummer').text = str(vorgabe.nummer)
|
|
||||||
ET.SubElement(vorgabe_el, 'Titel').text = vorgabe.titel
|
|
||||||
ET.SubElement(vorgabe_el, 'Thema').text = vorgabe.thema.name if vorgabe.thema else ""
|
|
||||||
|
|
||||||
kurztext_sections = vorgabe.vorgabekurztext_set.all().order_by('order')
|
|
||||||
if kurztext_sections:
|
|
||||||
kurztext_element = ET.SubElement(vorgabe_el, 'Kurztext')
|
|
||||||
for kt in kurztext_sections:
|
|
||||||
section_type = kt.abschnitttyp.abschnitttyp if kt.abschnitttyp else "text"
|
|
||||||
if section_type in ('tabelle', 'table'):
|
|
||||||
table = _parse_markdown_table(kt.inhalt)
|
|
||||||
if table is not None:
|
|
||||||
abschnitt = ET.SubElement(kurztext_element, 'Abschnitt')
|
|
||||||
abschnitt.set('typ', section_type)
|
|
||||||
abschnitt.append(table)
|
|
||||||
else:
|
|
||||||
abschnitt = ET.SubElement(kurztext_element, 'Abschnitt')
|
|
||||||
abschnitt.set('typ', section_type)
|
|
||||||
abschnitt.text = kt.inhalt
|
|
||||||
|
|
||||||
langtext_sections = vorgabe.vorgabelangtext_set.all().order_by('order')
|
|
||||||
if langtext_sections:
|
|
||||||
langtext_element = ET.SubElement(vorgabe_el, 'Langtext')
|
|
||||||
for lt in langtext_sections:
|
|
||||||
section_type = lt.abschnitttyp.abschnitttyp if lt.abschnitttyp else "text"
|
|
||||||
if section_type in ('tabelle', 'table'):
|
|
||||||
table = _parse_markdown_table(lt.inhalt)
|
|
||||||
if table is not None:
|
|
||||||
abschnitt = ET.SubElement(langtext_element, 'Abschnitt')
|
|
||||||
abschnitt.set('typ', section_type)
|
|
||||||
abschnitt.append(table)
|
|
||||||
else:
|
|
||||||
abschnitt = ET.SubElement(langtext_element, 'Abschnitt')
|
|
||||||
abschnitt.set('typ', section_type)
|
|
||||||
abschnitt.text = lt.inhalt
|
|
||||||
|
|
||||||
referenz_element = ET.SubElement(vorgabe_el, 'Referenzen')
|
|
||||||
for ref in vorgabe.referenzen.all():
|
|
||||||
ref_text = f"{ref.name_nummer}: {ref.name_text}" if ref.name_text else ref.name_nummer
|
|
||||||
ET.SubElement(referenz_element, 'Referenz').text = ref_text
|
|
||||||
|
|
||||||
vorgabe_gueltigkeit = ET.SubElement(vorgabe_el, 'Gueltigkeit')
|
|
||||||
ET.SubElement(vorgabe_gueltigkeit, 'Von').text = vorgabe.gueltigkeit_von.strftime("%Y-%m-%d") if vorgabe.gueltigkeit_von else ""
|
|
||||||
ET.SubElement(vorgabe_gueltigkeit, 'Bis').text = vorgabe.gueltigkeit_bis.strftime("%Y-%m-%d") if vorgabe.gueltigkeit_bis else None
|
|
||||||
|
|
||||||
checklistenfragen_element = ET.SubElement(vorgabe_el, 'Checklistenfragen')
|
|
||||||
for cf in vorgabe.checklistenfragen.all():
|
|
||||||
ET.SubElement(checklistenfragen_element, 'Frage').text = cf.frage
|
|
||||||
|
|
||||||
stichworte_element = ET.SubElement(vorgabe_el, 'Stichworte')
|
|
||||||
for stw in vorgabe.stichworte.all():
|
|
||||||
ET.SubElement(stichworte_element, 'Stichwort').text = stw.stichwort
|
|
||||||
|
|
||||||
xml_str = ET.tostring(root, encoding='unicode', method='xml')
|
xml_str = ET.tostring(root, encoding='unicode', method='xml')
|
||||||
xml_output = self._prettify_xml(xml_str)
|
xml_output = prettify_xml(xml_str)
|
||||||
|
|
||||||
if options['output']:
|
if options['output']:
|
||||||
with open(options['output'], 'w', encoding='utf-8') as f:
|
with open(options['output'], 'w', encoding='utf-8') as f:
|
||||||
f.write(xml_output)
|
f.write(xml_output)
|
||||||
self.stdout.write(self.style.SUCCESS(f'XML exported to {options["output"]}'))
|
self.stdout.write(self.style.SUCCESS(f'XML exported to {options["output"]}'))
|
||||||
else:
|
else:
|
||||||
self.stdout.write(xml_output)
|
self.stdout.write(xml_output)
|
||||||
|
|
||||||
def _prettify_xml(self, xml_string):
|
|
||||||
import xml.dom.minidom
|
|
||||||
dom = xml.dom.minidom.parseString(xml_string)
|
|
||||||
return dom.toprettyxml(indent=" ", encoding="UTF-8").decode('utf-8')
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
"""
|
"""
|
||||||
Utility functions for Vorgaben sanity checking
|
Utility functions for Vorgaben sanity checking and XML export
|
||||||
"""
|
"""
|
||||||
import datetime
|
import datetime
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
import xml.dom.minidom
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from itertools import combinations
|
from itertools import combinations
|
||||||
from dokumente.models import Vorgabe
|
from dokumente.models import Vorgabe
|
||||||
@@ -119,5 +121,192 @@ def format_conflict_report(conflicts, verbose=False):
|
|||||||
lines.append(f" Overlap: {overlap_start} to {overlap_end}")
|
lines.append(f" Overlap: {overlap_start} to {overlap_end}")
|
||||||
else:
|
else:
|
||||||
lines.append(f" Overlap starts: {overlap_start} (no end)")
|
lines.append(f" Overlap starts: {overlap_start} (no end)")
|
||||||
|
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
# XML Export utilities
|
||||||
|
|
||||||
|
def parse_markdown_table(markdown_content):
|
||||||
|
"""
|
||||||
|
Parse markdown table content and return XML element with <table><header><row><column> structure
|
||||||
|
"""
|
||||||
|
lines = [line.strip() for line in markdown_content.strip().split('\n') if line.strip()]
|
||||||
|
if not lines:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Create table element
|
||||||
|
table = ET.Element('table')
|
||||||
|
|
||||||
|
# Parse first row as header
|
||||||
|
header_row = [cell.strip() for cell in lines[0].split('|') if cell.strip()]
|
||||||
|
header = ET.SubElement(table, 'header')
|
||||||
|
for cell in header_row:
|
||||||
|
column = ET.SubElement(header, 'column')
|
||||||
|
column.text = cell
|
||||||
|
|
||||||
|
# Parse remaining rows (skip separator row if it exists)
|
||||||
|
for line in lines[2:] if len(lines) > 1 and all(c in '-| ' for c in lines[1]) else lines[1:]:
|
||||||
|
# Check if this is a separator row
|
||||||
|
if all(c in '-| ' for c in line):
|
||||||
|
continue
|
||||||
|
|
||||||
|
row = ET.SubElement(table, 'row')
|
||||||
|
row_cells = [cell.strip() for cell in line.split('|') if cell.strip()]
|
||||||
|
for cell in row_cells:
|
||||||
|
column = ET.SubElement(row, 'column')
|
||||||
|
column.text = cell
|
||||||
|
|
||||||
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
def prettify_xml(xml_string):
|
||||||
|
"""
|
||||||
|
Prettify XML string with proper indentation
|
||||||
|
"""
|
||||||
|
dom = xml.dom.minidom.parseString(xml_string)
|
||||||
|
return dom.toprettyxml(indent=" ", encoding="UTF-8").decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def build_dokument_xml_element(dokument, parent_element):
|
||||||
|
"""
|
||||||
|
Build XML element for a single Dokument and append it to parent_element.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dokument: Dokument instance (should be prefetched with related data)
|
||||||
|
parent_element: Parent XML element to append to
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The created document element
|
||||||
|
"""
|
||||||
|
doc_element = ET.SubElement(parent_element, 'Vorgabendokument')
|
||||||
|
|
||||||
|
ET.SubElement(doc_element, 'Typ').text = dokument.dokumententyp.name if dokument.dokumententyp else ""
|
||||||
|
ET.SubElement(doc_element, 'Nummer').text = dokument.nummer
|
||||||
|
ET.SubElement(doc_element, 'Name').text = dokument.name
|
||||||
|
|
||||||
|
autoren_element = ET.SubElement(doc_element, 'Autoren')
|
||||||
|
for autor in dokument.autoren.all():
|
||||||
|
ET.SubElement(autoren_element, 'Autor').text = autor.name
|
||||||
|
|
||||||
|
pruefende_element = ET.SubElement(doc_element, 'Pruefende')
|
||||||
|
for pruefender in dokument.pruefende.all():
|
||||||
|
ET.SubElement(pruefende_element, 'Pruefender').text = pruefender.name
|
||||||
|
|
||||||
|
gueltigkeit_element = ET.SubElement(doc_element, 'Gueltigkeit')
|
||||||
|
ET.SubElement(gueltigkeit_element, 'Von').text = dokument.gueltigkeit_von.strftime("%Y-%m-%d") if dokument.gueltigkeit_von else ""
|
||||||
|
ET.SubElement(gueltigkeit_element, 'Bis').text = dokument.gueltigkeit_bis.strftime("%Y-%m-%d") if dokument.gueltigkeit_bis else None
|
||||||
|
|
||||||
|
ET.SubElement(doc_element, 'SignaturCSO').text = dokument.signatur_cso
|
||||||
|
|
||||||
|
geltungsbereich_sections = dokument.geltungsbereich_set.all().order_by('order')
|
||||||
|
if geltungsbereich_sections:
|
||||||
|
geltungsbereich_element = ET.SubElement(doc_element, 'Geltungsbereich')
|
||||||
|
for gb in geltungsbereich_sections:
|
||||||
|
section_type = gb.abschnitttyp.abschnitttyp if gb.abschnitttyp else "text"
|
||||||
|
if section_type in ('tabelle', 'table'):
|
||||||
|
table = parse_markdown_table(gb.inhalt)
|
||||||
|
if table is not None:
|
||||||
|
abschnitt_element = ET.SubElement(geltungsbereich_element, 'Abschnitt')
|
||||||
|
abschnitt_element.set('typ', section_type)
|
||||||
|
abschnitt_element.append(table)
|
||||||
|
else:
|
||||||
|
abschnitt_element = ET.SubElement(geltungsbereich_element, 'Abschnitt')
|
||||||
|
abschnitt_element.set('typ', section_type)
|
||||||
|
abschnitt_element.text = gb.inhalt
|
||||||
|
|
||||||
|
einleitung_sections = dokument.einleitung_set.all().order_by('order')
|
||||||
|
if einleitung_sections:
|
||||||
|
einleitung_element = ET.SubElement(doc_element, 'Einleitung')
|
||||||
|
for ei in einleitung_sections:
|
||||||
|
section_type = ei.abschnitttyp.abschnitttyp if ei.abschnitttyp else "text"
|
||||||
|
if section_type in ('tabelle', 'table'):
|
||||||
|
table = parse_markdown_table(ei.inhalt)
|
||||||
|
if table is not None:
|
||||||
|
abschnitt_element = ET.SubElement(einleitung_element, 'Abschnitt')
|
||||||
|
abschnitt_element.set('typ', section_type)
|
||||||
|
abschnitt_element.append(table)
|
||||||
|
else:
|
||||||
|
abschnitt_element = ET.SubElement(einleitung_element, 'Abschnitt')
|
||||||
|
abschnitt_element.set('typ', section_type)
|
||||||
|
abschnitt_element.text = ei.inhalt
|
||||||
|
|
||||||
|
ET.SubElement(doc_element, 'Ziel').text = ""
|
||||||
|
ET.SubElement(doc_element, 'Grundlagen').text = ""
|
||||||
|
|
||||||
|
changelog_element = ET.SubElement(doc_element, 'Changelog')
|
||||||
|
for cl in dokument.changelog.all().order_by('-datum'):
|
||||||
|
entry = ET.SubElement(changelog_element, 'Eintrag')
|
||||||
|
ET.SubElement(entry, 'Datum').text = cl.datum.strftime("%Y-%m-%d")
|
||||||
|
autoren = ET.SubElement(entry, 'Autoren')
|
||||||
|
for autor in cl.autoren.all():
|
||||||
|
ET.SubElement(autoren, 'Autor').text = autor.name
|
||||||
|
ET.SubElement(entry, 'Aenderung').text = cl.aenderung
|
||||||
|
|
||||||
|
anhaenge_element = ET.SubElement(doc_element, 'Anhaenge')
|
||||||
|
ET.SubElement(anhaenge_element, 'Anhang').text = dokument.anhaenge
|
||||||
|
|
||||||
|
ET.SubElement(doc_element, 'Verantwortlich').text = "Information Security Management BIT"
|
||||||
|
ET.SubElement(doc_element, 'Klassifizierung').text = ""
|
||||||
|
|
||||||
|
glossar_element = ET.SubElement(doc_element, 'Glossar')
|
||||||
|
|
||||||
|
vorgaben_element = ET.SubElement(doc_element, 'Vorgaben')
|
||||||
|
|
||||||
|
for vorgabe in dokument.vorgaben.all().order_by('order'):
|
||||||
|
vorgabe_el = ET.SubElement(vorgaben_element, 'Vorgabe')
|
||||||
|
|
||||||
|
ET.SubElement(vorgabe_el, 'Nummer').text = str(vorgabe.nummer)
|
||||||
|
ET.SubElement(vorgabe_el, 'Titel').text = vorgabe.titel
|
||||||
|
ET.SubElement(vorgabe_el, 'Thema').text = vorgabe.thema.name if vorgabe.thema else ""
|
||||||
|
|
||||||
|
kurztext_sections = vorgabe.vorgabekurztext_set.all().order_by('order')
|
||||||
|
if kurztext_sections:
|
||||||
|
kurztext_element = ET.SubElement(vorgabe_el, 'Kurztext')
|
||||||
|
for kt in kurztext_sections:
|
||||||
|
section_type = kt.abschnitttyp.abschnitttyp if kt.abschnitttyp else "text"
|
||||||
|
if section_type in ('tabelle', 'table'):
|
||||||
|
table = parse_markdown_table(kt.inhalt)
|
||||||
|
if table is not None:
|
||||||
|
abschnitt = ET.SubElement(kurztext_element, 'Abschnitt')
|
||||||
|
abschnitt.set('typ', section_type)
|
||||||
|
abschnitt.append(table)
|
||||||
|
else:
|
||||||
|
abschnitt = ET.SubElement(kurztext_element, 'Abschnitt')
|
||||||
|
abschnitt.set('typ', section_type)
|
||||||
|
abschnitt.text = kt.inhalt
|
||||||
|
|
||||||
|
langtext_sections = vorgabe.vorgabelangtext_set.all().order_by('order')
|
||||||
|
if langtext_sections:
|
||||||
|
langtext_element = ET.SubElement(vorgabe_el, 'Langtext')
|
||||||
|
for lt in langtext_sections:
|
||||||
|
section_type = lt.abschnitttyp.abschnitttyp if lt.abschnitttyp else "text"
|
||||||
|
if section_type in ('tabelle', 'table'):
|
||||||
|
table = parse_markdown_table(lt.inhalt)
|
||||||
|
if table is not None:
|
||||||
|
abschnitt = ET.SubElement(langtext_element, 'Abschnitt')
|
||||||
|
abschnitt.set('typ', section_type)
|
||||||
|
abschnitt.append(table)
|
||||||
|
else:
|
||||||
|
abschnitt = ET.SubElement(langtext_element, 'Abschnitt')
|
||||||
|
abschnitt.set('typ', section_type)
|
||||||
|
abschnitt.text = lt.inhalt
|
||||||
|
|
||||||
|
referenz_element = ET.SubElement(vorgabe_el, 'Referenzen')
|
||||||
|
for ref in vorgabe.referenzen.all():
|
||||||
|
ref_text = f"{ref.name_nummer}: {ref.name_text}" if ref.name_text else ref.name_nummer
|
||||||
|
ET.SubElement(referenz_element, 'Referenz').text = ref_text
|
||||||
|
|
||||||
|
vorgabe_gueltigkeit = ET.SubElement(vorgabe_el, 'Gueltigkeit')
|
||||||
|
ET.SubElement(vorgabe_gueltigkeit, 'Von').text = vorgabe.gueltigkeit_von.strftime("%Y-%m-%d") if vorgabe.gueltigkeit_von else ""
|
||||||
|
ET.SubElement(vorgabe_gueltigkeit, 'Bis').text = vorgabe.gueltigkeit_bis.strftime("%Y-%m-%d") if vorgabe.gueltigkeit_bis else None
|
||||||
|
|
||||||
|
checklistenfragen_element = ET.SubElement(vorgabe_el, 'Checklistenfragen')
|
||||||
|
for cf in vorgabe.checklistenfragen.all():
|
||||||
|
ET.SubElement(checklistenfragen_element, 'Frage').text = cf.frage
|
||||||
|
|
||||||
|
stichworte_element = ET.SubElement(vorgabe_el, 'Stichworte')
|
||||||
|
for stw in vorgabe.stichworte.all():
|
||||||
|
ET.SubElement(stichworte_element, 'Stichwort').text = stw.stichwort
|
||||||
|
|
||||||
|
return doc_element
|
||||||
@@ -9,6 +9,7 @@ from django.utils.safestring import SafeString
|
|||||||
import json
|
import json
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
from .models import Dokument, Vorgabe, VorgabeKurztext, VorgabeLangtext, Checklistenfrage, VorgabeComment
|
from .models import Dokument, Vorgabe, VorgabeKurztext, VorgabeLangtext, Checklistenfrage, VorgabeComment
|
||||||
|
from .utils import build_dokument_xml_element, prettify_xml
|
||||||
from abschnitte.utils import render_textabschnitte
|
from abschnitte.utils import render_textabschnitte
|
||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
@@ -17,39 +18,6 @@ import parsedatetime
|
|||||||
calendar=parsedatetime.Calendar()
|
calendar=parsedatetime.Calendar()
|
||||||
|
|
||||||
|
|
||||||
def _parse_markdown_table(markdown_content):
|
|
||||||
"""
|
|
||||||
Parse markdown table content and return XML element with <table><header><row><column> structure
|
|
||||||
"""
|
|
||||||
lines = [line.strip() for line in markdown_content.strip().split('\n') if line.strip()]
|
|
||||||
if not lines:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Create table element
|
|
||||||
table = ET.Element('table')
|
|
||||||
|
|
||||||
# Parse first row as header
|
|
||||||
header_row = [cell.strip() for cell in lines[0].split('|') if cell.strip()]
|
|
||||||
header = ET.SubElement(table, 'header')
|
|
||||||
for cell in header_row:
|
|
||||||
column = ET.SubElement(header, 'column')
|
|
||||||
column.text = cell
|
|
||||||
|
|
||||||
# Parse remaining rows (skip separator row if it exists)
|
|
||||||
for line in lines[2:] if len(lines) > 1 and all(c in '-| ' for c in lines[1]) else lines[1:]:
|
|
||||||
# Check if this is a separator row
|
|
||||||
if all(c in '-| ' for c in line):
|
|
||||||
continue
|
|
||||||
|
|
||||||
row = ET.SubElement(table, 'row')
|
|
||||||
row_cells = [cell.strip() for cell in line.split('|') if cell.strip()]
|
|
||||||
for cell in row_cells:
|
|
||||||
column = ET.SubElement(row, 'column')
|
|
||||||
column.text = cell
|
|
||||||
|
|
||||||
return table
|
|
||||||
|
|
||||||
|
|
||||||
def standard_list(request):
|
def standard_list(request):
|
||||||
dokumente = Dokument.objects.all()
|
dokumente = Dokument.objects.all()
|
||||||
return render(request, 'standards/standard_list.html',
|
return render(request, 'standards/standard_list.html',
|
||||||
@@ -295,7 +263,7 @@ def standard_xml(request, nummer):
|
|||||||
# Get the document with all related data
|
# Get the document with all related data
|
||||||
dokument = get_object_or_404(
|
dokument = get_object_or_404(
|
||||||
Dokument.objects.prefetch_related(
|
Dokument.objects.prefetch_related(
|
||||||
'autoren', 'pruefende', 'vorgaben__thema',
|
'autoren', 'pruefende', 'vorgaben__thema',
|
||||||
'vorgaben__referenzen', 'vorgaben__stichworte',
|
'vorgaben__referenzen', 'vorgaben__stichworte',
|
||||||
'vorgaben__checklistenfragen', 'vorgaben__vorgabekurztext_set',
|
'vorgaben__checklistenfragen', 'vorgaben__vorgabekurztext_set',
|
||||||
'vorgaben__vorgabelangtext_set', 'geltungsbereich_set',
|
'vorgaben__vorgabelangtext_set', 'geltungsbereich_set',
|
||||||
@@ -304,150 +272,21 @@ def standard_xml(request, nummer):
|
|||||||
nummer=nummer
|
nummer=nummer
|
||||||
)
|
)
|
||||||
|
|
||||||
root = ET.Element('Vorgabendokument')
|
# Create a temporary root element to build the document
|
||||||
|
root = ET.Element('root')
|
||||||
ET.SubElement(root, 'Typ').text = dokument.dokumententyp.name if dokument.dokumententyp else ""
|
build_dokument_xml_element(dokument, root)
|
||||||
ET.SubElement(root, 'Nummer').text = dokument.nummer
|
|
||||||
ET.SubElement(root, 'Name').text = dokument.name
|
# Get the actual document element (first child of root)
|
||||||
|
doc_element = root[0]
|
||||||
autoren_element = ET.SubElement(root, 'Autoren')
|
|
||||||
for autor in dokument.autoren.all():
|
xml_str = ET.tostring(doc_element, encoding='unicode', method='xml')
|
||||||
ET.SubElement(autoren_element, 'Autor').text = autor.name
|
xml_output = prettify_xml(xml_str)
|
||||||
|
|
||||||
pruefende_element = ET.SubElement(root, 'Pruefende')
|
|
||||||
for pruefender in dokument.pruefende.all():
|
|
||||||
ET.SubElement(pruefende_element, 'Pruefender').text = pruefender.name
|
|
||||||
|
|
||||||
gueltigkeit_element = ET.SubElement(root, 'Gueltigkeit')
|
|
||||||
ET.SubElement(gueltigkeit_element, 'Von').text = dokument.gueltigkeit_von.strftime("%Y-%m-%d") if dokument.gueltigkeit_von else ""
|
|
||||||
ET.SubElement(gueltigkeit_element, 'Bis').text = dokument.gueltigkeit_bis.strftime("%Y-%m-%d") if dokument.gueltigkeit_bis else None
|
|
||||||
|
|
||||||
ET.SubElement(root, 'SignaturCSO').text = dokument.signatur_cso
|
|
||||||
|
|
||||||
geltungsbereich_sections = dokument.geltungsbereich_set.all().order_by('order')
|
|
||||||
if geltungsbereich_sections:
|
|
||||||
geltungsbereich_element = ET.SubElement(root, 'Geltungsbereich')
|
|
||||||
for gb in geltungsbereich_sections:
|
|
||||||
section_type = gb.abschnitttyp.abschnitttyp if gb.abschnitttyp else "text"
|
|
||||||
if section_type in ('tabelle', 'table'):
|
|
||||||
table = _parse_markdown_table(gb.inhalt)
|
|
||||||
if table is not None:
|
|
||||||
abschnitt_element = ET.SubElement(geltungsbereich_element, 'Abschnitt')
|
|
||||||
abschnitt_element.set('typ', section_type)
|
|
||||||
abschnitt_element.append(table)
|
|
||||||
else:
|
|
||||||
abschnitt_element = ET.SubElement(geltungsbereich_element, 'Abschnitt')
|
|
||||||
abschnitt_element.set('typ', section_type)
|
|
||||||
abschnitt_element.text = gb.inhalt
|
|
||||||
|
|
||||||
einleitung_sections = dokument.einleitung_set.all().order_by('order')
|
|
||||||
if einleitung_sections:
|
|
||||||
einleitung_element = ET.SubElement(root, 'Einleitung')
|
|
||||||
for ei in einleitung_sections:
|
|
||||||
section_type = ei.abschnitttyp.abschnitttyp if ei.abschnitttyp else "text"
|
|
||||||
if section_type in ('tabelle', 'table'):
|
|
||||||
table = _parse_markdown_table(ei.inhalt)
|
|
||||||
if table is not None:
|
|
||||||
abschnitt_element = ET.SubElement(einleitung_element, 'Abschnitt')
|
|
||||||
abschnitt_element.set('typ', section_type)
|
|
||||||
abschnitt_element.append(table)
|
|
||||||
else:
|
|
||||||
abschnitt_element = ET.SubElement(einleitung_element, 'Abschnitt')
|
|
||||||
abschnitt_element.set('typ', section_type)
|
|
||||||
abschnitt_element.text = ei.inhalt
|
|
||||||
|
|
||||||
ET.SubElement(root, 'Ziel').text = ""
|
|
||||||
ET.SubElement(root, 'Grundlagen').text = ""
|
|
||||||
|
|
||||||
changelog_element = ET.SubElement(root, 'Changelog')
|
|
||||||
for cl in dokument.changelog.all().order_by('-datum'):
|
|
||||||
entry = ET.SubElement(changelog_element, 'Eintrag')
|
|
||||||
ET.SubElement(entry, 'Datum').text = cl.datum.strftime("%Y-%m-%d")
|
|
||||||
autoren = ET.SubElement(entry, 'Autoren')
|
|
||||||
for autor in cl.autoren.all():
|
|
||||||
ET.SubElement(autoren, 'Autor').text = autor.name
|
|
||||||
ET.SubElement(entry, 'Aenderung').text = cl.aenderung
|
|
||||||
|
|
||||||
anhaenge_element = ET.SubElement(root, 'Anhaenge')
|
|
||||||
ET.SubElement(anhaenge_element, 'Anhang').text = dokument.anhaenge
|
|
||||||
|
|
||||||
ET.SubElement(root, 'Verantwortlich').text = "Information Security Management BIT"
|
|
||||||
ET.SubElement(root, 'Klassifizierung').text = ""
|
|
||||||
|
|
||||||
glossar_element = ET.SubElement(root, 'Glossar')
|
|
||||||
|
|
||||||
vorgaben_element = ET.SubElement(root, 'Vorgaben')
|
|
||||||
|
|
||||||
for vorgabe in dokument.vorgaben.all().order_by('order'):
|
|
||||||
vorgabe_el = ET.SubElement(vorgaben_element, 'Vorgabe')
|
|
||||||
|
|
||||||
ET.SubElement(vorgabe_el, 'Nummer').text = str(vorgabe.nummer)
|
|
||||||
ET.SubElement(vorgabe_el, 'Titel').text = vorgabe.titel
|
|
||||||
ET.SubElement(vorgabe_el, 'Thema').text = vorgabe.thema.name if vorgabe.thema else ""
|
|
||||||
|
|
||||||
kurztext_sections = vorgabe.vorgabekurztext_set.all().order_by('order')
|
|
||||||
if kurztext_sections:
|
|
||||||
kurztext_element = ET.SubElement(vorgabe_el, 'Kurztext')
|
|
||||||
for kt in kurztext_sections:
|
|
||||||
section_type = kt.abschnitttyp.abschnitttyp if kt.abschnitttyp else "text"
|
|
||||||
if section_type in ('tabelle', 'table'):
|
|
||||||
table = _parse_markdown_table(kt.inhalt)
|
|
||||||
if table is not None:
|
|
||||||
abschnitt = ET.SubElement(kurztext_element, 'Abschnitt')
|
|
||||||
abschnitt.set('typ', section_type)
|
|
||||||
abschnitt.append(table)
|
|
||||||
else:
|
|
||||||
abschnitt = ET.SubElement(kurztext_element, 'Abschnitt')
|
|
||||||
abschnitt.set('typ', section_type)
|
|
||||||
abschnitt.text = kt.inhalt
|
|
||||||
|
|
||||||
langtext_sections = vorgabe.vorgabelangtext_set.all().order_by('order')
|
|
||||||
if langtext_sections:
|
|
||||||
langtext_element = ET.SubElement(vorgabe_el, 'Langtext')
|
|
||||||
for lt in langtext_sections:
|
|
||||||
section_type = lt.abschnitttyp.abschnitttyp if lt.abschnitttyp else "text"
|
|
||||||
if section_type in ('tabelle', 'table'):
|
|
||||||
table = _parse_markdown_table(lt.inhalt)
|
|
||||||
if table is not None:
|
|
||||||
abschnitt = ET.SubElement(langtext_element, 'Abschnitt')
|
|
||||||
abschnitt.set('typ', section_type)
|
|
||||||
abschnitt.append(table)
|
|
||||||
else:
|
|
||||||
abschnitt = ET.SubElement(langtext_element, 'Abschnitt')
|
|
||||||
abschnitt.set('typ', section_type)
|
|
||||||
abschnitt.text = lt.inhalt
|
|
||||||
|
|
||||||
referenz_element = ET.SubElement(vorgabe_el, 'Referenzen')
|
|
||||||
for ref in vorgabe.referenzen.all():
|
|
||||||
ref_text = f"{ref.name_nummer}: {ref.name_text}" if ref.name_text else ref.name_nummer
|
|
||||||
ET.SubElement(referenz_element, 'Referenz').text = ref_text
|
|
||||||
|
|
||||||
vorgabe_gueltigkeit = ET.SubElement(vorgabe_el, 'Gueltigkeit')
|
|
||||||
ET.SubElement(vorgabe_gueltigkeit, 'Von').text = vorgabe.gueltigkeit_von.strftime("%Y-%m-%d") if vorgabe.gueltigkeit_von else ""
|
|
||||||
ET.SubElement(vorgabe_gueltigkeit, 'Bis').text = vorgabe.gueltigkeit_bis.strftime("%Y-%m-%d") if vorgabe.gueltigkeit_bis else None
|
|
||||||
|
|
||||||
checklistenfragen_element = ET.SubElement(vorgabe_el, 'Checklistenfragen')
|
|
||||||
for cf in vorgabe.checklistenfragen.all():
|
|
||||||
ET.SubElement(checklistenfragen_element, 'Frage').text = cf.frage
|
|
||||||
|
|
||||||
stichworte_element = ET.SubElement(vorgabe_el, 'Stichworte')
|
|
||||||
for stw in vorgabe.stichworte.all():
|
|
||||||
ET.SubElement(stichworte_element, 'Stichwort').text = stw.stichwort
|
|
||||||
|
|
||||||
xml_str = ET.tostring(root, encoding='unicode', method='xml')
|
|
||||||
xml_output = _prettify_xml(xml_str)
|
|
||||||
|
|
||||||
response = HttpResponse(xml_output, content_type='application/xml; charset=utf-8')
|
response = HttpResponse(xml_output, content_type='application/xml; charset=utf-8')
|
||||||
response['Content-Disposition'] = f'attachment; filename="{dokument.nummer}.xml"'
|
response['Content-Disposition'] = f'attachment; filename="{dokument.nummer}.xml"'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
def _prettify_xml(xml_string):
|
|
||||||
import xml.dom.minidom
|
|
||||||
dom = xml.dom.minidom.parseString(xml_string)
|
|
||||||
return dom.toprettyxml(indent=" ", encoding="UTF-8").decode('utf-8')
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def get_vorgabe_comments(request, vorgabe_id):
|
def get_vorgabe_comments(request, vorgabe_id):
|
||||||
"""Get comments for a specific Vorgabe"""
|
"""Get comments for a specific Vorgabe"""
|
||||||
|
|||||||
Reference in New Issue
Block a user