Python 我可以取消对lxml.etree.AncestorsIterator的引用吗?
我使用lxml来操作一个用xml文件表示的dbschema。它看起来像这样:Python 我可以取消对lxml.etree.AncestorsIterator的引用吗?,python,lxml,Python,Lxml,我使用lxml来操作一个用xml文件表示的dbschema。它看起来像这样: <Tables> <Table name = "table1"> <Columns> <Column name="COL1">...</Column> <Column name="COL2">... <References> <Reference>TABLENAME</Reference>
<Tables>
<Table name = "table1">
<Columns>
<Column name="COL1">...</Column>
<Column name="COL2">...
<References>
<Reference>TABLENAME</Reference>
</References>
</Column>
</Table>
...
</Tables>
我不喜欢这个解决方案,因为我知道我的namiter只能迭代单个元素——它只有一个父“表”。在python中,我似乎只能在循环中使用迭代器。但我觉得这有点傻。我知道我只有一个祖先“表”。我可以直接取消对迭代器的引用吗?或者有没有其他更合适的方法来获取此信息?您可以使用xpath来获取所需的两个祖先
x = """<?xml version="1.0" encoding="utf-8"?>
<Tables>
<Table name = "table1">
<Columns>
<Column name="COL1">...</Column>
<Column name="COL2">...
<References>
<Reference>TABLENAME</Reference>
</References>
</Column>
</Columns>
</Table>
<Table name = "table2">
<Columns>
<Column name="COL2">...</Column>
<Column name="COL3">...
<References>
<Reference>TABLENAME</Reference>
</References>
</Column>
</Columns>
</Table>
</Tables>"""
import lxml.etree as et
xml = et.fromstring(x)
refs = xml.iter("Reference")
print([(ref.xpath("./ancestor::Table/@name")[0], ref.xpath("./ancestor::Column/@name")[0]) for ref in refs])
或者,如果列始终是祖父母:
[(ref.xpath("./ancestor::Table/@name")[0], ref.xpath("./../../@name")[0]) for ref in refs]
使用您自己的逻辑,您可以在iTranceTors上调用next:
refs = xml.iter("Reference")
for r in refs:
print(next(r.iterancestors("Table")).get("name"))
print(next(r.iterancestors("Column")).get("name"))
这将给你:
[('table1', 'COL2'), ('table2', 'COL3')]
table1
COL2
table2
COL3
您可以使用xpath来获取所需的两个祖先
x = """<?xml version="1.0" encoding="utf-8"?>
<Tables>
<Table name = "table1">
<Columns>
<Column name="COL1">...</Column>
<Column name="COL2">...
<References>
<Reference>TABLENAME</Reference>
</References>
</Column>
</Columns>
</Table>
<Table name = "table2">
<Columns>
<Column name="COL2">...</Column>
<Column name="COL3">...
<References>
<Reference>TABLENAME</Reference>
</References>
</Column>
</Columns>
</Table>
</Tables>"""
import lxml.etree as et
xml = et.fromstring(x)
refs = xml.iter("Reference")
print([(ref.xpath("./ancestor::Table/@name")[0], ref.xpath("./ancestor::Column/@name")[0]) for ref in refs])
或者,如果列始终是祖父母:
[(ref.xpath("./ancestor::Table/@name")[0], ref.xpath("./../../@name")[0]) for ref in refs]
使用您自己的逻辑,您可以在iTranceTors上调用next:
refs = xml.iter("Reference")
for r in refs:
print(next(r.iterancestors("Table")).get("name"))
print(next(r.iterancestors("Column")).get("name"))
这将给你:
[('table1', 'COL2'), ('table2', 'COL3')]
table1
COL2
table2
COL3
由于您只对迭代器的第一个结果感兴趣,因此可以使用
next
方法获取第一个元素,并避免不清楚/不必要的for
循环
xml_string = """
<Tables>
<Table name = "table1">
<Columns>
<Column name="COL1">...</Column>
<Column name="COL2">...
<References>
<Reference>TABLENAME</Reference>
</References>
</Column>
</Columns>
</Table>
<Table name = "table2">
<Columns>
<Column name="COL2">...</Column>
<Column name="COL3">...
<References>
<Reference>TABLENAME</Reference>
</References>
</Column>
</Columns>
</Table>
</Tables>"""
import lxml.etree as ETree
root = ETree.fromstring(bytes(xml_string, 'UTF-8'))
refiter = root.iter('Reference')
for r in refiter:
nameiter = r.iterancestors('Table')
name = next(nameiter).get('name')
print(name)
由于您只对迭代器的第一个结果感兴趣,因此可以使用
next
方法获取第一个元素,并避免不清楚/不必要的for
循环
xml_string = """
<Tables>
<Table name = "table1">
<Columns>
<Column name="COL1">...</Column>
<Column name="COL2">...
<References>
<Reference>TABLENAME</Reference>
</References>
</Column>
</Columns>
</Table>
<Table name = "table2">
<Columns>
<Column name="COL2">...</Column>
<Column name="COL3">...
<References>
<Reference>TABLENAME</Reference>
</References>
</Column>
</Columns>
</Table>
</Tables>"""
import lxml.etree as ETree
root = ETree.fromstring(bytes(xml_string, 'UTF-8'))
refiter = root.iter('Reference')
for r in refiter:
nameiter = r.iterancestors('Table')
name = next(nameiter).get('name')
print(name)
我不太明白你想要什么,我怎么能直接去引用迭代器呢?什么意思<代码> > //引用/祖先:表/ @名称/ /参考文献/祖先::列/ @名称)< /C> >将得到表和列名在一个单一的查询中,母语是C++,所以当我我缺少了另一种语言的词汇,我倾向于使用C++词,希望它们能以一种可理解的方式来映射。在C++中,如果我得到第一个元素的迭代器,我就可以“DeErrEng'”——访问迭代器直接指向的对象。所以我可以跳过一个循环。我试过你的问题,但恐怕我无法理解它的正确用法。最后我得到了所有表名和列名的列表。。。不是我想要的。你是说你不想在namiterans中为n添加
,只需获取上一个表和列名?也许一些有效的输入和预期的输出会使它更清楚一些。我认为在我看来,使用“引用引用”这个词是一个糟糕的选择,尽管我认为C++程序员会理解我所要做的。基本上我有一个子元素。这个子元素有一个单一的祖先“Table”,我想得到它的“name”属性。如果不在一个元素上循环,我可以得到它吗?@Spacemouse,有很多选项,请看下面的答案。我不完全符合您的要求,我可以以某种方式直接取消对迭代器的引用吗?什么意思<代码> > //引用/祖先:表/ @名称/ /参考文献/祖先::列/ @名称)< /C> >将得到表和列名在一个单一的查询中,母语是C++,所以当我我缺少了另一种语言的词汇,我倾向于使用C++词,希望它们能以一种可理解的方式来映射。在C++中,如果我得到第一个元素的迭代器,我就可以“DeErrEng'”——访问迭代器直接指向的对象。所以我可以跳过一个循环。我试过你的问题,但恐怕我无法理解它的正确用法。最后我得到了所有表名和列名的列表。。。不是我想要的。你是说你不想在namiter
ans中为n添加,只需获取上一个表和列名?也许一些有效的输入和预期的输出会使它更清楚一些。我认为在我看来,使用“引用引用”这个词是一个糟糕的选择,尽管我认为C++程序员会理解我所要做的。基本上我有一个子元素。这个子元素有一个单一的祖先“Table”,我想得到它的“name”属性。我能在一个元素上没有循环的情况下得到它吗?@Spacemouse,有很多选项,见下面的答案