如何将参数从Javascript函数传递到XSLT

How to pass parameter to XSLT from Javascript function

本文关键字:XSLT 函数 Javascript 参数      更新时间:2023-09-26

我浏览了许多帖子,试图解释如何实现这一点,但没有一篇能帮助我解决问题。

我有一个HTML文件,其中包含一个XML解析JavaScript函数,该函数反过来呈现XSLT文件。问题是,我的XML文件中有多个"记录",我只想用一个XSLT来呈现每个记录(而不是每个记录都有一个单独的XSLT文件)。根据下面的代码,请有人建议我如何从JavaScript传递包含记录id的参数(在我的XML文件中的每个XML记录中),以便"单个"XSLT可以使用来自该参数的正确数据解析布局。

HTML

<!DOCTYPE html>
    <html lang="en">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no" />
      <title>Weather App</title>
      <link href="../../css/materialize.css" type="text/css" rel="stylesheet" media="screen,projection" />
      <link href="../../css/animate.css" type="text/css" rel="stylesheet" />
      <link href="../../css/style.css" type="text/css" rel="stylesheet" media="screen,projection" />
    </head>
    <body>
      <div id="WeatherDetailsContainer"></div>
      <!--  Scripts-->
      <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
      <script src="../../js/materialize.js"></script>
      <script>
        $(function(){
          RenderXSLT();
        });
        function loadXMLDoc(filename) {
          if (window.ActiveXObject) {
            xhttp = new ActiveXObject("Msxml2.XMLHTTP");
          } else {
            xhttp = new XMLHttpRequest();
          }
          xhttp.open("GET", filename, false);
          try {
            xhttp.responseType = "msxml-document"
          } catch (err) {} // Helping IE11
          xhttp.send("");
          return xhttp.responseXML;
        }
        function RenderXSLT() {
          xml = loadXMLDoc("datastore/Weather.xml");
          xslt = loadXMLDoc("transformations/WeatherDetailsCard.xslt");
          var currentLocation = localStorage.getItem('current_weather_location');
          if (window.ActiveXObject || xhttp.responseType == "msxml-document") {
            ex = xml.transformNode(xslt);
            document.getElementById("WeatherDetailsContainer").innerHTML = ex;
          }
          else if (document.implementation && document.implementation.createDocument) {
            xsltProcessor = new XSLTProcessor();
            xsltProcessor.importStylesheet(xslt);
            /** I believe this is how to set the param, but it didn't work **/
            //xsltProcessor.setParameter(null, "cityname", currentLocation);
            resultDocument = xsltProcessor.transformToFragment(xml, document);
            document.getElementById("WeatherDetailsContainer").appendChild(resultDocument);
          }
        }
      </script>
    </body>
    </html>

XML文件

<?xml version="1.0" encoding="UTF-8" ?>
<locations>
  <location>
    <cityid>Lon</cityid>
    <cityname>London</cityname>
    <temperature>11</temperature>
    <high>13</high>
    <low>4</low>
    <date>17/03/2015</date>
  </location>
  <location>
    <cityid>Man</cityid>
    <cityname>Manchester</cityname>
    <temperature>07</temperature>
    <high>08</high>
    <low>2</low>
    <date>17/03/2015</date>
  </location>
  <location>
    <cityid>Gla</cityid>
    <cityname>Glasgow</cityname>
    <temperature>05</temperature>
    <high>06</high>
    <low>1</low>
    <date>17/03/2015</date>
  </location>
</locations>

XSLT文件

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
    <!-- How do I use the value of the parameter sent via JavaScript for the cityname (in place of value 'London') -->
    <xsl:for-each select="locations/location[cityname='London']">
      <div class="section">
        <div class="container">
          <div class="row">
            <div class="col s4 m4 l4">
              <div class="card-panel z-depth-3 animated fadeInUp" style="padding:10px 10px 5px 10px !important;">
                <span class="center-align">
                  <h5><xsl:value-of select="cityname"/></h5><span> (<xsl:value-of select="cityid"/>)</span>
                </span>
                <p>Temp: <xsl:value-of select="temperature"/></p>
                <p>High: <xsl:value-of select="high"/></p>
                <p>Low: <xsl:value-of select="low"/></p>                
              </div>
            </div>
          </div>
        </div>
      </div>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

在XSLT中,您需要更改

<xsl:template match="/">
    <!-- How do I use the value of the parameter sent via JavaScript for the cityname (in place of value 'London') -->
    <xsl:for-each select="locations/location[cityname='London']">

<xsl:param name="cityname"/>
<xsl:template match="/">
    <!-- How do I use the value of the parameter sent via JavaScript for the cityname (in place of value 'London') -->
    <xsl:for-each select="locations/location[cityname = $cityname]">

我还将设置<xsl:output method="html"/>,因为您只创建HTML的一个片段,如果您不设置输出方法,XSLT处理器就不知道这一点。

在您的Mozilla、Chrome、Opera的Javascript代码中,我会更改检查

      else if (document.implementation && document.implementation.createDocument) {
        xsltProcessor = new XSLTProcessor();
        xsltProcessor.importStylesheet(xslt);
        /** I believe this is how to set the param, but it didn't work **/
        //xsltProcessor.setParameter(null, "cityname", currentLocation);
        resultDocument = xsltProcessor.transformToFragment(xml, document);
        document.getElementById("WeatherDetailsContainer").appendChild(resultDocument);
      }

      else if (typeof XSLTProcessor !== 'undefined') {
        var xsltProcessor = new XSLTProcessor();
        xsltProcessor.importStylesheet(xslt);

        xsltProcessor.setParameter(null, "cityname", currentLocation);
        var resultFragment = xsltProcessor.transformToFragment(xml, document);
        document.getElementById("WeatherDetailsContainer").appendChild(resultFragment);
      }

您的transformNode IE代码不允许设置参数,您还需要更改该部分,更改

      if (window.ActiveXObject || xhttp.responseType == "msxml-document") {
        ex = xml.transformNode(xslt);
        document.getElementById("WeatherDetailsContainer").innerHTML = ex;
      }

      if (window.ActiveXObject || xhttp.responseType == "msxml-document") {
        var template = new ActiveXObject('Msxml2.XslTemplate');
        template.stylesheet = xslt;
        var proc = template.createProcessor();
        proc.input = xml;
        proc.addParameter('cityname', currentLocation);
        proc.transform();
        document.getElementById("WeatherDetailsContainer").innerHTML = proc.output;
      }

看起来您的Javascript中有正确的代码来传递参数,但您的XSLT也必须编写为接受参数:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- Declare it here -->
  <xsl:param name="cityName" />
  <xsl:template match="/">
    <!--                                 use it here ------v   -->
    <xsl:for-each select="locations/location[cityname = $cityName]">
      ...
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>