转换XML与多个XSL文件(Transform XML with multiple XSL file

2019-08-02 23:38发布

我有一些XML,我想用一些XSL文件转换为HTML。 这些XSL文件通过XSL所有相关:import和xsl:include语句,并完成转换所需的所有。

我知道XSL的作品,因为使用<?xml-stylesheet type="text/xsl" href="transform.xsl"?>指令由浏览器中打开一个预先创建的XML文件显示了我想要的输出。 问题是,我希望能够在动态生成的XML复制此功能。

有两种方法,我可以看到,这都不可能做到,但两者似乎有一个,我一直没能解决的限制。

第一个方案是使用JavaScript来转换XML。 从我可以告诉,这将需要XSLTProcessor中对象加载多个XSL文件,但Chrome浏览器(可能其他浏览器)不支持XSL:进口很好- http://code.google.com/p/chromium/问题/细节?ID = 8441

我还研究了写入XML到的iFrame或新窗口,但<?xml-stylesheet type="text/xsl" href="transform.xsl"?>指令是在所得到的窗口注释。 其实写东西到一个新的窗口是HTML无论如何 - 我还没有找到一个方式来写XML到一个新窗口。

所以,我怎么能得到一个浏览器窗口中显示了一组XSL文件转换的XML文件的结果呢?

UPDATE

因此,这里是我的研究成果了这个问题。

可能的解决方法 :使用emscripten编译像xsltproc的工具转换为JavaScript。 其实我已经做到了这一点-看到https://github.com/mcasperson/xsltproc.js

问题 :它是在Firefox(什么需要5秒的Chrome 30+需要在Firefox)令人难以置信的速度慢,无法运行在Chrome Web工作的代码- https://code.google.com/p/chromium/问题/细节?ID = 252492

可能的解决方法 :在所有不使用XSL,但使用CSS样式表显示XML。

问题 :直到浏览器开始实施css attr(atrributename, url)功能,有没有办法来治疗的XML属性作为不是一个字符串,这使得它无法显示图像的任何其他文件引用。

可能的解决方法 :合并所有XSL文件合并为一个样式表

问题 :这在某种程度上可能(见合并多个XSLT样式表 ),但XSL:import和xsl:包括具有不跨越携带时只需在一个地方的xsl代以文件的内容特定的语义:进口或XSL:include语句。 在过去的多个文件打散大XSL转换,该解决方案将需要大量的手工工作。

可能的解决方法 :写出XML的内容到iframe或新窗口。

问题 :这是不可能写XML到一个新窗口或iframe。 写入到这些元素的内容总是假设为HTML,并插入到HTML的“BODY元素。

可能的解决方法 :创建一个服务器端的服务,它的XML,然后返回与XSL样式表指令,XML。 然后,服务URL可以被用作一个src为的iframe或新窗口属性。

问题 :服务必须是一个GET终点,这意味着要返回都必须包括一个查询参数,这意味着你最终会遇到问题与URL的长度的XML。

可能的解决方法 :使用JavaScript库的XSL像Saxonica CE 。

问题 :这实际上可能工作(我还没有尝试过),但Saxonica CE是不开源的(这是我们项目的要求)。

Answer 1:

如果你想要一个浏览器唯一的解决办法,我会做这样的:

静态XML

使包含只调用了xsl一个简单的静态XML。 这是在浏览器中打开XML - 永远。 这个XML文件可能包含属性设置来控制流量或者什么都没有为这个例子。

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="cartoon2html.xsl"?>
<xml/>

动态纯XML

产生在使用定义的名称自己喜欢的方式动态XML - 在我的情况cartoons.xml。

<?xml version="1.0" encoding="utf-8"?>
<cartoons>
    <cartoon name="Donald Duck" publisher="Walt Disney" />
    <cartoon name="Mickey Mouse" publisher="Walt Disney" />
    <cartoon name="Batman" publisher="DC Comics" />
    <cartoon name="Superman" publisher="DC Comics" />
    <cartoon name="Iron Man" publisher="Marvel Comics" />
    <cartoon name="Spider-Man" publisher="Marvel Comics" />
</cartoons>

XSLT处理文档负载

使用在XSLT文档贷款基准生成的动态XML。 通过在第一选择使用应用模板按计划所有其他模板会工作。

采取在顶部和在代码中的变量引用的进一步回落密切关注。 这是执行的魔力。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:variable name="cartoons" select="document('cartoons.xml')/cartoons" />

    <xsl:template match="/">
        <html>
            <head>
                <title>Cartoons</title>
                <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
            </head>
            <body>
                <xsl:apply-templates select="$cartoons" />
            </body>
        </html>
    </xsl:template>

    <xsl:template match="cartoons">
        <table>
            <xsl:apply-templates />
        </table>
    </xsl:template>

    <xsl:template match="cartoon">
        <tr>
            <td><xsl:value-of select="@name" /></td>
            <td><xsl:value-of select="@publisher" /></td>
        </tr>
    </xsl:template>

</xsl:stylesheet>

你可以将这三个文件保存到选定的目录,并在Firefox打开静态XML文件。 (Chrome和Safari浏览器也许必须有文件通过Web服务器提供执行转换)。



Answer 2:

我会建议使用jQuery导入和样式的XML。

像这样将允许您导入XML每当一个函数被调用(链接到一个按键或刷新按钮,甚至连计时器的功能。)

$.ajax({
    type: "GET",
    url: "FILENAME.xml",
    dataType: "xml",
    success: function(xml) {
        $(xml).find('site').each(function(){ //finds parent node
            var id = $(this).attr('id'); //id of parent node
            var title= $(this).find('title').text();  //finds title node within parent node
            var url = $(this).find('url').text(); //finds URL node within parent node
            var description = $(this).find('descr').text(); //etc...
            var img = $(this).find('img').text(); //etc...

            // Creates div with id of parent node (for individual styling)
            $('<div id="link_'+id+'">')
                .addClass('add a div class')
            //sets css of div
                .css({set css})
            // Sets the inner HTML of this XML allocated div to hyperlinked 'title' with 'description' and an 'img'
                .html('<a href="'+url+'">'+title+'</a>'+description+'<img src="'+img+'">')                  
            // Append the newly created element to body
                .appendTo('#holder');
    }
    }
})

而XML会是这个样子:

<site id="0">
 <url>http://blah.com</url>
 <img>imgs/image1.png</img>
 <description>this is a description</description>
 <title>Title</title>
</site>

<site id="1">
 <url>http://filler.com</url>
 <img>imgs/image2.jpg</img>
 <description>this is another description</description>
 <title>Title 2</title>
</site>

当然,而不是导入到一个div你可以导入XML到一个表或任何其他类型的HTML元素。



Answer 3:

刚才我有同样的问题。 我的解决办法是传播包括直接进入XML。 这个代码是根据浏览器,Firefox和IE 10,9,8和7测试。

function propegateIncludes(dname,xml, isExplorer) {
    var preTag = isExplorer ? "xsl:" : "";

    var TAG_STYLESHEET = preTag + "stylesheet", TAG_INCLUDE = preTag
        + "include", TAG_TEMPLATE = preTag + "template";

    var stylesheets = xml.getElementsByTagName(TAG_STYLESHEET);
    if (stylesheets.length == 0) {
        return;
    }

    var includes = xml.getElementsByTagName(TAG_INCLUDE);
    if (includes.length == 0) {
        return;
    }

    var stylesheet = stylesheets[0];
    var path = dname.substring(0, dname.lastIndexOf('/'));

    for ( var i = 0; i < includes.length; i++) {
        var args = includes[i].attributes;
        var includeXml = null;

        for ( var a = 0; a < args.length; a++) {
            if (args[a].nodeName == "href") {
                includeXml = loadXMLDoc(path + "/" + args[a].nodeValue);
                break;
            }
        }

        stylesheet.removeChild(includes[i]);

        if (includeXml != null) {
            var templates = includeXml.getElementsByTagName(TAG_TEMPLATE);

            for (var t = 0; t < templates.length; ++t) {
                stylesheet.appendChild(templates[t].cloneNode(true));
            }
        }
    }
}


文章来源: Transform XML with multiple XSL files