如何使用递归iterparse来避免重复进入一个LXML树节点?

2024-09-29 21:59:40 发布

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

递归函数是parseMML。我希望它将MathML表达式解析为Python表达式。简单的例子mmlinput是por产生的分数3/5,但它产生:

['(', '(', '3', ')', '/', '(', '5', ')', '(', '3', ')', '(', '5', ')', ')']

而不是:

^{pr2}$

因为我不知道如何删除已经递归输入的元素。有什么办法跳过它们吗?在

谢谢

mmlinput='''<?xml version="1.0"?> <math xmlns="http://www.w3.org/1998/Math/MathML" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/1998/Math/MathML http://www.w3.org/Math/XMLSchema/mathml2/mathml2.xsd"> <mrow> <mfrac> <mrow> <mn>3</mn> </mrow> <mrow> <mn>5</mn> </mrow> </mfrac> </mrow> </math>'''


def parseMML(mmlinput):
    from lxml import etree
    from StringIO import *
    from lxml import objectify
    exppy=[]
    events = ("start", "end")
    context = etree.iterparse(StringIO(mmlinput),events=events)
    for action, elem in context:
        if (action=='start') and (elem.tag=='mrow'):
            exppy+='('
        if (action=='end') and (elem.tag=='mrow'):
            exppy+=')'
        if (action=='start') and (elem.tag=='mfrac'):
            mmlaux=etree.tostring(elem[0])
            exppy+=parseMML(mmlaux)
            exppy+='/'
            mmlaux=etree.tostring(elem[1])
            exppy+=parseMML(mmlaux)
        if action=='start' and elem.tag=='mn': #this is a number
            exppy+=elem.text
    return (exppy)

Tags: orghttpwwwactionmathmathmlstartetree
1条回答
网友
1楼 · 发布于 2024-09-29 21:59:40

问题是您要对mfrac标记中的子树进行两次解析, 因为你在递归地解析它。一个快速的解决办法是数一数 递归级别:

mmlinput = "<math> <mrow> <mfrac> <mrow> <mn>3</mn> </mrow> <mrow> <mn>5</mn> </mrow> </mfrac> </mrow> </math>"

def parseMML(mmlinput):
    from lxml import etree
    from StringIO import *
    from lxml import objectify
    exppy=[]
    events = ("start", "end")
    level = 0
    context = etree.iterparse(StringIO(mmlinput),events=events)
    for action, elem in context:
        if (action=='start') and (elem.tag=='mfrac'):
            level += 1
            mmlaux=etree.tostring(elem[0])
            exppy+=parseMML(mmlaux)
            exppy+='/'
            mmlaux=etree.tostring(elem[1])
            exppy+=parseMML(mmlaux)
        if (action=='end') and (elem.tag=='mfrac'):
            level -= 1
        if level:
            continue
        if (action=='start') and (elem.tag=='mrow'):
            exppy+='('
        if (action=='end') and (elem.tag=='mrow'):
            exppy+=')'
        if action=='start' and elem.tag=='mn': #this is a number
            exppy+=elem.text
    return (exppy)

注意:我必须删除名称空间来实现这一点,因为elem.tag会为我返回完全限定的标记名。您还可以使用+=将字符串添加到列表中。对于可能有效的单字符字符串,但是列表上的+的工作方式与调用extend类似,因此:

^{pr2}$

相关问题 更多 >

    热门问题