2015-09-18 4 views
1

У меня есть много файлов xml, которые мне нужно объединить. Я попробовал эту ссылку на merging xml files using python's ElementTree , код которого (под редакцией согласно моей потребности):Слияние большого количества XML-файлов

import os, os.path, sys 
import glob 
from xml.etree import ElementTree 

def run(files): 
    xml_files = glob.glob(files +"/*.xml") 
    xml_element_tree = None 
    for xml_file in xml_files: 
     print xml_file 
     data = ElementTree.parse(xml_file).getroot() 
     # print ElementTree.tostring(data) 
     for result in data.iter('TALLYMESSAGE'): 
      if xml_element_tree is None: 
       xml_element_tree = data 
       insertion_point = xml_element_tree.findall("./BODY/DATA/TALLYMESSAGE")[0] 
      else: 
       insertion_point.extend(result) 
    if xml_element_tree is not None: 
     f = open("myxmlfile.xml", "wb") 
     f.write(ElementTree.tostring(xml_element_tree)) 
run("F:/data/data") 

Но проблема в том, что у меня есть много XML файла, 365, чтобы быть точным, и каждый из них по крайней мере 2 Мб. слияние их всех привело к сбою моего ПК. Это образ XML-дерева моего XML-файла: XML element tree

Мой новый обновленный код является:

import os, os.path, sys 
import glob 
from lxml import etree 
def XSLFILE(files): 
    xml_files = glob.glob(files +"/*.xml") 
    #print xml_files[0] 
    xslstring = """<?xml version="1.0" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:template match="/DATA"> 
<DATA> 
<xsl:copy> 
<xsl:copy-of select="TALLYMESSAGE"/>\n""" 
    #print xslstring 
    for xmlfile in xml_files[1:]: 
     xslstring = xslstring + '<xsl:copy-of select="document(\'' + xmlfile[-16:] + "')/BODY/DATA/TALLYMESSAGE\"/>\n" 
    xslstring = xslstring + """</xsl:copy>+ 
</DATA> 
</xsl:template> 
</xsl:transform>""" 
    #print xslstring 
    with open("parsingxsl.xsl", "w") as f: 
     f.write(xslstring) 
    with open(xml_files[0], "r") as f: 
     dom = etree.XML(f.read()) 
    print etree.tostring(dom) 
    with open('F:\data\parsingxsl.xsl', "r") as f: 
     xslt_tree = etree.XML(f.read()) 
    print xslt_tree 
    transform = etree.XSLT(xslt_tree) 
    newdom = transform(dom) 
    #print newdom 
    tree_out = etree.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True) 
    print(tree_out) 

    xmlfile = open('F:\data\OutputFile.xml','wb') 
    xmlfile.write(tree_out) 
    xmlfile.close() 
XSLFILE("F:\data\data") 

То же при запуске создает следующее сообщение об ошибке:

Traceback (most recent call last): 
    File "F:\data\xmlmergexsl.py", line 38, in <module> 
    XSLFILE("F:\data\data") 
    File "F:\data\xmlmergexsl.py", line 36, in XSLFILE 
    xmlfile.write(tree_out) 
TypeError: must be string or buffer, not None 

ответ

2

Учитывать используя XSLT и его функцию document() для объединения файлов XML. Python (как и многие объектно-ориентированные языки программирования) поддерживает XSLT processor, как в своем модуле lxml. Как информация, XSLT является декларативным языком программирования для преобразования XML-файлов в различные форматы и структуры.

Для ваших целей XSLT может быть более эффективным, чем использование кода программирования для разработки файлов, поскольку в процессе обработки в памяти не хранятся списки или циклы или другие объекты, кроме того, что будет использовать процессор XSLT.

XSLT (для сохранения наружно в виде файла .xsl)

Рассмотрим сначала запустить Python запись в текстовый файл зацикливание заполнить все 365 документов, чтобы избежать копирования и вставки. Также обратите внимание на первый документ пропускается, поскольку он является отправной точкой используется в сценарии Python ниже:

<?xml version="1.0" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

<xsl:template match="DATA"> 
    <DATA> 
    <xsl:copy> 
     <xsl:copy-of select="TALLYMESSAGE"/> 
     <xsl:copy-of select="document('Document2.xml')/BODY/DATA/TALLYMESSAGE"/> 
     <xsl:copy-of select="document('Document3.xml')/BODY/DATA/TALLYMESSAGE"/> 
     <xsl:copy-of select="document('Document4.xml')/BODY/DATA/TALLYMESSAGE"/> 
     ... 
     <xsl:copy-of select="document('Document365.xml')/BODY/DATA/TALLYMESSAGE"/>    
    </xsl:copy> 
    </DATA> 
</xsl:template> 

</xsl:transform> 

Python (которые должны быть включены в вас общий сценарий)

import lxml.etree as ET 

dom = ET.parse('C:\Path\To\XML\Document1.xml') 
xslt = ET.parse('C:\Path\To\XSL\file.xsl') 
transform = ET.XSLT(xslt) 
newdom = transform(dom) 

tree_out = ET.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True) 
print(tree_out) 

xmlfile = open('C:\Path\To\XML\OutputFile.xml','wb') 
xmlfile.write(tree_out) 
xmlfile.close() 
+0

Это ошибка я m receive .: Traceback (последний последний звонок): Файл «F: \ data \ xmlmergexsl.py», строка 32, в XSLFILE («F: \ data \ data») Файл «F: \ data \ xmlmergexsl.py ", строка 30, в XSLFILE xmlfile.wr ite (tree_out) ТипError: должен быть строкой или буфером, а не None –

+0

См. обновленный XSLT. где корневой узел явно объявлен. Было бы полезно увидеть образец XML-файла. Кроме того, убедитесь, что все файлы XML находятся в одном каталоге. – Parfait

+0

Я добавил изображение структуры моего xml-файла. каждый из них имеет эту основную стратегию точно такой же. единственные различия в элементе ваучера. –

Смежные вопросы