Python 使用ElementTree时,lxml(findall的唯一(.//)通配符)不能使用相对路径?

Python 使用ElementTree时,lxml(findall的唯一(.//)通配符)不能使用相对路径?,python,xml,xpath,lxml,elementtree,Python,Xml,Xpath,Lxml,Elementtree,我有一个高度嵌套的长xml文件,需要对其进行解析并将其放入数据框架中 这是我的XML: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE PPP SYSTEM 'PPP.DTD'> <book chg="R" model="AB" > <chapter chapnbr="09" chg="

我有一个高度嵌套的长xml文件,需要对其进行解析并将其放入数据框架中

这是我的XML:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE PPP
  SYSTEM 'PPP.DTD'>
<book chg="R" model="AB" >
    <chapter chapnbr="09" chg="U" key="EN49" >
        <effect effrg="Afcd"/>
        <title>HOW TO WIN</title>
        <section chapnbr="09" chg="U" key="Edff" revdate="20100701" sectnbr="102">
            <title>What a start</title>
            <subject chapnbr="09" chg="U" key="Edff" revdate="20100701" sectnbr="102" subjnbr="00">
                <title>1.A</title>
                <pgblk chapnbr="09" chg="U" confnbr="00" key="Edff00" pgblknbr="00" revdate="20200701" sectnbr="102" subjnbr="00">
                    <effect effrg="12"/>
                    <title>1.A.i) Plan Ahead for the worst</title>
                    <prclist1>
                        <prcitem1 adns-numbering="8" adns-title="learning my way with help of good people" >
                            <effect effrg="Edff"/>
                            <prcitem asFragment="true">
                                <title>1.A.i) Plan Ahead for the worst</title>
                                <para>It was a cold January night, and I had too much whisky. 
                                    <refblock>
                                        09-102-00
                                        <refint rrr="22,445,555,555,555" refid="Edff0898">
                                            <effect effrg="Edff0899"/>
                                            0910200</refint>
                                    </refblock>. </para>
                                <para>In more usual circumstances, I possesed the self-control. Not this time 
                                    <refblock>
                                        09-102-00-1111
                                        <refint rrr="sdf,2323,2323" refid="Edff123">
                                            <effect effrg="Edff12434"/>
                                            09-102-00</refint>
                                    </refblock>. </para>
                            </prcitem>
                        </prcitem1>
                    </prclist1>
                </pgblk>
            </subject>
        </section>
    </chapter>
</book>

我还能够获得每个元素的绝对路径:


for e in root.iter():
    print(tree.getpath(e))

这给出了(下面是一个示例,我的实际xml更嵌套,输出的路径是下面路径的3倍):

然后,我需要从xml的特定区域提取标记和文本

但是,如果尝试使用绝对路径或相对路径,字典输出
d
,将保持为空

d={}

for item in root.findall('./section/title'): 
    d[item.tag] = item.text

同样适用于

findall('.//section/title')
再一次,空口述为

findall('/book/chapter/section/title')
唯一有效的xpath是:

findall('.//')
findall()
不接受绝对路径名。您需要相对路径名

。//section/title'
确实有效,但它返回
title
标记。因此,无论有多少匹配项,您的dict中都会有一个名为
title
的单键,why可能不是您想要的

如果要使用标题作为章节索引,可以执行以下操作:

d = dict((item.text, item.getparent()) for item in root.findall('.//section/title'))
从示例XML中,这将创建一个dict,key
What a start
和chapter元素作为值

如果您想使用XPath表达式的全部功能,我建议您使用
xpatheevaluator

from lxml import etree

tree = etree.parse('file.xml')

xev = etree.XPathEvaluator(tree)

d = dict((item.text, item.getparent()) for item in xev('/book/chapter/section/title'))

for k, v in d.items():
    print(f"{k} -> {v.tag}")
输出:

What a start -> section

您可能希望将xml文件的一部分显示为示例。您正在使用xml名称空间吗?(1)您必须包含xml才能获得最佳帮助。(2) “绝对”和“相对”这两个术语的使用被禁用:
/
/
都是相对的<代码>/和
/
都是绝对值。@AdrianW不使用namespaces@kjhughes谢谢你指出这一点。我现在还包括了我的xml示例。
/book/chapter/section/title
//title
都应该使用
findall()
来选择
title
元素。尽管您提交了报告,
//section/title
似乎也应该至少找到一个
title
。再次检查?非常感谢。这很有帮助。我仍然不清楚如何通过指定('/a/b/c/d/e')来获得一个“曾孙”元素,而不必通过每一个级别进行下一步操作?我还没有设法使用XPathEvaluator和'/'进入一个特定的节点,而是设法使用不同的源xml文件进行复制。我现在遇到的麻烦是遍历一个包含xml文件的文件夹。由于某种原因,没有找到任何文件。这似乎是两个截然不同的问题。首先,看一看XPath,了解更多有关XPath功能的信息。您可以从任何元素创建一个新的XPathEvaluator作为新的起点,并从那里导航。有轴说明符,如
后代或self::
。所以,真的有很多可能性。不清楚你到底有什么问题。简单地迭代子对象也可能是一个解决方案,这取决于您想要做什么。可能会为此提出一个新问题。第二,这在
os.walk()
中应该是可行的。谢谢。我问了一个新问题
from lxml import etree

tree = etree.parse('file.xml')

xev = etree.XPathEvaluator(tree)

d = dict((item.text, item.getparent()) for item in xev('/book/chapter/section/title'))

for k, v in d.items():
    print(f"{k} -> {v.tag}")
What a start -> section