用python

时间:2016-03-29 19:48:34

标签: python xml elementtree minidom

我已经尝试了两种方法来替换xml文件中给定节点内的值,但它无效。

我的档案:

<?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 ...

我的目标是将ActnCode值从NEW替换为CAN。

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:
	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 doc,找到所有ActnCode节点并将值更改为“CAN”。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

你有几个问题。您要查找的元素具有从<OrdSet xmlns="..."中的默认命名空间继承的命名空间,并且需要包含在查找中。然后,findall只会查看子项,除非您添加了ElementTree&#34; pseudo-xsl&#34;子树搜索模式。最后,您需要更改text属性,而不是`txt。

用于测试的缩写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>

您的代码变为

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")

修改

您可以使用lxml而不是使用ElementTree执行更复杂的XPATH查询。如果要限制处理的<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")