2010-05-19 6 views
1

J'ai une chaîne de texte qui contient html avec tous les différents types de liens (relatif, absolu, relatif à la racine). J'ai besoin d'une regex qui peut être exécutée par preg_replace de PHP pour remplacer tous les liens relatifs avec des liens relatifs à la racine, sans toucher aucun des autres liens. J'ai déjà le chemin racine.Regex pour remplacer le lien relatif par le lien relatif racine

liens REMPLACÉ:

<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" ... /> 

liens Untouched:

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

Doit-il être regex? L'utilisation d'une classe DOM pourrait permettre des résultats beaucoup plus précis. – webbiedave

+0

Il doit s'agir d'une regex car je n'ai aucune assurance que DOM sera suffisamment valide pour que tout lecteur DOM basique puisse être correctement analysé. –

Répondre

4

Si vous voulez juste changer l'URI de base, vous pouvez essayer le BASE element:

<base href="/basepath/"> 

Mais notez que la modification de l'URI de base affecte tous les URIs relatives et non seulement les chemins URI relatifs.

Sinon, si vous voulez vraiment utiliser l'expression régulière, considérer qu'un chemin relatif comme vous voulez doit être du chemin noScheme Type (voir 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 = "!"/"$"/"&"/"'"/"("/")" 
      /"*"/"+"/","/";"/"=" 

Alors le début de l'URI doit correspondre:

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

Veuillez utiliser un analyseur HTML approprié pour analyser le code HTML et créer un D OM hors de ça. Ensuite, vous pouvez interroger le DOM pour obtenir les attributs href et tester la valeur avec l'expression régulière ci-dessus.

+0

la balise de base a fonctionné presque parfaitement, sauf qu'il semble jouer avec des liens tels que href = "# test" il les transforme en href = "/ basepath/# test". Du côté positif, href = "link # test" devient href = "/ basepath/link # test", ce qui fonctionne. Existe-t-il un moyen pour les ancres de travailler avec la classe de base, sans rien savoir de l'URL actuelle? –

+0

Le commentaire ci-dessus est en fait un bug dans webkit (safari, chrome) et IE, ça fonctionne bien dans Firefox. –

+0

@Kendall Hopkins: Comme je l'ai dit: * tous les URI relatifs sont affectés. Et '# test' est un URI relatif. Et je dirais plutôt que c'est un bug dans Firefox de ne pas résoudre '# test' avec un URI de base de'/basepath/'à'/basepath/# test'. (Je pense que Firefox utilise l'algorithme de RFC 2396 alors que les autres utilisent celui de RFC 3986 qui a obsolète RFC 3986 il y a cinq ans.) – Gumbo

0

je suis venu avec ceci:

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

Il est peut-être un peu trop simpliste. La faille évidente que je vois est que cela correspondra aussi href="something" quand il est en dehors d'une étiquette, mais j'espère que cela peut vous aider à démarrer.

Questions connexes