从 XML/XSL 中提取 URL 参数



我正在编写一个应用程序来可视化几个数据库的内容。此应用程序应尽可能易于安装和使用,因此我决定使用 XML 文件作为数据库,并通过浏览器使用 XSL 充分转换它们。现在,XSL文件被编程为每个数据库的摘要表,并且通过单击每行的第一个单元格,将显示整个条目的更完整的描述。这意味着页面包含数据库中每条记录的所有完整描述,但这种情况会减慢页面的加载速度,加载几百条记录最多需要 5 秒。由于我计划将来扩展数据库很多,因此这个问题注定会变得更糟。为了减少负载,下一个明显的步骤是诉诸某种延迟加载,通过使用 AJAX 或 iframe(现在哪一个并不重要,也不是问题的重点(,但我遇到了一些困难。我的想法是直接调用这样的XML文件:

file:///path/to/file/transform.xml?id=23

通过转换.xml是:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="transform.xsl"?>
<content />

并且转换.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解决方案是完全可以接受的,因为它是客户端的。

编辑:我的大部分工作都是基于这个问题,这个问题似乎有效,但很旧,并且该示例包含ASP页面的URL。

使用 xml 样式表处理指令调用转换不提供任何向转换提供参数的方法。因此,该参数将采用其默认值,即零长度字符串。

抱歉,此设计不会飞。

我认为做到这一点的唯一方法是在 HTML 页面中使用以编程方式调用转换的 Javascript 代码。

一种选择是使用 Saxon-JS,而不是依赖浏览器提供的 XSLT 引擎。这将使您能够访问 XSLT 2.0/3.0 功能,而不仅仅是 1.0,并且在 2.0 中,样式表可以使用 document-uri(( 函数访问源文档的 URI。

由于将 URL 参数传递给 XSL 似乎不切实际,我通过 AJAX 找到了另一种方法。Javascript 导入 XML 和 XSL 文件,然后过滤 XML 文件,以便只保留一个元素,然后将 XSL 文件应用于其余的 XML 结构。

对于任何寻求类似问题灵感的人,我将留下我正在使用的代码的简化示例。 jQuery是这段代码所必需的,但它可以在没有的情况下完美地工作。

页面.js(从这里无耻地复制(:

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 文件来包含所有共享模板,因此替换是自动的,但可以很容易地进行调整以使其更加灵活。

数据库.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 请求由于对用户的负面影响而被弃用,并且将来可能会被禁用,因此答案可能会有所改进,但我故意选择同步请求,因为一切都发生在我的计算机上,无论文件有多大,请求都很快。在远程服务器上,异步请求是必需的。

最新更新