Генератор XML со случайными значениями через скрипт Python
Не могли бы вы подсказать правильно ли я написал код под задачу, и можно ли его оптимизировать?
Задача:
Создать скрипт Python для генерирования XML-чеков со случайными значениями в определённом диапазоне.
Пример чека:
<?xml version="1.0" encoding="UTF-8"?>
<Cheque
inn="0000000000"
kpp="000000000"
address="Test"
name="Test"
kassa="1"
shift="1"
number="1"
datetime="0101150000"
>
<Bottle
price="10.00"
barcode="22N00000XOPN13MM66T0HVF311220130003476539219152175585956302712947101"
ean="4607005090812"
volume="1.0000"
/>
</Cheque>
Сделать нужно по этой XSD схеме:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Cheque" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Cheque">
<xs:complexType>
<!-- случайное из файла -->
<xs:attribute name="inn" type="IN" use="required" />
<!-- случайное в соответствие с типом-->
<xs:attribute name="kpp" type="KP" />
<!-- случайный набор русских букв и 2ух пробелов, общая длина от 20
до 100 -->
<xs:attribute name="address" type="ADDRESS" use="required" />
<!-- случайный набор русских букв длиной от 10 до 20-->
<xs:attribute name="name" type="xs:string" use="required" />
<!-- случайный набор латинских букв и цифр длиной от 6 до 12-->
<xs:attribute name="kassa" type="xs:string" use="required" />
<!-- случайное в соответствие с типом-->
<xs:attribute name="shift" type="xs:int" use="required" />
<!-- случайное в соответствие с типом-->
<xs:attribute name="number" type="xs:int" use="required" />
<!-- случайное в соответствие с типом-->
<xs:attribute name="datetime" type="DT" use="required" />
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="Bottle">
<xs:complexType>
<!-- случайное от 100.00 до 1000.00 -->
<xs:attribute name="price" type="PRICE" use="required"/>
<!-- случайное в соответствие с типом-->
<xs:attribute name="barcode" type="BK" use="required" />
<!-- случайное из файла -->
<xs:attribute name="ean" type="EAN" use="required" />
<!-- случайное от 0.1000 до 3.0000 с шагом 0.05-->
<xs:attribute name="volume" type="VOLUME" />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
<xs:unique name="bottleBarcode">
<xs:selector xpath="Bottle" />
<xs:field xpath="@barcode" />
</xs:unique>
</xs:element>
<xs:simpleType name="IN">
<xs:restriction base="xs:string">
<xs:pattern value="(от 1 до 10\d{10}|\d{12})"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="KP">
<xs:restriction base="xs:string">
<xs:pattern value="(от 1 до 10\d{9}|)"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="DT">
<xs:restriction base="xs:string">
<xs:pattern value="[0-3][0-9][0-1][0-9][0-9]{2}[0-2][0-9][0-5][0-9]"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="BK">
<xs:restriction base="xs:string">
<xs:pattern value="\d\dN\w{20}\d[0-1]\d[0-3]\d{10}\w{31}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="EAN">
<xs:restriction base="xs:string">
<xs:pattern value="(от 1 до 10\d{8}|\d{13}|\d{12}|\d{14})"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PRICE">
<xs:restriction base="xs:string">
<xs:pattern value="[-]?\d+\.\d{0,2}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="VOLUME">
<xs:restriction base="xs:string">
<xs:pattern value="(от 1 до 10\d+\.?\d{0,4}|)"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ADDRESS">
<xs:restriction base="xs:string">
<xs:maxLength value="128"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
Вот мой скрипт:
import xml.etree.ElementTree as ET
import random
import string
# Читаем содержимое файлов EAN.txt и INN.txt
with open("EAN.txt", "r") as f_ean:
ean_list = [line.strip() for line in f_ean]
with open("INN.txt", "r") as f_inn:
inn_list = [line.strip() for line in f_inn]
# Создаем корневой элемент
cheque = ET.Element("Cheque")
ean = random.choice(ean_list)
inn = random.choice(inn_list)
# Создаём функцию генератор рандомных зачений
def generate_random_value(data_type, min_value, max_value, step=None):
if data_type == "int":
return str(random.randint(min_value, max_value))
elif data_type == "float":
if step is None:
return random.uniform(min_value, max_value)
else:
return round(random.uniform(min_value, max_value), step)
elif data_type == "str_rus":
return ''.join(random.choice(string.ascii_letters + "абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ") for _ in range(random.randint(10, 20)))
elif data_type == "str_lat":
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(random.randint(6, 12)))
elif data_type == "barcode":
return "22N" + "".join(random.choice(string.ascii_uppercase + string.digits) for _ in range(12)) + "MM66T0HVF311220130003476539219152175585956302712947101"
elif data_type == "datetime":
return f"{random.randint(1, 31)}{random.randint(1, 12)}{random.randint(2000, 2024)}{random.randint(0, 23)}{random.randint(0, 59)}{random.randint(0, 59)}"
else:
raise ValueError(f"Неизвестный тип данных: {data_type}")
# Добавляем атрибуты корневому элементу
cheque.set("inn", inn)
# случайное в соответствие с типом
cheque.set("kpp", generate_random_value("str_lat", 9, 10))
# случайный набор русских букв и 2ух пробелов, общая длина от 20 до 100
cheque.set("address", generate_random_value("str_rus", 20, 100))
# случайный набор русских букв длиной от 10 до 20
cheque.set("name", generate_random_value("str_rus", 10, 20))
# случайный набор латинских букв и цифр длиной от 6 до 12
cheque.set("kassa", generate_random_value("str_lat", 6, 12))
# случайное в соответствие с типом
cheque.set("shift", generate_random_value("int", 1, 10))
# случайное в соответствие с типом
cheque.set("number", generate_random_value("int", 1, 10))
# случайное в соответствие с типом
cheque.set("datetime", "0101150000")
# Создаем элемент "Bottle"
bottle = ET.Element("Bottle")
# Добавляем атрибуты элементу "Bottle"
# случайное от 100.00 до 1000.00
bottle.set("price", "10.00")
# случайное в соответствии с типом
bottle.set("barcode", "22N00000XOPN13MM66T0HVF311220130003476539219152175585956302712947101")
bottle.set("ean", ean)
# случайное от 0.1000 до 3.0000 с шагом 0.05
bottle.set("volume", "1.0000")
# Добавляем элемент "Bottle" к корневому элементу
cheque.append(bottle)
xml_string = ET.tostring(cheque, encoding="unicode")
# Записываем XML строку в файл
with open("cheque.xml", "w", encoding="utf-8") as f:
f.write(xml_string)