2

我正在用 BeautifulSoup 解析几个 XML 文档提要,并想做一些预处理以用自定义 XML 标记替换非标准CDATA标记。为了显示:

以下 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)BeautifulSoupreplaceWith()方法并将其应用于每个结果NavigableString。我所做的尝试要么没有替换,要么看起来像一个递归循环。

我很高兴发布我以前的尝试,但鉴于这里的问题非常简单,我希望有人可以发布一个清晰的示例,说明如何使用 BeautifulSoup 3 完成上述搜索和替换。

4

1 回答 1

2

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()方法是一样的。

  • 我知道CData在 BS3 中获取对象内容的唯一方法是对其进行切片,如上面的片段所示。str(navstr)会保留所有 <![CDATA[...]]>垃圾,这显然是您不想要的。在 BS4 中,str(navstr) 为您提供没有垃圾的内容。

于 2012-11-18T03:13:07.793 回答