2010-03-10 35 views
2

我期待學習如何在Coldfusion中創建REGEX,它將掃描大量HTML文本並創建項目列表。ColdFusion,REGEX - 鑑於TEXT,查找SPAN中包含的所有項目

我想要的物品都包含以下

<span class="findme">The Goods</span> 

感謝之間的任何提示,以幫助這是怎麼回事。

+0

我仍在尋找一個優雅,簡單的解決方案。那不是buggy – AnApprentice 2010-03-12 04:53:54

+0

爲什麼用正則表達式代替某種形式的DOM解析?假設你的html格式良好,顯然 – 2010-03-18 17:11:47

回答

6

你不說什麼版本的CF.由於V8可以使用REMatch獲取數組

results = REMatch('(?i)<span[^>]+class="findme"[^>]*>(.+?)</span>', text) 

使用ArrayToList來把它轉換成一個列表。 對於較早的版本,使用REFindNoCase並使用Mid()提取子字符串。

編輯:要回答你的後續評論使用REFINDER返回所有匹配的過程是相當涉及,因爲該功能只返回第一場比賽。這意味着您實際上每次都必須多次調用REFIN並傳遞新的startpos。本福塔已經寫了一個UDF,完成這個並且會爲你節省一些時間。

<!--- 
Returns all the matches of a regular expression within a string. 
NOTE: Updated to allow subexpression selection (rather than whole match) 

@param regex  Regular expression. (Required) 
@param text  String to search. (Required) 
@param subexnum Sub-expression to extract (Optional) 
@return Returns a structure. 
@author Ben Forta ([email protected]) 
@version 1, July 15, 2005 
---> 
<cffunction name="reFindAll" output="true" returnType="struct"> 
<cfargument name="regex" type="string" required="yes"> 
<cfargument name="text" type="string" required="yes"> 
<cfargument name="subexnum" type="numeric" default="1"> 

<!--- Define local variables --->  
<cfset var results=structNew()> 
<cfset var pos=1> 
<cfset var subex=""> 
<cfset var done=false> 

<!--- Initialize results structure ---> 
<cfset results.len=arraynew(1)> 
<cfset results.pos=arraynew(1)> 

<!--- Loop through text ---> 
<cfloop condition="not done"> 

    <!--- Perform search ---> 
    <cfset subex=reFind(arguments.regex, arguments.text, pos, true)> 
    <!--- Anything matched? ---> 
    <cfif subex.len[1] is 0> 
     <!--- Nothing found, outta here ---> 
     <cfset done=true> 
    <cfelse> 
     <!--- Got one, add to arrays ---> 
     <cfset arrayappend(results.len, subex.len[arguments.subexnum])> 
     <cfset arrayappend(results.pos, subex.pos[arguments.subexnum])> 
     <!--- Reposition start point ---> 
     <cfset pos=subex.pos[1]+subex.len[1]> 
    </cfif> 
</cfloop> 

<!--- If no matches, add 0 to both arrays ---> 
<cfif arraylen(results.len) is 0> 
    <cfset arrayappend(results.len, 0)> 
    <cfset arrayappend(results.pos, 0)> 
</cfif> 

<!--- and return results ---> 
<cfreturn results> 
</cffunction> 

這給了你每場比賽的開始(POS)和長度,從而得到各子使用另一個循環

<cfset text = '<span class="findme">The Goods</span><span class="findme">More Goods</span>' /> 
<cfset pattern = '(?i)<span[^>]+class="findme"[^>]*>(.+?)</span>' /> 
<cfset results = reFindAll(pattern, text, 2) /> 
<cfloop index="i" from="1" to="#ArrayLen(results.pos)#"> 
    <cfoutput>match #i#: #Mid(text, results.pos[i], results.len[i])#<br></cfoutput> 
</cfloop> 

編輯:更新reFindAll與subexnum說法。將其設置爲2將捕獲第一個子表達式。默認值1捕獲整個匹配。

+0

嗨SpliFF感謝你的想法。無論如何,你可以告訴我你正在考慮REFINNOCASE&Mid()的想法,我很想知道他們如何一起工作。 thankxs – AnApprentice 2010-03-10 04:59:00

+0

好消息!我可以用上面的REGEX命名爲REGet的CF腳本,它可以工作並獲得所有的跨度。 問題是它返回的標籤,我不想.. \t WTC圈養與A $ 1十億FEMA授權創建和提供保險 上面的REGEX如何被更新爲只發回:WTC Captive創建了一個價值10億美元的FEMA撥款並提供了保險範圍 – AnApprentice 2010-03-12 05:01:49

+0

如果您查看上面的函數,您會看到它使用'subex查找匹配位置。 LEN [1]'。爲什麼在那裏?那麼如果你檢查REFIN的文檔,你會發現len和pos實際上是'匹配的subpressions'的數組。正則表達式標準說整個表達式總是第一個匹配,所以它會顯示匹配開始的位置(在標籤的邊緣)。子表達式是括號中的一個匹配項。仔細看看我給你的正則表達式,你會看到'(。+?)'。這是一個將被存儲爲匹配2的子表達式。因此,只需在上面的函數中將pos [1]更改爲pos [2]並將len [1]更改爲len [2]。 – SpliFF 2010-03-15 22:55:10

2

試着尋找使你的HTML使用常規DOM解析器工作並通過XPath查詢的可能性,而不是敲打這個基於正則表達式的可憎的槽。

  1. 使HTML輸入可用,使其通過jTidy(見http://jtidy.riaforge.org/
  2. 一旦有了良好的XML/XHTML,使用從它
    <cfset dom = XmlParse(scrubbedHtml, true)>
  3. 查詢XML文檔建立的XML文檔XPath
    <cfset result = XmlSearch(dom, "//span[@class='findme']")>

完成。

編輯:Coldfusion的XmlSearch()沒有很好的XML名稱空間支持。如果最終生成的是XHTML而不是更值得推薦的XML,請使用以下XPath(注意冒號)"//:span[@class='findme']""//*:span[@class='findme']"。有關更多信息,請參閱herehere

查看jTidy API documentation瞭解jTidy可以做什麼的完整概述。

+0

Well-Formed HTML是什麼意思?它已經是一個來自所見即所得編輯器的TEXT的HTML塊?那麼這是否需要?另外,RESULT會被設置爲什麼?一個字符串,一個數組等?將會有多個SPAN應該在TEXT中匹配。 – AnApprentice 2010-03-10 22:46:21

+1

良好的形式意味着按書,按規格,無錯 - 任何HTML。更好的是XHTML。並不是所有的所見即所得編輯器都能生產這種產品。一些可以提供給XML解析器而不會窒息的東西。 jTidy可以輕鬆清理不符合規範的鬆散HTML。一旦你這樣做了,你可以評估它的*結構*而不是拋出令人難以置信的正則表達式,永遠不會很好地完成這項工作。結果'然後將包含匹配的''節點的數組。我的建議是放棄正則表達式,儘可能地吸引人,贊成這一點。 – Tomalak 2010-03-10 23:22:34

+0

好吧這有幫助,但爲什麼這比REGEX更好? – AnApprentice 2010-03-11 00:17:27

相關問題