2016-03-29 22 views
0

xmlファイル内の指定されたノード内の値を置き換える2つの方法を試しましたが、機能しません。xml値をPythonに置き換えます

マイファイル:

<?xml version="1.0" encoding="UTF-8"?> 
 
<OrdSet xmlns="tfs" xmlns:xsi="http://www.sample.org/XMLSchema-instance" xsi:schemaLocation="tfs tfs.xsd" Version="25"> 
 
    <Msg> 
 
     <MsgCreate> 
 
      <Date>20160324</Date> 
 
      <Time>111057</Time> 
 
      <Src> 
 
       <SrcType>D</SrcType> 
 
       <DlrCode>0001</DlrCode> 
 
      </Src> 
 
      <Target> 
 
       <TargetType>F</TargetType> 
 
       <MgmtCode>BTG</MgmtCode> 
 
      </Target> 
 
     </MsgCreate> 
 
     <MsgType> 
 
      <OrdReq> 
 
       <ActnCode>NEW</ActnCode> 
 
       <SrcID>64698602107101</SrcID> 
 
       <RepCode>0000</RepCode> 
 
       <OrdDtl> 
 
        <AcctLookup> 
 
         <MgmtCode>ABC</MgmtCode> 
 
         <FundAcctID>984575</FundAcctID> 
 
         <AcctDesig>2</AcctDesig> 
 
        </AcctLookup> 
 
        <TrxnDtl> 
 
         <Buy> 
 
          <TrxnTyp>5</TrxnTyp> 
 
          <FundID>205</FundID> 
 
          <Amt> 
 
           <AmtType>D</AmtType> 
 
           <AmtValue>600.00</AmtValue> 
 
          </Amt> 
 
         </Buy> 
 
        </TrxnDtl> 
 
       </OrdDtl> 
 
      </OrdReq> 
 
     </MsgType> 
 
    </Msg> 
 
omitted ...

私の目標は、NEWからCANにActnCode値を交換することです。

I.e., <ActnCode>CAN</ActnCode>

試み#1:スクリプトは正常に動作しますが、値が出力ファイルにはまだ "NEW" です。何も変更されていないようです。

import xml.etree.ElementTree as ET 
 
tree = ET.parse("~\input.xml") 
 
root = tree.getroot() 
 
elems = tree.findall('ActnCode') 
 
for elem in elems: 
 
\t elem.txt = 'CAN' 
 
tree.write("~\output.xml")

試み#2:スクリプトは、同様に正常に動作しますが、意図したとおり、それは働いていません。

xmldoc = minidom.parse('~input.xml') 
 
action_code = xmldoc.getElementsByTagName('ActnCode') 
 
firstchild = action_code[0] 
 
firstchild.setAttribute('ActnCode', 'CAN') 
 

 
result: 
 
<ActnCode ActnCode="CAN">NEW</ActnCode>

最終的に、私はPythonは、XMLドキュメントに目を通すすべてActnCodeノードを見つけて、 "CAN" に値を変更したいです。どんな助けもありがとう。

+0

の兄弟を持つノードに制限これは、XSLTで簡単です。 etreeの代わりに*** lxml ***を使ってXSLT変換を実行できますか? –

答えて

0

いくつかの問題があります。あなたが探している要素には、デフォルトの名前空間から継承した名前空間が<OrdSet xmlns="..."にあり、それを検索に含める必要があります。 ElementTreeの "pseudo-xsl"サブツリー検索パターンを追加しない限り、findallは子のみを参照します。最後に、 `txtではなくtext属性を変更する必要があります。テストのためのXMLを省略

...

<?xml version="1.0" encoding="UTF-8"?> 
<OrdSet xmlns="tfs"> 
    <Msg> 
     <MsgCreate> 
      <ActnCode>NEW</ActnCode> 
      <SrcID>64698602107101</SrcID> 
      <RepCode>0000</RepCode> 
      <OrdDtl> 
       <AcctLookup> 
        <MgmtCode>ABC</MgmtCode> 
        <FundAcctID>984575</FundAcctID> 
        <AcctDesig>2</AcctDesig> 
       </AcctLookup> 
      </OrdDtl> 
     </MsgCreate> 
    </Msg> 
</OrdSet> 

そして、あなたのコードは、あなたがElementTreeよりもlxmlでより複雑なXPathクエリを行うことができます

import xml.etree.ElementTree as ET 
tree = ET.parse("input.xml") 
root = tree.getroot() 
elems = tree.findall('.//{http://abc}ActnCode') 
print('elems', elems) 
for elem in elems: 
    elem.text = 'CAN' 
tree.write("output.xml") 

EDIT

になります。どの<ActnCode>要素を処理するかを制限したい場合、この述部は他の要素を調べて選択範囲を絞り込みます。山括弧の中の要素は、本質的に、一致しないノードを削除するフィルタです。ここで私はOrdDtl/AcctLookup/FundAcctID 984575

import lxml.etree 
tree = lxml.etree.parse('input.xml') 
elems = tree.xpath('//tfs:ActnCode[../tfs:OrdDtl/tfs:AcctLookup/tfs:FundAcctID/text()="984575"]', 
    namespaces={'tfs':'tfs'}) 
elems2 = tree.xpath('.//tfs:ActnCode[../tfs:OrdDtl]', 
    namespaces={'tfs':'tfs'}) 
print('elems', elems) 
for elem in elems: 
    elem.text = 'CAN' 
tree.write("output.xml") 
+0

それは完全に動作します。ありがとう! – spiderlily

+0

私は別の問題にぶつかります。 FundAcctIDが984575の場合にのみActnCodeを「CAN」に変更するようにコードを変更するにはどうすればよいですか? – spiderlily

+0

検索式に述語を追加することはできますが、 'ElemenTree'述語のサポートは制限されています。 'lxml'述語とXPATH述語を使用する別の例を提供します。 – tdelaney

関連する問題