当前位置: 首页 > news >正文

递归解析 LXML 树并避免重复进入某个节点

在这里插入图片描述

1、问题背景

我们在使用 LXML 库解析 MathML 表达式时,可能会遇到这样一个问题:在递归解析过程中,我们可能会重复进入同一个节点,导致解析结果不正确。例如,我们希望将以下 MathML 表达式解析为 Python 表达式:

<?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><mn>3</mn></mn><mn>5</mn></mn></mfrac></mrow>
</math>

如果我们使用以下代码来解析该表达式:

def parseMML(mmlinput):from lxml import etreefrom StringIO import *from lxml import objectifyexppy=[]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 numberexppy+=elem.textreturn (exppy)

那么我们得到的解析结果将是:

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

而不是我们期望的:

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

这是因为在解析 mfrac 节点时,我们递归调用了 parseMML 函数两次,分别解析了分子和分母。而在解析分子时,我们又递归调用了 parseMML 函数,导致重复进入了 mrow 节点。

2、解决方案

为了解决这个问题,我们可以使用一个栈来保存已经解析过的节点。当我们开始解析一个新的节点时,我们可以将该节点压入栈中。当我们完成解析该节点时,我们可以将该节点从栈中弹出。这样,我们就能够避免重复进入同一个节点。

以下代码演示了如何使用栈来避免重复进入同一个节点:

def parseMML(mmlinput):from lxml import etreefrom StringIO import *from lxml import objectifyexppy=[]events = ("start", "end")context = etree.iterparse(StringIO(mmlinput),events=events)nodestack=[]for action, elem in context:if action=='start' and elem.tag in nodestack:continueif (action=='start') and (elem.tag=='mrow'):nodestack.append(elem.tag)exppy+='('if (action=='end') and (elem.tag=='mrow'):nodestack.pop()exppy+=')'if (action=='start') and (elem.tag=='mfrac'):nodestack.append(elem.tag)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 numberexppy+=elem.textreturn (exppy)

使用该代码,我们可以得到正确的解析结果:

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

相关文章:

  • Plotly : 超好用的Python可视化工具
  • Django路由与会话深度探索:静态、动态路由分发,以及Cookie与Session的奥秘
  • 05 Hadoop简单使用
  • 品牌与产品:消费者决策的经济逻辑与品牌宣传的战略意义
  • Keil MDK 下载安装相对应CPU的Software Packs
  • QT6 学生管理系统以及登录(QSQLITE数据库)
  • “探索AIGC市场:腾讯元宝APP加入竞争,大模型产品的未来走向与个人选择“
  • 在 .NET Core 中构建工作服务和调度运行
  • Java 关于抽象 -- Java 语言的抽象类、接口和函数式接口
  • STM32项目分享:智能蓝牙手环
  • 攻防世界--杂项misc-2017_Dating_in_Singapore
  • 力扣爆刷第149天之TOP100五连刷(LRU、K个一组)
  • 专栏【汇总】
  • Ansible——shell模块
  • 面试题:如何避免索引失效?
  • [ JavaScript ] 数据结构与算法 —— 链表
  • JavaScript-Array类型
  • Java读取Properties文件的六种方法
  • js数组之filter
  • mysql中InnoDB引擎中页的概念
  • pdf文件如何在线转换为jpg图片
  • Python 反序列化安全问题(二)
  • spring学习第二天
  • Web标准制定过程
  • Xmanager 远程桌面 CentOS 7
  • 初识MongoDB分片
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 聊聊redis的数据结构的应用
  • 前端知识点整理(待续)
  • 树莓派 - 使用须知
  • 无服务器化是企业 IT 架构的未来吗?
  • scrapy中间件源码分析及常用中间件大全
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • # Apache SeaTunnel 究竟是什么?
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #HarmonyOS:基础语法
  • (+4)2.2UML建模图
  • (003)SlickEdit Unity的补全
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (2024最新)CentOS 7上在线安装MySQL 5.7|喂饭级教程
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (vue)页面文件上传获取:action地址
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (二十四)Flask之flask-session组件
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (四)搭建容器云管理平台笔记—安装ETCD(不使用证书)
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • *Django中的Ajax 纯js的书写样式1
  • .bat批处理(六):替换字符串中匹配的子串