几年前,我编写了一些代码来自动将一些javascript代码包含在http服务器提供的html页面中。该方法记录在博客条目和此 StackOverflow 问题中。在过去的几年里,这个解决方案对我很有帮助。
两句话的方法:
- 对于 HTTP 服务器提供的每个完整 HTML 页面,通过服务器端替换将一些占位符添加到页面底部
- 该占位符再次替换为要通过服务器端包含的 JavaScript 代码
现在,我想扩展该解决方案,并将相同的逻辑应用于基于 SVG 而不是 HTML 作为文档格式的页面。注意:不是 html 页面中包含的 SVG,而是通过链接直接引用的 SVG 格式的页面。
扩展本身不是问题,javascript代码包含在SVG标记中。问题是代码未执行。不幸的是,我对 SVG 中的脚本知之甚少,这就是为什么我有些迷茫的原因。也许有人可以给我一个提示,这里出了什么问题:-)
各种 apache vhosts 定义中包含的过滤器链:
# ----------
# internal requests to include the piwik tracking code at the bottom of every html page
FilterDeclare PIWIK_token
FilterProvider PIWIK_token SUBSTITUTE resp=Content-Type $text/html
SUBSTITUTE 's|^s*</body>|<!--#include virtual="/piwik"--></body>|iq'
FilterProvider PIWIK_token SUBSTITUTE resp=Content-Type $image/svg+xml
SUBSTITUTE 's|^s*</svg>|<!--#include virtual="/piwik"--></svg>|iq'
FilterDeclare PIWIK_code
FilterProvider PIWIK_code INCLUDES resp=Content-Type $text/html
FilterProvider PIWIK_code INCLUDES resp=Content-Type $image/svg+xml
FilterChain PIWIK_token PIWIK_code
# map virtual request to the file system
Alias /piwik /srv/www/internal/piwik.php
# all that is left for the virtual host is to do two things:
# SetEnv PIWIK_ID 15
# Include /etc/apache2/vhosts.d/_internal.inc
# note: the '15' above is an example piwik site id
要包含的 javascript 代码是 piwik 跟踪代码段的略微修改版本:
<?php
define('piwikBase','https://some.domain.xxx/stats/');
define('piwikSite',apache_getenv('PIWIK_ID'));
if(is_numeric(piwikSite)){
?>
<script type="text/javascript">
var _paq = _paq || [];
_paq.push(["trackPageView"]);
_paq.push(["enableLinkTracking"]);
(function() {
var u="<?= piwikBase ?>";
_paq.push(["setTrackerUrl", u+"piwik.php"]);
_paq.push(["setSiteId", "<?= piwikSite ?>"]);
var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s);
})();
</script>
<?php } else { ?>
<!-- invalid piwik site id: <?php echo piwikSite;?> -->
<?php } ?>
如前所述:扩展有效,javascript代码成功包含在SVG文档中。但是它显然没有被激活,我没有看到原因......
交付的最终 SVG 如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.2"
width="100%"
height="100%"
viewBox="0 0 640 400"
docname="somedocument.svg">
[... content of the SVG ...]
<script type="text/javascript">
var _paq = _paq || [];
_paq.push(["trackPageView"]);
_paq.push(["enableLinkTracking"]);
(function() {
var u="https://some.domain.xxx/stats/";
_paq.push(["setTrackerUrl", u+"piwik.php"]);
_paq.push(["setSiteId", "15"]);
var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s);
})();
</script>
</svg>
只是猜测,但我会尝试更改代码,以便将动态脚本注入替换为带有 xlink:href
的内联脚本标签(我已经测试过动态执行此操作,就像您的代码使用看似"更正确"createAttibuteNS('xlink','href','...')
但结果也没有执行)
生成的代码如下所示(尚未在真实环境中测试,因此拼写错误):
<?php
define('piwikBase','https://some.domain.xxx/stats/');
define('piwikSite',apache_getenv('PIWIK_ID'));
if(is_numeric(piwikSite)){
?>
<script type="text/javascript"><![CDATA[
var _paq = _paq || [];
_paq.push(["trackPageView"]);
_paq.push(["enableLinkTracking"]);
_paq.push(["setTrackerUrl", "<?= piwikBase ?>piwik.php"]);
_paq.push(["setSiteId", "<?= piwikSite ?>"]);
]]></script>
<script type="text/javascript"
xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="<?= piwikBase ?>piwik.js"
defer="defer" async="async"></script>
<?php } else { ?>
<!-- invalid piwik site id: <?php echo piwikSite;?> -->
<?php } ?>
我不确定那些defer
和async
的东西,它是否在 SVG 中有任何影响。我已经用简单的datauri示例对此进行了测试,它似乎运行良好。
笔记:
- 脚本或其某些父级
xmlns:xlink="http://www.w3.org/1999/xlink"
是必要的,但很可能您的 SVG 已经拥有它 - 在这种情况下,
CDATA
不是必需的,但是如果您打算将来使用<
或&
...你知道吗。
不能使用 创建 SVG 脚本元素
g=d.createElement("script")
你需要写
g=d.createElementNS("http://www.w3.org/2000/svg", "script")