我正在编写一个应用程序来可视化几个数据库的内容。这个应用程序应该尽可能简单地安装和使用,所以我决定使用XML文件作为数据库,并通过浏览器使用XSL充分转换它们。现在,XSL文件被编程为创建每个数据库的汇总表,并通过单击每行的第一个单元格,显示整个条目的更完整描述。这意味着该页面包含数据库中每条记录的每个完整描述,但这种情况会减慢页面的加载速度,这需要最多5秒才能加载数百条记录。由于我计划在未来大量扩展数据库,这个问题注定会变得更糟。为了减少负载,下一个明显的步骤是采用某种延迟加载,或者使用AJAX或iframe(现在不是那么重要而不是问题的重点),但是我遇到了一些困难。我的想法是直接调用这样的XML文件:
file:///path/to/file/transform.xml?id=23
使用transform.xml:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="transform.xsl"?>
<content />
并且transform.xsl是:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xsl:output method="html" version="5" doctype-system="about:legacy-compat" indent="yes" />
<xsl:param name="url" />
<xsl:template match="/">
<html>
<body><xsl:value-of select="$url" /></body>
</html>
</xsl:template>
</xsl:stylesheet>
现在这仅仅是一个概念证明,但这一部分是所有后续的基石,如果它不起作用,那么继续这样做是没有用的。
我现在所能看到的只是一个空白页面。我还尝试将参数名称更改为id
,但页面仍为空。
我知道这可以通过PHP或其他服务器端解决方案轻松实现,MySQL会更高效,但我真的需要这个应用程序在下载结束时才可用。如果我的用户必须安装* AMP服务器,他们可能不会。公共服务器也不是解决方案,因为我需要将此应用程序脱机运行。另一方面,JavaScript / jQuery解决方案是完全可以接受的,因为它是客户端的。
编辑:我的大部分工作都基于this question,它似乎有效,但很老,该示例包含ASP页面的URL。
答案 0 :(得分:0)
使用xml-stylesheet处理指令调用转换不提供任何为转换提供参数的方法。因此参数将采用其默认值,即零长度字符串。
很抱歉,但这个设计不会飞。
我认为唯一的方法是在HTML页面中使用Javascript代码以编程方式调用转换。
一种选择是使用Saxon-JS而不是依赖浏览器提供的XSLT引擎。这将使您可以访问XSLT 2.0 / 3.0功能而不是1.0,而在2.0中,样式表可以使用document-uri()函数访问源文档的URI。
答案 1 :(得分:0)
由于将URL参数传递给XSL似乎不切实际,我通过AJAX找到了另一种方法。 Javascript导入XML和XSL文件,然后过滤XML文件,以便只剩下一个元素,然后将XSL文件应用于剩余的XML结构。
对于那些寻求类似问题灵感的人,我将留下我正在使用的代码的简化示例。这个代码需要jQuery,但它可以完美地运行。
page.js(从here无耻地复制):
function expand_box(id, tag_to_isolate, XML_file, XSL_file, container) {
if($('div#' + id).length == 0) { //first opening
var XML = $.ajax({url: XML_file, async: false, dataType: 'xml'}).responseXML.activeElement;
var XSL = $.ajax({url: XSL_file, async: false, dataType: 'xml'}).responseXML.activeElement;
if(XSL.getElementsByTagName('xsl:include').length == 1) { //bonus, see below*
var XSL_temp = $.ajax({url: 'templates.xsl', async: false, dataType: 'xml'}).responseXML.activeElement;
$(XSL.getElementsByTagName('xsl:include')).replaceWith(XSL_temp.childNodes);
}
XML = $(XML).find(tag_to_isolate + '[id=' + id + ']')[0];
if (window.ActiveXObject) { // code for IE
var result = XML.transformNode(XSL);
}
else if (document.implementation && document.implementation.createDocument) { // code for Chrome, Firefox, Opera, etc.
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(XSL);
var result = xsltProcessor.transformToFragment(XML, document);
}
$('div#' + panel).append(result);
//other code here, e.g. to apply all jQuery functions bound to clicks, ...
}
$('#' + id).slideDown();
}
*奖励:我发现javascript xsltProcessor无法处理xsl:include
标签,因此我必须手动导入它们。这里的代码非常简单,因为我只使用一个xsl文件来包含所有共享模板,因此替换是自动的,但它可以很容易地适应更灵活。
database.xml(与上面显示的XML文件不同):
<?xml version="1.0" encoding="UTF-8"?>
<elements>
<element id="1">
...
</element>
...
</elements>
transform.xsl:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xsl:template match="/elements/element">
...
</xsl:template>
<xsl:include href="templates.xsl" />
</xsl:stylesheet>
根据使用的数据库,您可以根据需要创建任意数量的匹配项。
我不得不说我的浏览器警告我主线程上的同步AJAX请求因为对用户的负面影响而被弃用,并且可能在将来被禁用,所以答案可能会得到改善,但我选择了目的为了获得同步请求,因为我的计算机上发生了一切,无论文件有多大,请求都很快。在远程服务器上,需要异步请求。