Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 我可以取消对lxml.etree.AncestorsIterator的引用吗?_Python_Lxml - Fatal编程技术网

Python 我可以取消对lxml.etree.AncestorsIterator的引用吗?

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>

我使用lxml来操作一个用xml文件表示的dbschema。它看起来像这样:

<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,有很多选项,见下面的答案