2012-09-16 61 views
2

我正在使用BeautifulSoup解析多個XML文檔源,並且想要執行一些預處理以用自定義XML標記替換非標準CDATA標記。爲了說明:用BeautifulSoup中的標籤替換CDATA NavigableStrings

下面的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.

回答

2

CDataNavigableString子類,所以你可以先搜索所有NavigableString對象,然後測試 每個是否是CData實例找到所有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) 爲您提供沒有垃圾的內容。