2010-05-19 64 views
1

我有一個包含所有不同類型的鏈接(相對,絕對,根相對)的HTML文本的字符串。我需要一個可以由PHP的preg_replace執行的正則表達式來替換所有相關鏈接和根相關鏈接,而不會觸及任何其他鏈接。我已經有了根路徑。正則表達式來替換相對鏈接與根相對鏈接

替換鏈接:

<tag ... href="path/to_file.ext" ... > ---> <tag ... href="/basepath/path/to_file.ext" ... > 
<tag ... href="path/to_file.ext" ... /> ---> <tag ... href="/basepath/path/to_file.ext" ... /> 

非接觸鏈接:

<tag ... href="/any/path" ... > 
<tag ... href="/any/path" ... /> 
<tag ... href="protocol://domain.com/any/path" ... > 
<tag ... href="protocol://domain.com/any/path" ... /> 
+0

它必須是正則表達式嗎?使用DOM類可以提供更準確的結果。 – webbiedave 2010-05-19 22:28:01

+0

它必須是正則表達式,因爲我不能保證DOM對於任何基本的DOM閱讀器都能夠正確解析有效。 – 2010-05-19 22:32:34

回答

4

如果你只是想改變基礎URI,你可以嘗試BASE element

<base href="/basepath/"> 

但是請注意,改變基本URI影響所有相對URI,不只是相對的URI路徑。

否則,如果你真的想用正則表達式,認爲像你這樣的相對路徑要必須型路徑noscheme(見RFC 3986):

path-noscheme = segment-nz-nc *("/" segment) 
segment  = *pchar 
segment-nz-nc = 1*(unreserved/pct-encoded/sub-delims/"@") 
       ; non-zero-length segment without any colon ":" 
pchar   = unreserved/pct-encoded/sub-delims/":"/"@" 
pct-encoded = "%" HEXDIG HEXDIG 
unreserved = ALPHA/DIGIT/"-"/"."/"_"/"~" 
sub-delims = "!"/"$"/"&"/"'"/"("/")" 
      /"*"/"+"/","/";"/"=" 

所以URI的開頭必須匹配:

^([a-zA-Z0-9-._~!$&'()*+,;[email protected]]|%[0-9a-fA-F]{2})+($|/) 

但是,請使用適當的HTML解析器來解析HTML並構建一個D OM出了那個。然後,您可以查詢DOM以獲取href屬性,並使用上面的正則表達式測試該值。

+0

基本標記幾乎完美工作,除了它似乎與諸如href =「#test」之類的鏈接混淆在一起之後,它將它們變成了href =「/ basepath /#test」。另一方面,href =「link#test」變成了href =「/ basepath/link#test」,它工作正常。有沒有一種方法讓錨點與基類一起工作,而不知道任何當前的url? – 2010-05-19 23:50:40

+0

上面的評論其實是webkit(safari,chrome)和IE中的一個bug,它在Firefox中工作正常。 – 2010-05-20 00:06:39

+0

@肯德爾霍普金斯:正如我所說:*所有*相對URI都受到影響。 '#test'是一個相對URI。而且我寧願說這是Firefox中的一個錯誤,不能使用'/ basepath /'的基本URI解析'#test'到'/ basepath /#test'。 (我認爲Firefox使用RFC 2396的算法,而其他人使用RFC 3986在五年前廢棄RFC 3986的算法。) – Gumbo 2010-05-20 06:49:07

0

我想出了這一點:

preg_replace('#href=["\']([^/][^\':"]*)["\']#', $root_path.'$1', $html); 

這可能是有點過於簡單化。我看到的一個明顯的缺陷是,它在標籤之外時也會匹配href="something",但希望它能幫助您開始。