Создание вложенного XML-документа в Python - PullRequest
0 голосов
/ 27 июня 2018

Случайный сценарист, я искал этот форум, и он забрал меня так далеко, но я застрял, так что искал помощи. Я пытаюсь создать XML-документ из структуры CSV, и цель состоит в том, чтобы получить что-то, что выглядит примерно так:

ID,Type,Currency,Notional,Underlying,Maturity Date,Representation Type
ID1,COMMIT,EUR,100,,2018-06-01,Bond
ID2,COMMIT,AUD,110,,2018-03-25,Stock

и преобразует это так.

<tradeRequests>     
<tradeRequest>
    <id>ID1</id>
    <newDeals size="1">
        <deal>
            <id>ID1</id>
            <terms>
                <id>ID1</id>
                <MaturityDate>2018-06-01</MaturityDate>                 
            </terms>
        </deal>
    </newDeals>     
</tradeRequest>
<tradeRequest>
    <id>ID2</id>
    <newDeals size="1">
        <deal>
            <id>ID2</id>
            <terms>
                <id>ID2</id>
                <MaturityDate>2018-06-01</MaturityDate>                 
            </terms>
        </deal>
    </newDeals>     
    </tradeRequest> 
</tradeRequests>

Проблема в том, что мой скрипт, похоже, неправильно форматирует элементы, потому что каждая строка по сути должна быть tradeRequest, но я не вижу этот формат.

Вот фрагмент моего кода, который извлечет подмножество столбцов из гораздо большего числа столбцов.

import csv
import xml.etree.ElementTree as ET
import xml.dom.minidom

tradeRequests = ET.Element("tradeRequests")
tradeRequest = ET.SubElement(tradeRequests, "tradeRequest")
newDeals = ET.SubElement(tradeRequest, "newDeals")
deal = ET.SubElement(newDeals, "deal")
dealid = ET.SubElement(deal, "id")

with open('TestCase.csv') as csvfile:
    reader = csv.DictReader(csvfile)

    for row in reader:
        ET.SubElement(tradeRequest, "id").text = row['ID']
        ET.SubElement(tradeRequest, "newDeals", {'size':"1"} )
        ET.SubElement(dealid, "id").text = row['ID']
        ET.SubElement(dealid, "maturityDate").text = row['Maturity Date']
        tree = ET.ElementTree(tradeRequests)
        tree.write("Testcase.xml" )

xml = xml.dom.minidom.parse('Testcase.xml')
pretty_xml_as_string = xml.toprettyxml()

print pretty_xml_as_string

Проблема в том, что я не могу правильно вложить элементы. Я пытался создать комбинацию родитель / потомок, но это не удалось. Вместо этого на основе этого кода я вижу вывод, который выглядит следующим образом.

<tradeRequests>
    <tradeRequest>
        <newDeals>
            <deal>
                <id>
                    <id>ID1</id>
                    <maturityDate>2018-06-01</maturityDate>
                    <id>ID2</id>
                    <maturityDate>2018-03-25</maturityDate>
                </id>
            </deal>
        </newDeals>
        <id>ID1</id>
        <newDeals size="1"/>
        <id>ID2</id>
        <newDeals size="1"/>
    </tradeRequest>
</tradeRequests>

Любая помощь ценится как всегда.

Я не ожидал этого пользовательского сценария, где мне нужно циклически создавать и создавать элементы динамически

ID1,COMMIT,EUR,100,,2018-06-01,Bond
ID2,110,2018-03-25,Stock
ID2,110,2018-03-26,A
ID2,110,2018-03-26,B
ID2,110,2018-03-26,C

Таким образом, по сути, мне нужно создать элемент, который будет проходить через ID2 и динамически создавать новый элемент в зависимости от количества строк, что неизвестно.

поэтому мои ожидаемые результаты будут примерно такими:

<tradeRequests>
    <ids>
    <id>ID1</id>
            <element>
                <maturityDate>2018-06-01</maturityDate>
                <type>Stock</type
            <element>
        </id>
        <id>ID2</id>
            <element>
                <maturityDate>2018-03-25</maturityDate>
                <type>A</type>
            </element>
            <element>
                <maturityDate>2018-03-25</maturityDate>
                <type>B</type>
            </element>
                <maturityDate>2018-03-25</maturityDate>
                <type>C</type>
            </element>
        </id>
</tradeRequests>

1 Ответ

0 голосов
/ 27 июня 2018

Я настоятельно рекомендую использовать превосходную библиотеку lxml. Это действительно быстро, потому что это оболочка, основанная на библиотеке C libxml2, и она включает в себя объект конструктора элементов E, который делает ваш работа действительно легкая:

import csv
import lxml.etree
from lxml.builder import E

with open('TestCase.csv') as csvfile:
    results = E.tradeRequests(*(
        E.tradeRequest(
            E.id(row['ID']),
            E.newDeals(
                E.deal(
                    E.id(row['ID']),
                    E.terms(
                        E.id(row['ID']),
                        E.MaturityDate(row['Maturity Date']),
                    )
                ),
                size="1",
            )
        ) for row in csv.DictReader(csvfile))
    )

print(lxml.etree.tostring(results, pretty_print=True))

Результаты:

<tradeRequests>
  <tradeRequest>
    <id>ID1</id>
    <newDeals size="1">
      <deal>
        <id>ID1</id>
        <terms>
          <id>ID1</id>
          <MaturityDate>2018-06-01</MaturityDate>
        </terms>
      </deal>
    </newDeals>
  </tradeRequest>
  <tradeRequest>
    <id>ID2</id>
    <newDeals size="1">
      <deal>
        <id>ID2</id>
        <terms>
          <id>ID2</id>
          <MaturityDate>2018-03-25</MaturityDate>
        </terms>
      </deal>
    </newDeals>
  </tradeRequest>
</tradeRequests>
...