【问题标题】:Python: xml.etree.ElementTree destroys xml formatPython:xml.etree.ElementTree 破坏 xml 格式
【发布时间】:2017-12-19 14:09:21
【问题描述】:

我有一个格式为 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">

但是在新的 XML 中它已经消失了,而是只有:

<msi xmlns:ns0="urn:schemas-microsoft-com:datatypes" codepage="65001" version="2.0">

还有更多的不同,这只是一个例子。

我用来进行更改的python代码是

   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)

谢谢!

【问题讨论】:

    标签: python xml python-2.7 installshield


    【解决方案1】:

    最终我搬到了一个新的库——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)
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 2023-03-28
        • 2012-06-12
        • 1970-01-01
        • 2011-10-16
        • 1970-01-01
        • 2011-03-09
        • 2021-10-29
        • 1970-01-01
        • 2015-02-17
        相关资源
        最近更新 更多