使用Python和Regular表达式编辑本地XML文件

时间:2018-02-25 18:04:44

标签: python regex xml lxml elementtree

我是python的新手,并尝试修改本地系统中存在的一些xml配置文件。

输入:我有一个包含以下内容的xml文件(比如Test.xml)。

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <JavaHost xmlns="SomeInfo/v1.1">
        <Domain>
           <MessageProcessor>
              <!-- This comment should not be removed and all formating should be untouched -->
              <SocketTimeout>500</SocketTimeout>
           </MessageProcessor>
            <!-- This comment should not be removed and all formating should be untouched -->
           <Composer>
                <SocketTimeout>5000</SocketTimeout>
                <Enabled>true</Enabled>
           </Composer> 
       </Domain>
    </JavaHost>

我想要达到的目标: 我想要达到以下两点:

第1部分: 我想将SocketTimeout标记的值(仅在composer标记下)修改为60,并且还想添加这样的注释(例如,更改此值以减少SocketTimeout)。 因此文件Test.xml应如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <JavaHost xmlns="SomeInfo/v1.1">
       <MessageProcessor>
          <!-- This comment should not be removed and all formating should be untouched -->
          <SocketTimeout>500</SocketTimeout>
       </MessageProcessor>
        <!-- This comment should not be removed and all formating should be untouched -->
       <Composer>
       <!-- Changed this value to reduce SocketTimeout -->
            <SocketTimeout>60</SocketTimeout>
            <Enabled>true</Enabled>
       </Composer>
   </Domain>
</JavaHost>

第2部分: 在Test.xml文件中,我想在Domain标记下添加一个新标记,如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <JavaHost xmlns="SomeInfo/v1.1">
       <MessageProcessor>
          <!-- This comment should not be removed and all formating should be untouched -->
          <SocketTimeout>500</SocketTimeout>
       </MessageProcessor>
       <!-- comment should not be removed and all formatting should be untouched -->
       <Composer>
       <!-- Changed this value to reduce SocketTimeout -->
            <SocketTimeout>60</SocketTimeout>
            <Enabled>true</Enabled>
       </Composer>
       <New_tag>
       <!-- New Tag -->
            <Enabled>true</Enabled>
       </New_tag>
   </Domain>
</JavaHost>

这就是我想要的:)

我做过什么:

为了完成这项任务,我在下面考虑了optons:

Minidom / ElementTree / lxml删除文件中的注释,并更改文件的格式。

正则表达式:不会删除评论,也不会打扰格式化。 因此,我选择了正则表达式,以下是我开始使用的,但是不起作用:(

import os, re
# set the working directory 
os.chdir('C:\\Users\\Dell\\Desktop\\')

# open the source file and read it
fh = open('C:\\Users\\Dell\\Desktop\\Test.xml', 'r')
subject = fh.read()
fh.close()

pattern = re.compile(r"\[<Composer>\].*?\[/<Composer>\]")
#Replace
result = pattern.sub(lambda match: match.group(0).replace('<SocketTimeout>500</SocketTimeout>','<SocketTimeout>60</SocketTimeout>') ,subject)

# write the file
f_out = open('C:\\Users\\Dell\\Desktop\\Test.xml', 'w')
f_out.write(result)
f_out.close()

任何实现我想要的想法或纠正错误的想法都会非常值得注意。 虽然我是python的新手,但我会尽力研究这些建议。

1 个答案:

答案 0 :(得分:2)

这不是完全你想要什么,但它已经接近了。首先,避免使用正则表达式来处理xml,html和类似处理,如瘟疫。与此同时,如果您偶尔发现挑战,请不要感到惊讶。使用像lxml这样的产品。

我想,这一次,我发现了一个错误。

from lxml import etree
tree = etree.parse('shivam.xml')
element_to_change = tree.xpath('.//Composer/SocketTimeout')[0]
print(element_to_change)
element_to_change.text='60'
comment_will_follow_this = tree.xpath('.//Composer')[0]
print(comment_will_follow_this)
comment = etree.Comment('This did not work')
comment_will_follow_this.append(comment)

comment = etree.Comment('Changed this value to reduce SocketTimeout')
element_to_change.addprevious(comment)

tree.write('see_it.xml', pretty_print=True)
  • 我使用xpath查找要更改的元素,以及文件中用于接收注释的位置。
  • append方法应该将注释或其他元素作为子元素添加到给定元素。但是,在这种情况下,我发现“这不起作用”#39;评论被添加为前面的元素评论。
  • 但是,我确实发现addprevious能够在所需的位置添加注释,美中不足的是它无法在注释和下一个xml元素之间放置一个结束线。 / LI>

这是生成的文件。从表面上看,您会注意到原始评论是完整的。

<JavaHost>
    <Domain>
       <MessageProcessor>
          <!-- This comment should not be removed and all formating should be untouched -->
          <SocketTimeout>500</SocketTimeout>
       </MessageProcessor>
        <!-- This comment should not be removed and all formating should be untouched -->
       <Composer>
            <!--Changed this value to reduce SocketTimeout--><SocketTimeout>60</SocketTimeout>
            <Enabled>true</Enabled>
       <!--This did not work--></Composer> 
   </Domain>
</JavaHost>