将 xml 值替换为 python
replace xml values with python
我已经尝试了 2 种方法来替换 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 文档,找到所有 ActnCode 节点并将值更改为 "CAN"。任何帮助将不胜感激。
你有几个问题。您要查找的元素具有从 <OrdSet xmlns="..."
中的默认命名空间继承的命名空间,并且需要包含在查找中。然后,findall
只查看子项,除非您添加 ElementTree 的 "pseudo-xsl" 子树搜索模式。最后,您需要更改 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")
编辑
与 ElementTree
相比,lxml
可以执行更复杂的 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")
我已经尝试了 2 种方法来替换 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 文档,找到所有 ActnCode 节点并将值更改为 "CAN"。任何帮助将不胜感激。
你有几个问题。您要查找的元素具有从 <OrdSet xmlns="..."
中的默认命名空间继承的命名空间,并且需要包含在查找中。然后,findall
只查看子项,除非您添加 ElementTree 的 "pseudo-xsl" 子树搜索模式。最后,您需要更改 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")
编辑
与 ElementTree
相比,lxml
可以执行更复杂的 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")