Python elementree 可以获取祖父属性值

问题描述 投票:0回答:1

我有 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 elementtree
1个回答
0
投票

不幸的是,由于这是来自 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']/../.."
语句。

© www.soinside.com 2019 - 2024. All rights reserved.