2017-12-19 30 views
1

XMLとしてフォーマットされたISMファイル(InstallShieldプロジェクト)を持っています。Python:xml.etree.ElementTreeがXMLフォーマットを破棄します

ファイルの属性を変更する必要があるため、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) 

ありがとうです!

答えて

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) 
+1

自己回答はSOに適しています。ありがとう。 – msw

0

まず、私はInstallShieldが生成するデフォルトのコンパイラの設定を持っていることを指摘したいと思いますMSIを構築するたびに新しいPackageCodeこれはベストプラクティスなので、なぜこのシナリオでISMを編集する必要があるのか​​わかりません。

私が指摘しておきたいのは、ISMのRAW DTD XMLフォーマットが非常に難しいことです。私は、大部分の動的オーサリングにCOMオートメーションインフェイスフェースを使用し、バイナリ形式でプロジェクトを保存する傾向があるので、ORCaを使用するのと同じようにリレーショナルデータベースとして編集できます。 WiX C#/ DTFのカスタムアクションにはLINQサポートが組み込まれているので、これをはるかに簡単に行うことができます。 C#ヘルパークラスを作成してPythonから呼び出すこともできます。オートメーションインターフェースでそれを開き、必要に応じてXML形式で保存することができます。

関連する問題