2010-05-19 137 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",但希望它能帮助您开始。