我有 xml 文件,其内容如下。如果其属性作业与值“al”匹配并且运行与值“jps”匹配,则希望从 XML 中提取用户类别下的名称值。尝试使用 elementree 提取值但无法。不确定尝试的方法是否正确。
<maruti>
<usrDirectory>/usr</usrDirectory>
<shareDirectory>/share</shareDirectory>
<jobLogDirectory>/logs</jobLogDirectory>
<clients>
<client>nexa-asia</client>
</clients>
<imax>
<uri>imaxs://imax-asia.fb.bda.com:123</uri>
<rootDn>o=lbr</rootDn>
<pend>ou=nexa-asia,ou=clients,o=lbr</pend>
<password>password</password>
</imax>
<enabling-aling-tags>
<tag>alingDisabled</tag>
</enabling-aling-tags>
<maxh>999</maxh>
<defaults>
<default type="slone">
<user>pot</user>
<exec>/usr/local/smarts/utils/runals.sh</exec>
<env>
<var name="ALARM">/taj/63123.lbr/ALARM</var>
<var name="TODAY">/taj/63123.lbr/TODAY</var>
<var name="jps_HOME">/usr/juju</var>
</env>
</default>
<default type="slanamb">
<user>pot</user>
<exec>/usr/local/smarts/utils/runals.sh</exec>
<env>
<var name="ALARM">/taj/63123.lbr/ALARM</var>
<var name="TODAY">/taj/63123.lbr/TODAY</var>
<var name="jps_HOME">/usr/juju</var>
</env>
</default>
<default type="slaljps">
<user>pot</user>
<exec>/use-ALARM/runmrts.sh</exec>
<env>
<var name="jps_HOME">/usr/juju</var>
</env>
</default>
<default type="slanjps">
<user>pot</user>
<exec>/use-ALARM/runmrts.sh</exec>
<env>
<var name="jps_HOME">/usr/juju</var>
</env>
</default>
<default type="cmj">
<user>pot</user>
<exec>/use-ALARM/runmrts.sh</exec>
<env>
<var name="jps_HOME">/usr/juju</var>
</env>
</default>
<default type="cbj">
<user>pot</user>
<exec>/use-ALARM/runmrts.sh</exec>
<env>
<var name="jps_HOME">/usr/juju</var>
</env>
</default>
<default type="slm">
<user>favactor</user>
<exec>/usr/local/actdrive/actdrive</exec>
<args>
<arg name="config">/usr01/lbr/conf/lbr-naming.properties</arg>
</args>
</default>
<default type="tata">
<user>pot</user>
<exec>/use-ALARM/tataals.sh</exec>
<env>
<var name="jps_HOME">/usr/juju</var>
</env>
</default>
</defaults>
<groups>
<user name="nexa_sit" annvday="20221003" make="one">
<jobs>
<job kind="al" run="jps">
<args>
<arg name="level">5000</arg>
</args>
</job>
<job kind="vm" run="jps">
<args>
<arg name="level">5000</arg>
</args>
</job>
</jobs>
</user>
<user name="nexa_tsx" annvday="20230714" make="two">
<jobs>
<job kind="al" run="jps">
<args>
<arg name="level">5000</arg>
</args>
</job>
<job kind="vm" run="jps">
<args>
<arg name="level">5000</arg>
</args>
</job>
</jobs>
</user>
<user name="nexatwo_bvk" annvday="20221003" make="one">
<jobs>
<job kind="al" run="jps">
<args>
<arg name="level">5000</arg>
</args>
</job>
<job kind="vm" run="jps">
<args>
<arg name="level">5000</arg>
</args>
</job>
</jobs>
</user>
<user name="nexaone_bvk" annvday="20221003" make="one">
<jobs>
<job kind="al" run="ips">
<args>
<arg name="level">5000</arg>
</args>
</job>
<job kind="vm" run="ips">
<args>
<arg name="level">5000</arg>
</args>
</job>
</jobs>
</user>
</groups>
</maruti>
但后来从错误中意识到不支持 getparent 。不知道如何提取。
尝试过代码
import xml.etree.ElementTree as ET
tree = ET.parse('text.xml')
root = tree.getroot()
for sub in root.findall(".//user/jobs/job"):
if (sub.attrib["run"] == 'java' and sub.attrib["kind"] == 'al'):
print sub.getparent()
预期产量
nexa_set
nexa_tfex
nexatwo_set
不幸的是,由于这是来自 Python 标准库的
xml
包,因此您获得的接口相当有限,并且无法访问方便的导航功能,例如 .getparent()
方法。
一种选择是使用
lxml
而不是 xml
,虽然它不包含在标准库中,但确实具有更高级的功能,包括以面向对象的方式导航节点树的方法。
但是,使用
xml
,您仍然拥有 XPath 本身的强大功能,或者至少拥有 其有限子集,这确实允许您执行所需的操作。
从选定的
job
节点,一旦您使用 user
轴验证给定的 job
具有所需的属性值(类似于描述树节点关系),您想在层次结构中向上移动多少次都可以。但是,由于您在验证孙子之后之后在 XPath 中执行导航,因此意味着您也需要在 XPath 中执行验证。 XPath 为此提供了谓词,将表达式括在方括号中 ..
`]:
[
上面的表达式的意思是“所有 ".//user/jobs/job[@run='jps'][@kind='al']"
节点,其父节点是 job
节点,其父节点是可以位于文档中任何位置的
jobs
节点,并且所述
user
节点具有名为
job
的属性,并且值等于字符串
run
,并且属性
jps
具有字符串值
kind
。
从这一点开始,您可以使用父轴简写两次来返回祖父母,
al
:
user
由于您在 XPath 查询中执行了所有必要的步骤,因此当您回到 Python 世界时,甚至不需要编写 ".//user/jobs/job[@run='jps'][@kind='al']/../.."
语句。