2

入力 xml ファイル:

<?xml version="1.0"?>
<res:testcases xmlns:res="urn:testcases" id="a1e4bfdb-40a2-485c-a1ac-54d220056dd5" type="MODEL">
  <mode>PRESSURE_CONTROL</mode>
  <category>ADULT</category>
  <testcase id="1" type="UNIQUE">
    <parameter id="PEEP" value="1.0">true</parameter>
    <parameter id="CMV_FREQ" value="4.0">true</parameter>
    <parameter id="PRESS_ABOVE_PEEP" value="0.0">true</parameter>
    <parameter id="I_E_RATIO" value="0.1">false</parameter>
  </testcase>
</res:testcases>

Python コード:

import xml.etree.ElementTree as ET

tree = ET.parse('/home/AlAhAb65/Desktop/input.xml')    
root = tree.getroot() 

root.attrib['type'] = 'AVA'

tree.write('/home/AlAhAb65/Desktop/output1.xml')

出力 xml ファイル:

<ns0:testcases id="a1e4bfdb-40a2-485c-a1ac-54d220056dd5" type="AVA" xmlns:ns0="urn:testcases">
  <mode>PRESSURE_CONTROL</mode>
  <category>ADULT</category>
  <testcase id="1" type="UNIQUE">
    <parameter id="PEEP" value="1.0">true</parameter>
    <parameter id="CMV_FREQ" value="4.0">true</parameter>
    <parameter id="PRESS_ABOVE_PEEP" value="0.0">true</parameter>
    <parameter id="I_E_RATIO" value="0.1">false</parameter>
  </testcase>
</ns0:testcases>

問題は、出力 xml ファイルをコピーして書き込んでいるときに、予期しないことが 3 回発生することです。1. 入力 xml ファイルの最初の行は自動的に削除されます。 2. 2 行目 (入力) では、テキスト 'res' が 'ns0' に置き換えられます。タグを閉じている間も同じことが起こります 3. (入力の 2 行目の) 属性の順序が変更されます。しかし、入力として取得したxmlファイルの正確なコピーを(出力として)書きたいと思います。この点で私を助けてください。

4

2 に答える 2

5

W3 はCanonical XML 標準を定義しました。この形式で記述されたドキュメントは、C14N 準拠のツールチェーンによって忠実に往復できます。

lxml.etree (C14N をサポートする ElementTree API のより機能的な実装)の場合、これは次の 2 つのことを行う必要があることを意味します。

  • 元の入力文書を C14N 形式に変換します。
  • 呼び出しを使用してElementTree.write_c14n()、出力ドキュメントを生成します。

入力ファイルの C14N 形式バージョンは次のようになります (xmlstarlet c14nコマンドによって生成されます)。

<res:testcases xmlns:res="urn:testcases" id="a1e4bfdb-40a2-485c-a1ac-54d220056dd5" type="MODEL">
  <mode>PRESSURE_CONTROL</mode>
  <category>ADULT</category>
  <testcase id="1" type="UNIQUE">
    <parameter id="PEEP" value="1.0">true</parameter>
    <parameter id="CMV_FREQ" value="4.0">true</parameter>
    <parameter id="PRESS_ABOVE_PEEP" value="0.0">true</parameter>
    <parameter id="I_E_RATIO" value="0.1">false</parameter>
  </testcase>
</res:testcases>

...そして、適切に修正されたバージョンのコード:

#!/usr/bin/env python

import lxml.etree

tree = lxml.etree.parse('input.xml')    
root = tree.getroot() 

root.attrib['type'] = 'AVA'

tree.write_c14n('output1.xml')

XML 宣言 (<?xml version="1.0"?>行)を追加すると、C14N 規格に準拠しなくなります。ですから、これは絶対にやってはいけないことです。あなたが本当に、本当にこの頭の悪いことをしたいのなら...

  • しないでください。
  • しかし、そうしなければならない場合は、次のようにします。

    outfile = open('output1.xml', 'w')
    outfile.write('<?xml version="1.0"?>\n')
    tree.write_c14n(outfile)
    outfile.close()
    
于 2013-07-26T15:16:45.443 に答える
2

ドキュメント ページから、XML 宣言を次のように追加できます。

tree.write('/home/AlAhAb65/Desktop/output1.xml', xml_declaration=True)

デフォルトは us-ascii であるため、エンコーディングも追加する必要があります。

tree.write('/home/AlAhAb65/Desktop/output1.xml', encoding='utf-8', xml_declaration=True)

または、元のファイルからエンコーディングを取得することもできますが、いずれにしても、おそらく次のような異なる XML 宣言が得られます。

<?xml version="1.0" encoding="UTF-8"?>

または、XML 宣言を手動で追加することもできます。いずれにせよ、宣言されたエンコーディングが実際のエンコーディングと一致している限り、わずかな宣言の不一致は堅牢な XML パーサーにとって問題にはなりません。


XML では属性の順序は重要ではないため、ファイルが API 内で解析されるときに情報が失われる可能性があります。標準の ElementTree API を介してファイルを処理する場合、おそらくこれを機能させる簡単な方法はありません。ファイルに小さな変更を加えたい場合は、おそらくlxml C14Nサポートを使用する必要があります。


名前空間のプレフィックスは、ElementTree でデフォルトで変更されます。この動作を防ぐには、デフォルトで名前空間プレフィックスを保持しているように見えるlxmlに切り替えることができます。

etree は名前空間プレフィックスを認識する libxml2 の上に構築されているため、etree は名前空間の宣言とプレフィックスを保持しますが、ElementTree は独自のプレフィックス (ns0、ns1 など) を使用する傾向があります。ただし、名前空間プレフィックスが指定されていない場合、etree は ElementTree スタイルのプレフィックスも作成します。

いずれにせよ、lxml に切り替えることは良い考えですが、反対側でファイルを読み取るプログラムが十分に XML に準拠している場合、観察された変更は問題になりません。残念ながら、多くの XPath プロセッサには名前空間プレフィックスの変更に関する問題があります...

于 2013-07-26T15:42:36.460 に答える