Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:xml.etree.ElementTree破坏xml格式_Python_Xml_Python 2.7_Installshield - Fatal编程技术网

Python:xml.etree.ElementTree破坏xml格式

Python:xml.etree.ElementTree破坏xml格式,python,xml,python-2.7,installshield,Python,Xml,Python 2.7,Installshield,我有一个格式化为XML的ISM文件(InstallShield项目) 我需要更改文件中的一些属性,所以我使用了xml.etree.ElementTree(Python库) 我可以找到这些值并对其进行更改,但是,在使用更新的值保存文件后,我无法在InstallShield中打开它(我遇到一个常规错误,文件无法打开) 当我比较新文件和旧文件时,我发现在我更改的值旁边,新XML中的一些行丢失了,而在一些行中,标记名称已经更改 为什么会这样?除了我所做的更改外,是否有其他方法使文件保持原样?我应该使用其

我有一个格式化为XML的ISM文件(InstallShield项目)

我需要更改文件中的一些属性,所以我使用了xml.etree.ElementTree(Python库)

我可以找到这些值并对其进行更改,但是,在使用更新的值保存文件后,我无法在InstallShield中打开它(我遇到一个常规错误,文件无法打开)

当我比较新文件和旧文件时,我发现在我更改的值旁边,新XML中的一些行丢失了,而在一些行中,标记名称已经更改

为什么会这样?除了我所做的更改外,是否有其他方法使文件保持原样?我应该使用其他工具进行更改吗

例如,以下部分以原始XML显示:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="is.xsl" ?>
<!DOCTYPE msi [
   <!ELEMENT msi   (summary,table*)>
   <!ATTLIST msi version    CDATA #REQUIRED>
   <!ATTLIST msi xmlns:dt   CDATA #IMPLIED
                 codepage   CDATA #IMPLIED
                 compression (MSZIP|LZX|none) "LZX">

   <!ELEMENT summary       (codepage?,title?,subject?,author?,keywords?,comments?,
                            template,lastauthor?,revnumber,lastprinted?,
                            createdtm?,lastsavedtm?,pagecount,wordcount,
                            charcount?,appname?,security?)>

   <!ELEMENT codepage      (#PCDATA)>
   <!ELEMENT title         (#PCDATA)>
   <!ELEMENT subject       (#PCDATA)>
   <!ELEMENT author        (#PCDATA)>
   <!ELEMENT keywords      (#PCDATA)>
   <!ELEMENT comments      (#PCDATA)>
   <!ELEMENT template      (#PCDATA)>
   <!ELEMENT lastauthor    (#PCDATA)>
   <!ELEMENT revnumber     (#PCDATA)>
   <!ELEMENT lastprinted   (#PCDATA)>
   <!ELEMENT createdtm     (#PCDATA)>
   <!ELEMENT lastsavedtm   (#PCDATA)>
   <!ELEMENT pagecount     (#PCDATA)>
   <!ELEMENT wordcount     (#PCDATA)>
   <!ELEMENT charcount     (#PCDATA)>
   <!ELEMENT appname       (#PCDATA)>
   <!ELEMENT security      (#PCDATA)>                            

   <!ELEMENT table         (col+,row*)>
   <!ATTLIST table
                name        CDATA #REQUIRED>

   <!ELEMENT col           (#PCDATA)>
   <!ATTLIST col
                 key       (yes|no) #IMPLIED
                 def       CDATA #IMPLIED>

   <!ELEMENT row            (td+)>

   <!ELEMENT td             (#PCDATA)>
   <!ATTLIST td
                 href       CDATA #IMPLIED
                 dt:dt     (string|bin.base64) #IMPLIED
                 md5        CDATA #IMPLIED>
]>
<msi version="2.0" xmlns:dt="urn:schemas-microsoft-com:datatypes" codepage="65001">

谢谢大家!

最后我搬到了一个新的库——lxml。 这个库与
xml.etree.ElementTree
相反,它保持了所有标记的顺序,因此我做了完全相同的事情,它起了作用:

def modify_ism_file(ism_file_path):
    context = etree.iterparse(ism_file_path)
    for action, attributes_group in context:
        for attribute in attributes_group:
            if attribute.tag == "revnumber":
                print "Found package code. TAG = {0} TEXT = {1}".format(attribute.tag, attribute.text)
                new_package_code = increment_hex_number(attribute.text)
                print "New package code is {0}".format(new_package_code)
                attribute.text = new_package_code

obj_xml = etree.tostring(context.root, pretty_print=True, xml_declaration=True,   encoding="utf-8")

    with open(ism_file_path, "w") as f:
        f.write(obj_xml)

首先,我想指出InstallShield有一个默认的编译器设置,即每次构建MSI时生成一个新的包代码。这是一个最佳实践,所以我真的不明白为什么在这种情况下需要编辑ISM

我要指出的第二件事是,ISM的原始DTD XML格式很难使用。我倾向于在大多数动态创作中使用COM automation inferface,然后以二进制格式保存项目,这样我就可以像使用ORCa一样将其编辑为关系数据库。WiX C#/DTF自定义操作具有LINQ支持,这使得操作更加容易。您甚至可以编写一个C#helper类,并从python中调用它。然后,您可以在自动化界面中打开它,并在需要时以XML格式将其保存回去

   tree = Et.parse(ism_file_path)
    root = tree.getroot()

    for attributes_group in root:
        for attribute in attributes_group:

            if attribute.tag == "revnumber":

                new_package_code = increment_hex_number(attribute.text)

                attribute.text = new_package_code

tree.write(ism_file_path)
def modify_ism_file(ism_file_path):
    context = etree.iterparse(ism_file_path)
    for action, attributes_group in context:
        for attribute in attributes_group:
            if attribute.tag == "revnumber":
                print "Found package code. TAG = {0} TEXT = {1}".format(attribute.tag, attribute.text)
                new_package_code = increment_hex_number(attribute.text)
                print "New package code is {0}".format(new_package_code)
                attribute.text = new_package_code

obj_xml = etree.tostring(context.root, pretty_print=True, xml_declaration=True,   encoding="utf-8")

    with open(ism_file_path, "w") as f:
        f.write(obj_xml)