我正在使用BeautifulSoup解析几个XML文档提要,并希望进行一些预处理以将非标准CDATA
标签替换为自定义XML标签。 举例说明:
以下 XML 源...
<title>The end of the world as we know it</title>
<category><![CDATA[Planking Dancing]]></category>
<pubDate><![CDATA[Sun, 16 Sep 2012 12:00:00 EDT]]></pubDate>
<dc:creator><![CDATA[Bart Simpson]]></dc:creator>
。会变成:
<title>The end of the world as we know it</title>
<category><myTag>Planking Dancing<myTag></category>
<pubDate><myTag>Sun, 16 Sep 2012 12:00:00 EDT<myTag></pubDate>
<dc:creator><myTag>Bart Simpson<myTag></dc:creator>
我认为这个问题以前在 SO 上没有被问过(我尝试了几个不同的 SO 查询)。 我还尝试了几种不同的方法,使用 .findAll('cdata', text=True)
并将 BeautifulSoup replaceWith()
方法应用于每个生成的NavigableString
。 我所做的尝试要么没有替换,要么看起来像递归循环。
我很高兴发布我以前的尝试,但鉴于这里的问题非常简单,我希望有人可以发布一个清晰的例子,说明如何使用 BeautifulSoup 3 完成上面的搜索和替换。
CData
是NavigableString
的子类,所以你可以找到所有CData
元素,首先搜索所有NavigableString
对象,然后测试每个是否都是CData
的实例。一旦你有一个,它很容易按照您的建议使用 replaceWith
替换:
>>> from BeautifulSoup import BeautifulSoup, CData, Tag
>>> source = """
... <title>The end of the world as we know it</title>
... <category><![CDATA[Planking Dancing]]></category>
... <pubDate><![CDATA[Sun, 16 Sep 2012 12:00:00 EDT]]></pubDate>
... <dc:creator><![CDATA[Bart Simpson]]></dc:creator>
... """
>>> soup = BeautifulSoup(source)
>>> for navstr in soup(text=True):
... if isinstance(navstr, CData):
... tag = Tag(soup, "myTag")
... tag.insert(0, navstr[:])
... navstr.replaceWith(tag)
...
>>> soup
<title>The end of the world as we know it</title>
<category><myTag>Planking Dancing</myTag></category>
<pubdate><myTag>Sun, 16 Sep 2012 12:00:00 EDT</myTag></pubdate>
<dc:creator><myTag>Bart Simpson</myTag></dc:creator>
>>>
几点注意事项:
您可以调用
BeautifulSoup
对象,就好像它是一个函数一样,并且效果与调用其.findAll()
方法相同。我知道在 BS3 中获取
CData
对象内容的唯一方法是切片它,如上面的代码片段所示。str(navstr)
会保留所有<![CDATA[...]]>
垃圾,显然你不想要。在 BS4 中,str(navstr)
为您提供没有垃圾的内容。