删除和替换XML文件中的特定节点

时间:2014-02-12 20:04:11

标签: python xml parsing minidom musicxml

我一直致力于一个分析乐谱并从中删除特定音符的项目。现在我已经从我的代码中获得了所需的信息,现在我需要使用我的新信息编辑原始XML分数。我在Python中这样做并且已经使用了Minidom所以我显然希望坚持这一点(我知道这可能是一个愚蠢的选择,因为这里的很多帖子推荐不同的XML解析方法,因为不太友好的界面目前在Minidom)。

所以在我原来的XML文件中说我有一个由10个音符组成的音乐作品。注释的XML格式如下所示:

<note>
  <pitch>
    <step>E</step>
    <alter>-1</alter>
    <octave>5</octave>
  </pitch>
  <duration>72</duration>
</note>

因此,对于每个音符值,这将重复10次。现在我已经完成了我的分析,我想删除其中的5个注释。删除我的意思是替换为休息(因为它毕竟是一个乐谱,它有一个符合的形状)。因此,XML文件中休息的格式如下所示:

<note>
    <rest/>
    <duration>72</duration>
</note>

所以我要做的就是删除音高标签并用rest标签替换它。但是我不确定如何解决这个问题,从我的搜索中找不到任何看似相似的内容。

我对找到要删除的笔记的位置并不感到困扰,因为我已经编写了一个快速测试工具来展示我将如何在Python中进行下面的操作(xml_format本质上只是包含我的新信息的字典列表)。它包含与原始XML文件相同数量的注释,唯一的区别是它们中的一些现在被标记为被删除。所以原始文件可能有如下注释:G,Bb,D,C,G,F,G,D,Bb和xml_format将有G,Bb,D,REMOVE,G,REMOVE,G,D,Bb等。

我刚刚回来了,以确保删除正确数量的笔记。

def remove_notes(xml_format, filename):

doc = minidom.parse(filename)                 
count = 0
a = 0
note = doc.getElementsByTagName("note")  

for item in note:
    if xml_format[count]['step'] == 'Remove':
        a = a + 1
        # THEN REMOVE THE ENTIRE PITCH TAG, REPLACE WITH REST
    count = count + 1
    # ELSE DON'T DO ANYTHING

return a 

所以基本上我只是在寻找一些语法或代码方面的帮助,这些语法或代码可以用来删除特定点上的特定节点,然后在写入新文件之前用新节点替换。非常感谢您的帮助,我希望这是可能的(逻辑似乎并不复杂,但谁知道什么是可能的)!

1 个答案:

答案 0 :(得分:0)

每个<note>节点需要做的是:

  1. 创建新的<rest/>节点
  2. 找到<pitch>节点
  3. <pitch>节点替换为新的<rest/>节点
  4. 以下是代码:

    def remove_notes(xml_format, filename):
        doc = minidom.parse(filename)                 
        count = 0
        a = 0
        note_nodes = doc.getElementsByTagName("note")  
    
        for note_node in note_nodes:
            if xml_format[count]['step'] == 'Remove':
                a = a + 1
    
                # Create a <rest/> node
                rest_node = note_node.ownerDocument.createElement('rest')
    
                # Locate the <pitch> node
                pitch_node = note_node.getElementsByTagName('pitch')[0]
    
                # Replace pitch with rest
                note_node.replaceChild(rest_node, pitch_node)
    
            count = count + 1
            # ELSE DON'T DO ANYTHING
    
        # Finished with the loop, doc now contains the replaced nodes, we need
        # to write it to a file    
    
        return a 
    

    请注意,您需要将更改写入新文件,否则您的更改将会丢失。