I have a HTML document where I want to automatically have a version number added to all script and style sheet references.
the following should be replaced
<link ... href="file.css" media="all" />
<script ... src="file.js"></script>
<script ... src="http://myhost.com/file.js"></script>
with that
<link ... href="file.v123456.css" media="all" />
<script ... src="file.v123456.js"></script>
<script ... src="http://开发者_JAVA技巧myhost.com/file.v123456.js"></script>
where 123456 is my dynamic version number.
But it shoud ONLY do that on local files
<link ... href="http://otherhost.com/file.css" media="all" />
should be left untouched.
So far I have the following regex:
$html = preg_replace('#(src|href)=("|\')(?!http)(?!("|\'| |\+))(.*)\.(css|js|swf)("|\')#Ui', '\\1=\\2\\3\\4.v'.$version .'.\\5\\6', $html);
But it does not work 100% and I am sure that there is a better way in doing this. How would you write it?
Edit:
I have it now using DOMDocument, but it turns out that it's pretty slow!
<?php
//------- snip --------------
$host = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
$refs = array();
$version = "v". $version;
$doc = new DOMDocument();
$tmpDoc = $html;
$doc->loadHTML($tmpDoc);
$xpath = new DOMXPath($doc);
foreach($xpath->query('/html/head/link/@href') as $href) {
$ref = $href->value;
if(
!preg_match('/^https?:/', $ref) ||
strpos($ref, $host) === 0
) {
$refs[$ref] = preg_replace('/\.css$/', '.'.$version.'$0', $ref);
}
}
foreach ($xpath->query('//script/@src') as $src) {
$ref = $src->value;
if(
!preg_match('/^https?:/', $ref) ||
strpos($ref, $host) === 0
) {
$refs[$ref] = preg_replace('/\.js$/', '.'.$version.'$0', $ref);
}
}
$html = str_replace(
array_keys($refs),
array_values($refs),
$tmpDoc
);
//------- snip --------------
?>
Don't use regex, at least not to find the src
values. Use the DOM.
var allScriptTags = document.getElementsByTagName("script");
var allLinkTags = document.getElementsByTagName("link");
for(var i=0; i<allScriptTags.length; i++) {
var srcAttribute = allScriptTags[i].getAttribute("src");
// ... do something with srcAttribute ...
// replace it with the modified value
allScriptTags[i].setAttribute("src", srcAttribute);
}
You should better use a HTML parser like Simple HTML DOM Parser or DOMDocument to find the elements/attributes. Then you can use regular expressions to modify the attribute values.
Here’s an example for DOMDocument:
$version = 'v123456';
$doc = new DOMDocument();
$doc->loadHTML($code);
$xpath = new DOMXPath($doc);
foreach ($xpath->query('/html/head/link/@href') as $href) {
if (!preg_match('/^https?:/', $href->value)) {
$href->value = preg_replace('/\.css$/', '.'.$version.'$0', $href->value);
}
}
foreach ($xpath->query('//script/@src') as $src) {
if (!preg_match('/^https?:/', $src->value)) {
$src->value = preg_replace('/\.js$/', '.'.$version.'$0', $src->value);
}
}
why not something a lot more simple like:
$version = 12345;
function print_local_css($base_filename)
{
global $version;
print '<link rel="stylesheet" type="text/css" href="'.$base_filename.'.v'.$version.'.css" />';
}
function print_local_js($base_filename)
{
global $version;
print '<script type="text/javascript" src="'.$base_filename.'.v'.$version.'.js"></script>';
}
It'll be quick, one location to change the version and any files you don't want to be versioned, just manually put the HTML in.
精彩评论