Проблема Python с использованием документа xml.dom.minidom. Дополнительные пустые строки между дочерними элементами с использованием toprettyxml()

Пожалуйста, потерпите меня, так как я ОЧЕНЬ новичок в python (и в большом сообществе программистов), но меня направляет коллега с большим опытом, чем у меня. Мы пытаемся написать скрипт python, который читается в XML файл и выбирает определенные части данных, редактирует некоторые значения переменных, а затем повторно собирает XML. Проблема, с которой мы сталкиваемся, заключается в том, что данные форматируются, когда они передаются обратно в новую операцию с помощью toprettyxml().

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

Итак, вот какими примерно должны быть соответствующие фрагменты кода:

def __handleElemsWithAtrributes(elem):
    #returns empty element with all attributes of source element
    tmpDoc = Document()
    result = tmpDoc.createElement(elem.item(0).tagName)
    attr_map = elem.item(0).attributes
    for i in range(attr_map.length):
        result.setAttribute(attr_map.item(i).name,attr_map.item(i).value)
    return result

def __getWholeElement(elems):
    #returns element with all attributes of source element and all contents
    if len(elems) == 0:
        return 0
    temp = Document()
    for e in elems:
        result = temp.createElement(e.tagName)
        attr_map = e.attributes
        for i in range(attr_map.length):
            result.setAttribute(attr_map.item(i).name,attr_map.item(i).value)
        result = e
    return result


def __init__():
      ##A bunch of other stuff I'm leaving out...
                f = xml.dom.minidom.parse(pathToFile)
                doc = Document()

                modules = f.getElementsByTagName("Module")
                descriptions = f.getElementsByTagName("Description")
                steptree = f.getElementsByTagName("StepTree")
                reference = f.getElementsByTagName("LessonReference")

                mod_val = __handleElemsWithAtrributes(modules)
                des_val = __getWholeElement(descriptions)
                step_val = __getWholeElement(steptree)
                ref_val = __getWholeElement(reference)

                if des_val != 0 and mod_val != 0 and step_val != 0 and ref_val != 0:
                    mod_val.appendChild(des_val)
                    mod_val.appendChild(step_val)
                    mod_val.appendChild(ref_val)
                    doc.appendChild(mod_val)
               o.write(doc.toprettyxml())

Нет, табуляция здесь не точно сохранена, потому что я скопировал из нескольких разных областей, но я уверен, что вы поняли суть.

В основном ввод, который я использую, выглядит примерно так:

<Module aatribute="" attribte2="" attribute3="" >
<Description>
    <Title>SomeTitle</Title>
    <Objective>An objective</Objective>
    <Action>
        <Familiarize>familiarize text</Familiarize>
    </Action>
    <Condition>
        <Familiarize>Condition text</Familiarize>
    </Condition>
    <Standard>
        <Familiarize>Standard text</Familiarize>
    </Standard>
    <PerformanceMeasures>
        <Measure>COL text</Measure>
    </PerformanceMeasures>
    <TMReferences>
        <Reference>Reference text</Reference> 
    </TMReferences>
</Description>

А потом при сборке получается что-то вроде этого:

<Module aatribute="" attribte2="" attribute3="" >
<Description>


    <Title>SomeTitle</Title>


    <Objective>An objective</Objective>


    <Action>


        <Familiarize>familiarize text</Familiarize>


    </Action>


    <Condition>


        <Familiarize>Condition text</Familiarize>


    </Condition>


    <Standard>


        <Familiarize>Standard text</Familiarize>


    </Standard>


    <PerformanceMeasures>


        <Measure>COL text</Measure>


    </PerformanceMeasures>


    <TMReferences>


        <Reference>Reference text</Reference> 


    </TMReferences>


</Description>

Как мне заставить его прекратить делать все лишние пустые строки? Есть идеи?


person SgtMac02    schedule 05.04.2012    source источник


Ответы (2)


У меня такая же проблема. Дело в том, что каждый раз, когда Python переходит через строку, он добавляет для этого textNode в ваше дерево. Следовательно, topprettyxml() — очень порочная функция, потому что она добавляет узел в ваше дерево без вашего ведома.

Одним из решений было бы найти способ стереть все бесполезные текстовые узлы при разборе файла в начале (я ищу его прямо сейчас, но до сих пор не нашел «красивого» решения).

Удаление узла за узлом:

def cleanUpNodes(nodes):
    for node in nodes.childNodes:
        if node.nodeType == Node.TEXT_NODE:
            node.data = ''
    nodes.normalize()

из http://mail.python.org/pipermail/xml-sig/2004-March/010191.html

person Lilley    schedule 06.05.2012

Спасибо, это работает рекурсивно!

def cleanUpNodes(self,nodes):
        for node in nodes.childNodes:
            if node.nodeType == node.TEXT_NODE and (node.data.startswith('\t') or node.data.startswith('\n') or node.data.startswith('\r') ):
                node.data = ''
            if node.nodeType == node.ELEMENT_NODE:
                self.cleanUpNodes(node)
        nodes.normalize()
person frank schmidt    schedule 13.10.2015