使用Python属性获取XML树中所有节点的xpath

2024-05-14 18:23:57 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有以下test.xml:

<?xml version="1.0" encoding="UTF-8"?>
<test:myXML xmlns:test="http://com/my/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Parent>
  <FirstNode name="FirstNodeName"></FirstNode>
    <Child1>Test from Child1</Child1>
  <SecondNode name="SecondNodeName" type="SecondNodeType">
    <Child2>
      <GrandChild>Test from GrandChild</GrandChild>
    </Child2>
  </SecondNode>
</Parent>
</test:myXML>

我希望遍历整个树,并获得每个节点的路径,包括属性。我能够在树上迭代并检索到每个节点的路径,如下所示:

from lxml import etree

xmlDoc = etree.parse("test.xml")
root = xmlDoc.getroot()

for node in xmlDoc.iter():
    print("path: ", xmlDoc.getpath(node))

正如预期的那样,这将打印出:

path:  /test:myXML
path:  /test:myXML/Parent
path:  /test:myXML/Parent/FirstNode
path:  /test:myXML/Parent/Child1
path:  /test:myXML/Parent/SecondNode
path:  /test:myXML/Parent/SecondNode/Child2
path:  /test:myXML/Parent/SecondNode/Child2/GrandChild

但是,正如我所提到的,我想以某种方式打印所述节点及其父节点的属性及其路径。例如,如果我想打印元素“Child2”,那么我想显示它的每个父元素的属性。比如:

path:  /test:myXML/Parent/SecondNode{name="SecondNodeName" type="SecondNodeType"}/Child2

这可能吗?我对根元素的名称空间不太在意,如果这使它更简单的话


Tags: pathnamefromtest路径节点xmlparent
1条回答
网友
1楼 · 发布于 2024-05-14 18:23:57

我不知道有什么预先包装好的方法可以做到这一点,但随着所有强制的“在家工作”的进行,我想我还是试着想出一些办法。这很不雅观,但似乎很管用

在您的实际代码上尝试此方法,看看是否有效:

att = """
<test:myXML xmlns:test="http://com/my/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Parent>
  <FirstNode name="FirstNodeName"></FirstNode>
    <Child1>Test from Child1</Child1>
  <SecondNode name="SecondNodeName" type="SecondNodeType">
    <Child2>
      <GrandChild>Test from GrandChild</GrandChild>
    </Child2>
  </SecondNode>
</Parent>
</test:myXML>
"""

from lxml import etree

bef = []
xps = []

xmlDoc = etree.fromstring(att)
root = etree.ElementTree(xmlDoc)

for node in xmlDoc.iter():        
    ats = "{"
    for a in range(len(node.keys())):
        mystr = node.keys()[a]+'="'+node.values()[a]+'" '
        ats +=mystr
    ats+='}'
    xp = root.getpath(node)    
    bef.append(xp)
    ent = ''
    if len(ats)>2:
        ent+=xp
        ent+=ats.replace(' }','}')        
    else:
        ent+=xp
    xps.append(ent)

for b,  f in zip(bef,xps):
    prev = bef.index(b)-1
    if prev >=0:
        cur = b.rsplit("/",1)[0]
        new_cur = f.rsplit("/",1)[1]
        if bef[prev]==cur:
            new_f = xps[prev]+'/'+new_cur
            xps[prev+1]=new_f
            print(new_f)
        else:
            print(f)  

输出:

/test:myXML/Parent
/test:myXML/Parent/FirstNode{name="FirstNodeName"}
/test:myXML/Parent/Child1
/test:myXML/Parent/SecondNode{name="SecondNodeName" type="SecondNodeType"}
/test:myXML/Parent/SecondNode{name="SecondNodeName" type="SecondNodeType"}/Child2
/test:myXML/Parent/SecondNode{name="SecondNodeName" type="SecondNodeType"}/Child2/GrandChild

如果它有效并且你感兴趣,我可以试着解释这一切的作用

相关问题 更多 >

    热门问题