【问题标题】:Adding javascript to a XML file transformed with XSLT using a Greasemonkey script使用 Greasemonkey 脚本将 javascript 添加到使用 XSLT 转换的 XML 文件中
【发布时间】:2013-08-04 18:31:22
【问题描述】:

在这里跟进我的问题 - How to transform an XML file with XSLT, using a Greasemonkey script? - 我面临另一个问题:

我想在我的 XSL 模板中使用一些基本的 javascript 函数来控制某些 div 的显示。但是,无论我如何包含这些 javascript 函数,它们似乎都无法被识别。我已经调查了很多,但我似乎无法绕过它。

我尝试了两件事:

  • 在 XSL 模板中的 <script> 标记中添加 javascript
  • 在 Greasemonkey 脚本本身中附加一个新的 <script> 标记

我不希望使用 jQuery 或外部 JS 文件(我也尝试过)以使其尽可能简单,但如果这能解决问题,我愿意改变整个事情!

无论哪种情况,当我调用该函数时,我都会得到一个ReferenceError: x is not defined。我确实看到 javascript 代码很好地位于最终的 HTML 结果中。当我使用 Firebug 附加一个新的<script> 标记时,它具有一个简单的功能,可以将“你好”警告到一个普通的 html 页面,那么它就可以完美地工作了。只有在 XSLT 转换之上完成此操作时才会出现问题(为了简单起见,我只是使用一个简单的函数来显示一个警告框)。

这是我的示例数据:

  <?xml version="1.0" encoding="utf-8"?>
  <Results>
      <Result>
          <Listings total="2">
              <Res>
                  <Result index="0">
                      <id>123456</id>
                      <name>My Business</name>
                      <category>Restaurants</category>
                      <phone>9872365</phone>
                  </Result>
              </Res>
              <Res>
                  <Result index="1">
                      <id>876553</id>
                      <name>Some Other Business</name>
                      <category>Restaurants</category>
                      <phone>9834756</phone>
                  </Result>
              </Res>
          </Listings>
      </Result>
  </Results>

这是我刚刚在&lt;head&gt; 标签中添加&lt;script&gt; 标签的第一次尝试:

// ==UserScript==
// @name        _Test XML Renderer
// @description stylesheet for xml results
// @include     *
// @grant       none
// ==/UserScript==

var xsl_str = '<?xml version="1.0" encoding="utf-8"?>\n\
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">\n\
    <xsl:output method="html"/>\n\
    <xsl:template match="/">\n\
        <html>\n\
            <head><script type="text/javascript">function hello() {alert("hello")};</script></head>\n\
            <body>\n\
                <table id="results" border="1" cellspacing="0" cellpadding="0">\n\
                    <thead>\n\
                        <tr>\n\
                            <th class="name">id</th>\n\
                            <th class="name">category ID</th>\n\
                            <th class="name">name</th>\n\
                            <th class="name">phone</th>\n\
                        </tr>\n\
                    </thead>\n\
                    <tbody>\n\
                        <xsl:for-each select="Results/Result/Listings/Res">\n\
                            <tr>\n\
                                <td class="small" width="120">\n\
                                    <a href="#" onclick="hello()"><xsl:value-of select="Result/id"/></a>\n\
                                </td>\n\
                                <td class="small" width="120">\n\
                                    <xsl:value-of select="Result/category"/>\n\
                                </td>\n\
                                <td class="small" width="120">\n\
                                    <xsl:value-of select="Result/name"/>\n\
                                </td>\n\
                                <td class="small" width="120">\n\
                                    <xsl:value-of select="Result/phone"/>\n\
                                </td>\n\
                            </tr>\n\
                        </xsl:for-each>\n\
                    </tbody>\n\
                </table>\n\
            </body>\n\
        </html>\n\
    </xsl:template>\n\
</xsl:stylesheet>\n\
';

var processor   = new XSLTProcessor ();
var dataXSL     = new DOMParser ().parseFromString (xsl_str, "text/xml");

processor.importStylesheet (dataXSL);

var newDoc      = processor.transformToDocument (document);

//-- These next lines swap the new, processed doc in for the old one...
window.content  = newDoc;

document.replaceChild (
    document.importNode (newDoc.documentElement, true),
    document.documentElement
);

这是我在 XSL 模板之外添加“hello”函数的另一个尝试:

// ==UserScript==
// @name        _Test XML Renderer
// @description stylesheet for xml results
// @include     *
// @grant       none
// ==/UserScript==

var xsl_str = '<?xml version="1.0" encoding="utf-8"?>\n\
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">\n\
    <xsl:output method="html"/>\n\
    <xsl:template match="/">\n\
        <html>\n\
            <head></head>\n\
            <body>\n\
                <table id="results" border="1" cellspacing="0" cellpadding="0">\n\
                    <thead>\n\
                        <tr>\n\
                            <th class="name">id</th>\n\
                            <th class="name">category ID</th>\n\
                            <th class="name">name</th>\n\
                            <th class="name">phone</th>\n\
                        </tr>\n\
                    </thead>\n\
                    <tbody>\n\
                        <xsl:for-each select="Results/Result/Listings/Res">\n\
                            <tr>\n\
                                <td class="small" width="120">\n\
                                    <a href="#" onclick="hello()"><xsl:value-of select="Result/id"/></a>\n\
                                </td>\n\
                                <td class="small" width="120">\n\
                                    <xsl:value-of select="Result/category"/>\n\
                                </td>\n\
                                <td class="small" width="120">\n\
                                    <xsl:value-of select="Result/name"/>\n\
                                </td>\n\
                                <td class="small" width="120">\n\
                                    <xsl:value-of select="Result/phone"/>\n\
                                </td>\n\
                            </tr>\n\
                        </xsl:for-each>\n\
                    </tbody>\n\
                </table>\n\
            </body>\n\
        </html>\n\
    </xsl:template>\n\
</xsl:stylesheet>\n\
';

var processor   = new XSLTProcessor ();
var dataXSL     = new DOMParser ().parseFromString (xsl_str, "text/xml");

processor.importStylesheet (dataXSL);

var newDoc      = processor.transformToDocument (document);

var script = "function hello() {alert('hello')};";
var newElem = newDoc.createElement('script');
newElem.type = 'text/javascript';
newElem.appendChild(newDoc.createTextNode(script));
newDoc.getElementsByTagName('head').item(0).appendChild(newElem);

//-- These next lines swap the new, processed doc in for the old one...
window.content  = newDoc;

document.replaceChild (
    document.importNode (newDoc.documentElement, true),
    document.documentElement
);

【问题讨论】:

    标签: javascript xml xslt greasemonkey


    【解决方案1】:

    Don't use onclick。这对于用户脚本来说是三倍,因为存在额外的范围和/或沙盒冲突。

    另外,尝试将JS添加到XSLT文件/文本中是一个糟糕的主意,在这种情况下也不需要脚本注入。

    使用脚本来做任何你想到的 JS 操作。例如:

    // ==UserScript==
    // @name        _XML Renderer with javascript functionality
    // @description Stylesheet and javascript for xml results
    // @include     http://YOUR_SERVER.COM/YOUR_PATH/*.xml
    // @resource    xslFile  Q_17998446_transform.xsl
    // @grant       GM_getResourceText
    // ==/UserScript==
    
    var xsl_str     = GM_getResourceText ("xslFile");
    var processor   = new XSLTProcessor ();
    var dataXSL     = new DOMParser ().parseFromString (xsl_str, "text/xml");
    
    processor.importStylesheet (dataXSL);
    
    var newDoc      = processor.transformToDocument (document);
    
    //-- These next lines swap the new, processed doc in for the old one...
    window.content  = newDoc;
    
    document.replaceChild (
        document.importNode (newDoc.documentElement, true),
        document.documentElement
    );
    
    //-- Use JS to smarten-up the new document.
    var firstCols   = document.querySelectorAll ("#results td:first-child");
    
    for (var J = firstCols.length - 1;  J >= 0;  --J) {
        var tdNode = firstCols[J];
        tdNode.style.cursor = "pointer";
        tdNode.addEventListener ("click", clickCellHandler, false);
    }
    
    function clickCellHandler (zEvent) {
        var cellContents = zEvent.target.textContent.trim ();
    
        alert ('The clicked cell contains "' + cellContents + '".');
    }
    

    其中Q_17998446_transform.xsl 是保存在您安装脚本的同一文件夹中的文件(您可能需要卸载并重新安装脚本)。

    Q_17998446_transform.xsl 包含这个,确切地说:

    <?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:template match="/">
            <html>
                <head></head>
                <body>
                    <table id="results" border="1" cellspacing="0" cellpadding="0">
                        <thead>
                            <tr>
                                <th class="name">id</th>
                                <th class="name">category ID</th>
                                <th class="name">name</th>
                                <th class="name">phone</th>
                            </tr>
                        </thead>
                        <tbody>
                            <xsl:for-each select="Results/Result/Listings/Res">
                                <tr>
                                    <td class="small" width="120">
                                        <xsl:value-of select="Result/id"/>
                                    </td>
                                    <td class="small" width="120">
                                        <xsl:value-of select="Result/category"/>
                                    </td>
                                    <td class="small" width="120">
                                        <xsl:value-of select="Result/name"/>
                                    </td>
                                    <td class="small" width="120">
                                        <xsl:value-of select="Result/phone"/>
                                    </td>
                                </tr>
                            </xsl:for-each>
                        </tbody>
                    </table>
                </body>
            </html>
        </xsl:template>
    </xsl:stylesheet>
    


    当您在适当的 XML 文件上运行该脚本时,它会向第一个表列(无标题)添加一个点击处理程序——“Web 2.0”方式。

    当单击第一列单元格中的一个时,它会发出警报,例如:

    点击的单元格包含“876553”。

    【讨论】:

    • 太好了,再次感谢您的帮助!感谢您向我介绍事件处理程序的世界,它们工作得很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 1970-01-01
    相关资源
    最近更新 更多