Python. Выгрузка sql запроса в xml

Столкнулся с проблемой выгрузки в xml нескольких связных таблиц. Получается, что при связке 1 к многим повторяются заголовки,то есть в 1 накладной несколько ресурсов и выводится все построчно. Поэтому не могу сделать объединение наименований накладных для ресурсов.

Требуется: Накладная:ресурс+ресурс

Спасибо!

import os,cx_Oracle,lxml

def fetchall_xml(cur, pretty_print=True):
    import lxml.etree
    
    fields_value = cur.fetchall()
    fields_name = tuple(i[0] for i in cur.description)

    Message=lxml.etree.Element('Message', attrib={'xmlns': 't'})
    elements = lxml.etree.SubElement(Message,'Body', attrib={'xmlns': 't'})
    
    for el in fields_value:
        element = lxml.etree.SubElement(elements, 'Накладная')
       
        lxml.etree.SubElement(element, str(fields_name[0])).text = '{}'.format(el[0])

        S_GUID = lxml.etree.SubElement(element, 'Ключевыесвойства')

        S_GUID2 = lxml.etree.SubElement(S_GUID, 'Данные')
        lxml.etree.SubElement(S_GUID2, str(fields_name[1])).text = '{}'.format(el[1])
        lxml.etree.SubElement(S_GUID2, str(fields_name[2])).text = '{}'.format(el[2])
        lxml.etree.SubElement(element, str(fields_name[3])).text = '{}'.format(el[3])    
 
           
    return lxml.etree.tounicode(Message, pretty_print=pretty_print)


def main():
    
    
    dbb = cx_Oracle.connect("admin","1234","pentagon")
    cur = dbb.cursor()
    cur.execute("SELECT  N.STRCODE  AS STRCODE, NS.POSITION_NAME,NS.QUANTITY,NS.RES_ID AS RES_ID FROM N , Ns WHERE ns.n_id = n.id AND n.id in (486558,480055)")  

    xml = fetchall_xml(cur)
    print(xml)
    with open("output2222.xml", 'w',encoding = 'utf-8') as doc:
       doc.write(xml)
       

main()

Ответы (1 шт):

Автор решения: Александр Александров

Так как идет выгрузка из oracle, то лучше формировать структуру xml в запросе, а результат записывать в файл. В статье описано как формировать нужную структуру https://oracle-base.com/articles/misc/sqlxml-sqlx-generating-xml-content-using-sql

код будет похож на ниже представленный:

import os,cx_Oracle,itertools


os.chdir("D:/py")


db =cx_Oracle.connect("admin","1234","pentagon")
cursor = db.cursor()


#sql=('SELECT XMLELEMENT("contract_list",XMLAGG (XMLELEMENT("contract",XMLATTRIBUTES(ch.STRCODE AS "STRCODE"),XMLFOREST((SELECT XMLAGG(XMLELEMENT("res",XMLFOREST(cS.NAMERES AS "pos"))) FROM   M2_ALL.contractspecification cs WHERE  cS.con_ID = ch.con_id) "res_list")))).getClobVal() AS "depts" FROM   m2_All.contracthistory ch where ch.flaghist=1 ')
#sql='SELECT XMLELEMENT ("rs_list",XMLAGG (XMLELEMENT ("rs",XMLATTRIBUTES (rs.STRCODE AS "STRCODE")))).getClobVal () AS "depts"FROM m2_All.resources rs where rownum=1'


sql= """
SELECT   XMLELEMENT (
            "Message",
            XMLAttributes ('http://www.1c.ru/SSL/Exchange/Message' as "xmlns:msg",
                                            'http://www.w3.org/2001/XMLSchema' as "xmlns:xs",
                                              'http://www.w3.org/2001/XMLSchema-instance' as "xmlns:xsi"  ),
            (XMLELEMENT("msg:Header",
                  XMLELEMENT("msg:Format",'http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.8'),
                  XMLELEMENT("msg:CreationDate",(select (sysdate) from dual)),
                  XMLELEMENT("msg:Confirmation",
                                   XMLELEMENT("msg:ExchangePlan",'СинхронизацияДанныхЧерезУниверсальныйФормат'),
                                   XMLELEMENT("msg:To",'3dadf8ee-4098-4cef-9f9e-e5b4d37848c6'),
                                   XMLELEMENT("msg:MessageNo",'0'),
                                   XMLELEMENT("msg:ReceivedNo",'1')       )  ,
                  XMLELEMENT("msg:AvailableVersion",'1.8'),
                  XMLELEMENT("msg:AvailableVersion",'1.7') ,
                  XMLELEMENT("msg:AvailableVersion",'1.6') ,
                  XMLELEMENT("msg:AvailableVersion",'1.5') ,
                  XMLELEMENT("msg:AvailableVersion",'1.4') ,
                  XMLELEMENT("msg:AvailableVersion",'1.3'),                
                  XMLELEMENT("msg:Prefix",'B1')                ))
            ,(XMLELEMENT (
                "body",
                XMLAttributes (
                   'http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.8' AS "xmlns"
                ),
                 XMLAGG(XMLELEMENT (
                   "Справочник.ЕдиницыИзмерения",
                   (XMLELEMENT (
                       "КлючевыеСвойства",
                       (XMLELEMENT (
                           "Ссылка", (   SUBSTR (SYS_GUID (), 1, 8)|| '-'|| SUBSTR (SYS_GUID (), 9, 4)|| '-'|| SUBSTR (SYS_GUID (), 13, 4)|| '-'|| SUBSTR (SYS_GUID (), 17, 4)|| '-'|| SUBSTR (SYS_GUID (), 21))
                        )),
                       XMLELEMENT ("ДанныеКлассификатора",
                                   (XMLELEMENT ("Код", u.strcode)),
                                   (XMLELEMENT ("Наименованиие", u.name)))
                    ))
                    , XMLELEMENT ("НаименованиеПолное",U.FULLNAME )
                ))
             ))
         ).getClobVal ()
            AS "ui"
  FROM   table.unit u
group by sysdate """ 

s=cursor.execute(sql)

myString = ''.join(map(str, itertools.chain(*s)))

with open("EI.xml", 'w',encoding = 'utf-8') as doc:
       doc.write(myString)
cursor.close()
db.close()

→ Ссылка