如何用lxml的findall()在RetroPie gamelist.xml中按标题模糊查找游戏元素
使用lxml从RetroPie的gamelist.xml中模糊匹配游戏元素
嘿,这个需求我熟!要实现基于标题的部分匹配甚至模糊搜索,结合lxml的findall()和XPath的字符串处理函数就能轻松搞定。下面是一步步的实现方案,直接就能用:
核心思路
RetroPie的gamelist.xml结构里,每个游戏的标题都存在<name>标签中,我们可以用XPath的contains()函数来检查标题是否包含搜索关键词,再配合lower()实现不区分大小写的匹配,这样不管用户搜"baseball"还是"BaseBall"都能命中目标。
完整代码示例
首先确保你已经安装了lxml:
pip install lxml
然后编写Python代码:
from lxml import etree def search_games_by_title(gamelist_path, search_query): # 解析XML文件 tree = etree.parse(gamelist_path) root = tree.getroot() # 构造不区分大小写的模糊匹配XPath表达式 # .//game 遍历所有游戏元素 # contains(lower(name), lower(...)) 检查标题是否包含搜索词(忽略大小写) xpath_expr = f".//game[contains(lower(name), lower('{search_query}'))]" matching_games = root.findall(xpath_expr) # 提取匹配到的游戏信息 results = [] for game in matching_games: game_info = { "name": game.find("name").text if game.find("name") is not None else "无标题", "path": game.find("path").text if game.find("path") is not None else "无路径", "id": game.get("id") if game.get("id") is not None else "无ID" } results.append(game_info) return results # 调用示例 if __name__ == "__main__": gamelist_path = "/home/pi/RetroPie/roms/snes/gamelist.xml" # 替换成你的文件路径 search_term = "baseball" # 可以是任意部分标题内容 matched_games = search_games_by_title(gamelist_path, search_term) if matched_games: print(f"找到{len(matched_games)}个匹配的游戏:") for idx, game in enumerate(matched_games, 1): print(f"{idx}. 标题: {game['name']}, 路径: {game['path']}, ID: {game['id']}") else: print("没有找到匹配的游戏")
关键细节说明
- 不区分大小写匹配:用
lower()把<name>的文本和搜索词都转成小写,避免因为大小写差异漏匹配(比如示例中的"SUPER BASEBALL 2020"和搜索词"baseball"就能匹配上) - 部分匹配:
contains()函数会检查标题是否包含搜索词的任意子串,不管搜索词在标题的开头、中间还是结尾都能命中 - 鲁棒性处理:代码里判断了标签和属性是否存在,避免XML结构不完整时抛出异常
扩展用法
如果需要更精准的匹配,可以调整XPath表达式:
- 匹配标题开头:
starts-with(lower(name), lower('super')) - 匹配标题结尾:
ends-with(lower(name), lower('2020')) - 精确匹配(区分大小写):
name='SUPER BASEBALL 2020'
内容的提问来源于stack exchange,提问作者JManRiceCakes
相关产品推荐
相关产品推荐

