代码之家  ›  专栏  ›  技术社区  ›  Gurwinder Singh

xslt文档函数在chrome中不起作用

  •  13
  • Gurwinder Singh  · 技术社区  · 6 年前

    我正在尝试使用javascript转换xslt,并尝试让它同时在chrome和ie上工作。 a.html . 它在IE(本地/兼容模式)中运行良好,但在Chrome中运行不正确,即下拉菜单不是用选项创建的。

    但是,如果我打开 data.xml 它有:

    <?xml-stylesheet type="text/xsl" href="render.xslt" ?>
    

    直接在铬中,它被完美地转化。但是,如果我尝试使用xsltprocessor执行同样的操作,它就不起作用。具体来说, document 功能不起作用。你能帮忙吗?

    我的代码如下。

    Javascript:

    var MSXML2_DOMDocument_6 = "MSXML2.DOMDocument.6.0";
    function tranform(xml, xsl) {
        if (window.ActiveXObject || "ActiveXObject" in window) {
            var xmlSerializer = new XMLSerializer();
            var xmlString = xmlSerializer.serializeToString(xml);
            var xslString = xmlSerializer.serializeToString(xsl);
    
            var xsl = new ActiveXObject(MSXML2_DOMDocument_6);
            xsl.setProperty("AllowXsltScript", true);
            xsl.setProperty("AllowDocumentFunction", true);
            xsl.resolveExternals = true;
            xsl.async = false;
            xsl.loadXML(xslString);
    
            var xml = new ActiveXObject(MSXML2_DOMDocument_6);
            xml.resolveExternals = true;
            xml.preserveWhiteSpace = true;
            xml.async = false;
            xml.loadXML(xmlString);
            xml.resolveExternals = true;
    
            ex = xml.transformNode(xsl);
            document.getElementById("example").innerHTML = ex;
        } else if (document.implementation && document.implementation.createDocument) {
            xsltProcessor = new XSLTProcessor();
            xsltProcessor.importStylesheet(xsl);
            resultDocument = xsltProcessor.transformToFragment(xml, document);
            document.getElementById("example").appendChild(resultDocument);
        }
    }
    
    function loadXMLDoc() {
    
        $.ajax({
            method: "GET",
            url: "data.xml",
            dataType: "xml"
        }).then(function (xml) {
                console.log("done xml")
                $.ajax({
                    method: "GET",
                    url: "render.xslt",
                    dataType: "xml"
                }).then(function (xsl) {
                    console.log("done xsl")
                    tranform(xml, xsl)
                })
            },
            function (e) {
                console.log("Got error in xml", e.status)
            })
    }
    
    $(loadXMLDoc)
    

    FoO/B.XML:

    <dropdowns>
      <dropdown name="xyz">
        <option value="I">Info</option>
        <option value="C">Category</option>
      </dropdown>
    </dropdowns>
    

    数据XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet type="text/xsl" href="render.xslt" ?>
    <catalog name="xyz" />
    

    A.HTML:

    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <script src="jquery-3.3.1.js"></script>
        <title>Document</title>
    </head>
    
    <body>
        <div id="example"></div>
        <script src="b.js"></script>
    </body>
    
    </html>
    

    小精灵:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:import href="util.xslt" />
        <xsl:output method="html"></xsl:output>
        <xsl:template match="/">
            <h1>
                <xsl:value-of select="/catalog/@name"></xsl:value-of>
            </h1>
            <xsl:call-template name="dropdown">
                <xsl:with-param name="listname">xyz</xsl:with-param>
                <xsl:with-param name="value" select="/catalog/@name"/>
            </xsl:call-template>
        </xsl:template>
    </xsl:stylesheet>
    

    UTX.XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output method="html"></xsl:output>
        <xsl:template name="dropdown">
            <xsl:param name="listname"/>
            <xsl:param name="value"/>
            <select>
                <xsl:for-each select="document('foo/b.xml')/dropdowns/dropdown[@name=$listname]/option">
                    <option>
                        <xsl:attribute name="value">
                            <xsl:value-of select="@value"/>
                        </xsl:attribute>
                        <xsl:value-of select="."/>
                    </option>
                </xsl:for-each>
            </select>
        </xsl:template>
    </xsl:stylesheet>
    

    很抱歉,作为一个mve的例子有点长,但它是完整的。

    如果需要澄清,请告诉我。

    3 回复  |  直到 6 年前
        1
  •  0
  •   David user10336229    6 年前

    一般来说,整个方法都是关于嵌套模板的。
    这里已经回答了: How to traverse a nested XML structure using templates

    以下仍然是一些问题以及对问题下方评论的澄清。

    调整了发送文件的本地服务器 util.xslt 作为内容类型 text/css 就像chrome所期望的那样 application/xslt+xml ,脚本仍然无法正常工作。因此,一定还有另一个与chrome相关的问题。

    enter image description here

    有趣的是,有两个xslt文档,其中一个被chrome通过 应用程序/xslt+xml 但另一个只是 text/xml text/xsl (是的,两个都被chrome接受,我试过了)。

    因此,一个 interesting post about versions of xml / xslt 可能对这个问题没用。

    以下是控制台消息的详细信息:

    enter image description here

    服务器的调整已通过以下行完成,这将更改 Content-Type (mime类型)如果请求的文件名有后缀 xslt 预期的mime类型是 文本/ CSS :

    <If "%{REQUEST_FILENAME} =~ m#\.xslt$# && %{HTTP:Accept} =~ m#^text\/css#">
        Header set "Content-Type" "text/css"
    </If>
    

    火狐

    值得注意的是,firefox正在隐藏 利用XSLT 在网络面板中:

    enter image description here

    此外,firefox接受两种方法,activexobject和xsltprocessor。根据javascript中的逻辑,默认设置为activexobject,对于下拉列表的动画,该版本看起来也更平滑。

    当xml版本设置为1.1时,firefox正在抱怨,因此使用 版本号可能并不能真正帮助提高浏览器的兼容性。

        2
  •  0
  •   Sandeep Saroha    6 年前

    这是已知的问题,并从2009年开放。此外,chrome团队也没有任何计划来修复它,他们正在计划从chrome中删除它的支持(不确定何时)。但有一个办法可以解决这个问题。将xml数据转换为xslt,然后可以将其导入到样式表中。

    所以javascript代码将保持不变。

    foo/b.xml将变成foo/b.xslt

     <?xml version="1.0" encoding="UTF-8"?>
     <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:template name="dropdowns">
        <xsl:param name="listname"/>
        <xsl:param name="value"/>
        <xsl:choose>
            <xsl:when test="$listname='xyz'">
                <xsl:call-template name="option">
                    <xsl:with-param name="value">I</xsl:with-param>
                    <xsl:with-param name="label">Info</xsl:with-param>
                    <xsl:with-param name="selectedValue" select="$value"/>
                </xsl:call-template>
                <xsl:call-template name="option">
                    <xsl:with-param name="value">C</xsl:with-param>
                    <xsl:with-param name="label">Category</xsl:with-param>
                    <xsl:with-param name="selectedValue" select="$value"/>
                </xsl:call-template>
            </xsl:when>
    
        </xsl:choose>
     </xsl:template>
    
     <xsl:template name="option">
        <xsl:param name="label"/>
        <xsl:param name="value"/>
        <xsl:param name="selectedValue"/>
        <option value="{$value}">
            <xsl:if test="$value = $selectedValue">
                <xsl:attribute name="selected">selected</xsl:attribute>
            </xsl:if>
            <xsl:value-of select="$label"/>
        </option>
    </xsl:template>
    </xsl:stylesheet>
    

    UTX.XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:import href="foo/b.xslt" />
    <xsl:output method="html" />
    
    <xsl:template name="dropdown">
        <xsl:param name="listname"/>
        <xsl:param name="value"/>
        <select>
            <xsl:call-template name="dropdowns">
                <xsl:with-param name="listname" select="$listname"/>
                <xsl:with-param name="value" select="$value"/>
            </xsl:call-template>
        </select>
    </xsl:template>
    </xsl:stylesheet>
    

    Relord.XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:import href="util.xslt" />
    <xsl:output method="html"></xsl:output>
    <xsl:template match="/">
        <h1>
            <xsl:value-of select="/catalog/@name"></xsl:value-of>
        </h1>
        <xsl:call-template name="dropdown">
            <xsl:with-param name="listname">xyz</xsl:with-param>
            <xsl:with-param name="value">C</xsl:with-param>
        </xsl:call-template>
    </xsl:template>
    </xsl:stylesheet>
    

    通过这些更改,您可以在您的网页中创建下拉菜单,这将在IE和Chrome中工作。

        3
  •  0
  •   Gurwinder Singh    6 年前

    我找到了一个解决办法 〔1〕 为了这个问题。

    在铬合金中, <xsl:import> 在javascript中转换时工作正常。所以,我将xml转换成xsl <xsl:choose> 具有 <xsl:when> 对于每一个 dropdown 标签。

    更新 util.xslt :

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output method="html"></xsl:output>
        <xsl:template name="dropdown">
            <xsl:param name="listname"/>
            <xsl:param name="value"/>
            <select>
                <xsl:choose>
                    <xsl:when name="$listname='xyz'">
                        <option value="I">Info</option>
                        <option value="C">Category</option>
                    </xsl:when>
                </xsl:choose>
            </select>
        </xsl:template>
    </xsl:stylesheet>
    

    1。我同意这不是一个很好的解决办法,当然也不是一个普遍的解决办法。如果有人有更好的解决方案,请将其作为答案发布。