2012-08-23 56 views
4

我有HTML的字符串,在這個例子中,它看起來像如何將HTML轉換爲有效的XHTML?

<img src="somepic.jpg" someAtrib="1" > 

我想鍛鍊正則表達式的peice的,將匹配「IMG」節點和應用斜線到節點的末尾,以便看起來像。

<img src="somepic.jpg" someAtrib="1" /> 

基本上這裏的最終目標是確保該節點是封閉的,開放的節點是在HTML有效,但不是很明顯XML。有沒有任何正則表達式的buff可以幫助?

+3

您不應該[使用正則表達式解析(X)HTML](http://stackoverflow.com/a/1732454/451590)。 HTML是不規則的,因此是正則表達式的一個不好的候選。使用完整的HTML解析器。 –

+0

@DavidB我明白你在說什麼。但是我試圖操縱一個'字符串',這就是爲什麼我問這個問題:) – John

+0

原始標記無效,並且請求的XHTML標記也不是。你的意思是「良性」而不是「有效」? –

回答

11

不要使用正則表達式,而是使用專用解析器。

var doc = new DOMParser().parseFromString('<img src="foo">', 'text/html'); 
var result = new XMLSerializer().serializeToString(doc); 
// result: 
// <html xmlns="http://www.w3.org/1999/xhtml"><head></head><body> (no line break) 
// <img src="foo" /></body></html> 
+0

嘿羅布。我想學習如何使用這種技術。我正在運行Opera9,IE6和FF2(我的所有代碼都必須在舊版瀏覽器上運行,以確保向後兼容),並且上述代碼不能按原樣運行。還需要包括哪些內容才能使其發揮作用?你能發佈一個完整的工作功能嗎?謝謝。 – ridgerunner

+1

@ridgerunner它支持IE9 +,FF 12+(4 + DOMParser text/html polyfill),Opera 11.6+(含DOMParser polyfill)。 Chrome(21)有一個錯誤是沒有添加'/>'。對不起,我沒有詳細說明,我很忙。隨意編輯我的/你的答案,使其更完整,如果你願意。 –

+0

仍然無法在Chrome(34)中使用,所以這是一項很酷的技術,但如果您的用戶使用Chrome,則不會。 – rossdavidh

1

這會是一個很好的工作:

result = text.replace(/(<img\b[^<>]*[^<>\/])>/ig, "$1 />"); 

附錄:在(不可能),你的代碼在JavaScript中,創建一個使用DOMParser文件,然後使用XMLSerializer序列化包括含有尖括號標記屬性(這是不是vaild XML/XHTML BTW),那麼這個人會做的更好一點的工作:

result = text.replace(/(<img\b(?:[^<>"'\/]+|'[^']*'|"[^"]*")*)>/ig, "$1 />"); 
+0

謝謝你,以及刪除他的帖子的人! – John

+0

@John正則表達式不能用於創建符合XHTML的文檔的原因是它不可靠。例如,此答案在'2 > 1「src =」2gt1「>'處已失敗,輸出爲'<img alt= 1」src =「2gt1」>'。 –

+0

啊,我看@RobW無論如何都謝謝你! – John

0

爲什麼會ü想˚F瀏覽器DOM中的ix XHTML無效的HTML文檔?

它已經被服務和解析,並且您已經有DOM可用。任何分析錯誤,無效/不良形成的文檔會導致,已經發生,它不會是一個正則表達式,將解決它。

另外,請記住幾乎所有的文檔都被解析爲HTML標籤湯。如果您無法在服務器端修復文檔,請忽略其在客戶端的有效性/良好性。

3

您可以創建一個xhtml文檔並導入/採用html元素。 Html字符串可以通過原因的HTMLElement.innerHTML屬性進行解析。 關鍵的一點是使用Document.importNode()或Document.adoptNode()方法來轉換 HTML節點到節點XHTML:

var di = document.implementation; 
var hd = di.createHTMLDocument(); 
var xd = di.createDocument('http://www.w3.org/1999/xhtml', 'html', null); 
hd.body.innerHTML = '<img>'; 
var img = hd.body.firstElementChild; 
var xb = xd.createElement('body'); 
xd.documentElement.appendChild(xb); 
console.log('html doc:\n' + hd.documentElement.outerHTML + '\n'); 
console.log('xhtml doc:\n' + xd.documentElement.outerHTML + '\n'); 
img = xd.importNode(img); //or xd.adoptNode(img). Now img is a xhtml element 
xb.appendChild(img); 
console.log('xhtml doc after import/adopt img from html:\n' + xd.documentElement.outerHTML + '\n'); 

輸出應該是:

html doc: 
<html><head></head><body><img></body></html> 

xhtml doc: 
<html xmlns="http://www.w3.org/1999/xhtml"><body></body></html> 

xhtml doc after import/adopt img from html: 
<html xmlns="http://www.w3.org/1999/xhtml"><body><img /></body></html> 

羅布·W公司的回答呢由於DOMParser不支持'text/html'類型,而且XMLSerializer爲chrome中的html文檔生成html語法(不是xhtml),所以不能在chrome中工作(至少爲29以下)。

+0

這似乎是比Rob W更好的解決方案。 importNode()有第二個參數,如果你還想轉換後代元素 – fishbone

2

除了羅布W公司answer,可以提取正文內容使用正則表達式:

var doc = new DOMParser().parseFromString('<img src="foo">', 'text/html'); 
var result = new XMLSerializer().serializeToString(doc); 

/<body>(.*)<\/body>/im.exec(result); 
result = RegExp.$1; 

// result: 
// <img src="foo" /> 

注:parseFromString(htmlString, 'text/html');將拋出錯誤在IE9因爲text/html的 mime類型不supported in IE9。雖然與IE10和IE11一起工作。

+0

爲什麼使用regexp?你可以簡單地使用doc.body.innterHTML –

+0

糾正我自己。 innerHTML將例如返回
而不是
。但這個正則表達式模式更好地工作http://stackoverflow.com/questions/3628374/how-to-extract-body-contents-using-regexp –