提问人:upkar 提问时间:10/20/2023 更新时间:10/20/2023 访问量:34
Python elementree 可以获取大父属性值
Python elementree possible to get grand parent attribute value
问:
我有如下内容的xml文件。如果 XML 的属性作业与值“al”匹配,并且 run 将值匹配为“jps”,则要从 XML 中提取用户类别下的 name 值。尝试使用 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
但是,使用 ,您仍然拥有 XPath 本身的强大功能,或者至少是其中的有限子集,这确实允许您执行所需的操作。xml
从所选节点中,一旦验证给定节点具有所需的属性值,就可以返回到其祖父节点 (),方法是使用轴(有点像描述树节点关系的运算符)在层次结构中向上移动的次数。job
user
job
..
但是,由于您在验证孙子后在 XPath 中执行导航,因此这意味着您还需要在 XPath 中执行验证。XPath 为此提供了谓词,表达式括在方括号中:[
]
".//user/jobs/job[@run='jps'][@kind='al']"
上面的表达式表示“所有节点,其父节点是节点,其父节点是可以位于文档中任何位置的节点,所述节点具有以 value 等于 string 命名的属性,以及具有字符串值的属性。job
jobs
user
job
run
jps
kind
al
从这一点开始,您可以使用父轴速记两次来返回到祖父轴:user
".//user/jobs/job[@run='jps'][@kind='al']/../.."
由于您在 XPath 查询中执行了所有必要的步骤,因此当您回到 Python 的世界时,您甚至不需要费心编写语句。if
编辑:请注意,与你的-testing方法相比,如果发现一个对象确实具有a或a属性,或者同时具有这两个属性,但具有与预期值不同的对象,XPath方法将简单地静默地忽略它们,而你的dict成员访问运算符将抛出一个错误(可能)。if
user/jobs/job
run
kind
KeyError
评论