通过 apache 服务器内部的服务器端过滤,在 SVG 中动态包含 javascript
Dynamic inclusion of javascript in SVG by means of server side filtering inside apache server
几年前,我编写了一些代码,自动将一些 javascript 代码包含在由 http 服务器传送的 html 页面中。该方法记录在此处的 blog entry and in this Whosebug question 中。在过去的几年里,这个解决方案对我很有帮助。
两句话的方法:
- 对于 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
的内联脚本标记(我已经测试过动态执行此操作,就像您的代码看似 "more correct" 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")
几年前,我编写了一些代码,自动将一些 javascript 代码包含在由 http 服务器传送的 html 页面中。该方法记录在此处的 blog entry and in this Whosebug question 中。在过去的几年里,这个解决方案对我很有帮助。
两句话的方法:
- 对于 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
的内联脚本标记(我已经测试过动态执行此操作,就像您的代码看似 "more correct" 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")