使用BeautifulSoup append添加XML元素时命名空间丢失问题求助
问题:BeautifulSoup添加带命名空间的XML元素时命名空间丢失
我想向已有的<pic:pictures>标签中添加单个<pic:picture>元素,编写了如下代码:
for i, el in enumerate(data.get("pictures").get('picture')): img_link = el.get("link")[0].get('href') test = BeautifulSoup(""" <pic:picture> <pic:link rel="thumbnail" href="xxxx" /> </pic:picture> """, "xml") soup.ad.pictures.append(test) print(soup.ad.pictures)
执行后输出结果如下:
<pic:pictures> <picture> <link href="xxxx" rel="thumbnail"/> </picture><picture> <link href="xxxx" rel="thumbnail"/> </picture><picture> <link href="xxxx" rel="thumbnail"/> </picture><picture> <link href="xxxx" rel="thumbnail"/> </picture></pic:pictures>
疑问:为什么<pic:picture>和<pic:link>的pic命名空间消失了?之前尝试用new_tag方法能保留命名空间,用它创建<pic:pictures>没问题,但无法给<pic:pictures>添加<pic:link>元素。
原因与解决方法
命名空间丢失的原因
- 直接用BeautifulSoup解析带命名空间的XML字符串时,新生成的
soup对象与原有文档的soup对象不共享命名空间上下文。原有文档中pic命名空间已在上级节点声明,新解析的元素无法继承该上下文,输出时就会省略命名空间前缀。
正确解决方式:基于原有soup创建带命名空间的元素
不要重新解析XML字符串,而是依托原有soup的new_tag方法创建元素,同时关联正确的命名空间URI:
# 获取原有文档中pic命名空间的URI pic_namespace = soup.ad.pictures.namespace for i, el in enumerate(data.get("pictures").get('picture')): img_link = el.get("link")[0].get('href') # 创建带pic命名空间的picture标签 pic_picture = soup.new_tag("pic:picture", namespace=pic_namespace) # 创建带pic命名空间的link标签 pic_link = soup.new_tag("pic:link", namespace=pic_namespace) pic_link['rel'] = 'thumbnail' pic_link['href'] = img_link # 替换为实际图片链接 # 组装元素并添加到目标标签下 pic_picture.append(pic_link) soup.ad.pictures.append(pic_picture) print(soup.ad.pictures)
关于new_tag创建link失败的说明
之前用new_tag创建<pic:pictures>正常,但添加<pic:link>失败,大概率是创建pic:link时未指定正确的命名空间URI,或是没有基于同一个soup对象创建元素。所有带命名空间的元素必须由同一个soup对象生成,并关联正确的命名空间URI,才能让BeautifulSoup在输出时保留前缀。
内容的提问来源于stack exchange,提问作者otto
相关产品推荐
相关产品推荐

