XML转换为HTML文档(XSL)

时间:2015-05-18 23:03:03

标签: javascript html xml xslt

我似乎无法使用XSL将XML数据传输到HTML网页。它是一个大学项目,因此没有使用其他技术。

XML结构很简单 - 例如

<dust2>
  <team>
    <player>
      <name>Xizt</name>
      <team>NiP</team>
      <kills>19</kills>
      <deaths>16</deaths>
      <assists>0</assists>
      <kdr>0.19</kdr>
    </player>
  </team>
</dust2>

真实文档包含2个<team>个标记,每个标记在每个小组中有5个<player>。根据我的知识,XML标签都已关闭并正确声明。

讲师为我们提供了这个script.js文件,其中包含用于XML加载,解析和转换的函数:

// HTTP Request
function loadXML (file) {
    if (window.XMLHttpRequest) {
        // code for Chrome, Firefox, Opera, etc.
        xhttp = new XMLHttpRequest();
    } else {
        // code for IE
        xhttp = new ActiveXObject("Microsoft.XMLHTTP"); // Different ActiveXObject for IE
    };
    xhttp.open("GET", file, false);
    try {xhttp.responseType = "msxml-document";} catch (e) {}; // Set responseType for IE 9+
    xhttp.send(null);
    return xhttp.responseXML;
};

// Process & Output
function processXML (location, xml, xsl) {
    if (window.ActiveXObject || xhttp.responseType == "msxml-document" || "ActiveXObject" in window) { // Added criteria for IE detection
        // code for IE
        ex = xml.transformNode(xsl);
        document.getElementById(location).innerHTML = ex;
    } else if (document.implementation && document.implementation.createDocument) {
        // code for Chrome, Firefox, Opera, etc.
        xsltProcessor = new XSLTProcessor();
        xsltProcessor.importStylesheet(xsl);
        resultDocument = xsltProcessor.transformToFragment(xml, document);
        document.getElementById(location).innerHTML = '';
        document.getElementById(location).appendChild(resultDocument);
    };
};

// HTTP Request, Process & Output
function outputXML(location, xmlFile, xslFile) {
    xml = loadXML(xmlFile);
    xsl = loadXML(xslFile);
    processXML(location, xml, xsl);
};

// Parse XML to String
function XMLToString(xml) {
    if (window.ActiveXObject) {
        // code for IE
        var txt = xml.xml;
        return txt;
    } else {
        // code for Chrome, Firefox, Opera, etc.
        var txt = new XMLSerializer();
        txt = txt.serializeToString(xml);
        return txt;
    };
};

// Parse String to XML
function StringToXML(txt) {
    if (window.DOMParser) {
        // code for Chrome, Firefox, Opera, etc.
        parser=new DOMParser();
        xml=parser.parseFromString(txt,"text/xml");
    } else {
        // code for IE
        xml=new ActiveXObject("Microsoft.XMLDOM");
        xml.async=false;
        xml.loadXML(txt); 
    };
    return xml;
};

HTML看起来像这样:

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Dreamhack Winter 2014 Finals</title>

  <!-- JS Transform - Obtained from lecture material -->
  <script type="text/javascript" src="js/script.js"></script>
  <script type="text/javascript">
    function loadxml() {
      outputXML('dust2', 'xml/dust2nons.xml', 'xml/dust2stats.xsl');
    }
  </script>
</head>
<body onload="loadxml();">
  <p><div id="dust2" onload="outputXML('dust2', 'xml/dust2nons.xml', 'xml/dust2stats.xsl');"></div></p>
</body>
</html>

我的XSL文档已经改变了,只能在主页上打印一张XML,但即使使用相同的技术,我也无法实现。我设法让XSL在XSL文件中显示静态html,但没有

<xsl:for-each select="dust2/team/player">

<xsl:value-of select="name"> 
到目前为止

组合。

从那时起,我失去了从XSL文档传输静态HTML的能力。我不确定即使是doctype等也是正确的。

我的XSL文档dust2stats.xsl

<html xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0">
  <body>
    <table>
      <thead>
        <tr>
          <th>Player</th>
          <th>Kills</th>
          <th>Assists</th>
          <th>Deaths</th>
          <th>KDR</th>
        </tr>
      </thead>
      <tbody>
        eggs
        <xsl:for-each select="dust2/team/player">
          <tr>
            <td>
              <xsl:value-of select="name" />
            </td>
            <td>
              <xsl:value-of select="kills" />
            </td>
            <td>
              <xsl:value-of select="assists" />
            </td>
            <td>
              <xsl:value-of select="deaths" />
            </td>
            <td>
              <xsl:value-of select="kdr" />
            </td>
            test1234
          </tr>
        </xsl:for-each>
      </tbody>
    </table>
  </body>
</html>

随机单词是尝试传递静态HTML。我在某个阶段实现了这个目标,但从那时起就已经退步并且已经失去了它。

非常感谢任何形式的指导或建议。 :)

2 个答案:

答案 0 :(得分:0)

首先,您需要正确声明样式表:

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

   [here is your templates]

</xsl:stylesheet>

然后,您需要为转换声明一个根模板:

<xsl:template match="/">
   <html>
      ...
      <tbody>
         <xsl:apply-templates select="dust2/team/player/>
      </tbody>
      ...
   </html>
</xsl:template>

然后你可以为每个玩家声明以下模板:

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

                    <td><xsl:value-of select="kills"/></td>

                    <td><xsl:value-of select="assists"/></td>

                    <td><xsl:value-of select="deaths"/></td>

                    <td><xsl:value-of select="kdr"/></td>
   </tr>
</xsl:template>

不确定浏览器xslt处理器,但通常看起来像这样。

答案 1 :(得分:0)

以下效果非常好(在IE 5 +,Chrome,Firefox中测试过)。

首先,我重写了整个script.js文件,因为坦率地说,它并不是很好。

function loadXml(url) {
    var xhr;
    if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
        try { xhr.responseType = "msxml-document"; } catch (ex) {}
    } else {
        throw new Error("Failed to create XMLHTTP request object.");
    }
    xhr.open("GET", url, false);
    xhr.send();
    return xhr.responseXML;
}

function transformXml(xml, xsl) {
    var xsltProcessor;
    if (typeof xml === "string") xml = stringToXml(xml);
    if (typeof xsl === "string") xsl = stringToXml(xsl);
    if (window.XSLTProcessor) {
        xsltProcessor = new XSLTProcessor();
        xsltProcessor.importStylesheet(xsl);
        return xsltProcessor.transformToFragment(xml, document);
    } else if ("ActiveXObject" in window) {
        return xml.documentElement.transformNode(xsl);
    } else {
        throw new Error("Failed to transform XML.");
    }
}

function xmlToString(input) {
    var str;
    if (window.XMLSerializer) {
        return (new XMLSerializer()).serializeToString(input);
    } else if (input.xml) {
        return input.xml;
    } else {
        throw new Error("Failed to convert input to string.");
    }
    return str;
}

function stringToXml(input) {
    var xml;
    if ("ActiveXObject" in window) {
        xml = new ActiveXObject("Microsoft.XMLDOM");
        xml.async=false;
        xml.loadXML(input);
        return xml;
    } else if (window.DOMParser) {
        return (new DOMParser()).parseFromString(input, "text/xml");
    } else {
        throw new Error("Failed to convert input to XML document.");
    }
}

function setElementContent(element, content) {
    element.innerHTML = '';
    if (content.nodeType) { 
        element.appendChild(content);
    } else {
        element.innerHTML = content;
    }
}

现在我们有了这些功能:

  • loadXml - 从URL同步加载XML文档并将其返回
  • transformXml - 将XML和XSL应用于XML并返回结果
  • xmlToString - 获取XML文档并返回字符串
  • stringToXml - 接受一个字符串并返回一个XML文档
  • setElementContent - 设置元素的内容

接下来,您的XSL语法搞砸了。好吧,从理论上讲它是有效的,但是IE使用的MSXML处理器并不理解这种特殊的格式。它期望XML文档以<xsl:stylesheet><xsl:transform>开头。

所以我们正在使用它:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <output method="html" />
  <xsl:template match="/dust2">
    <xsl:for-each select="team">
      <table>
        <thead>
          <tr>
            <th>Player</th>
            <th>Kills</th>
            <th>Assists</th>
            <th>Deaths</th>
            <th>KDR</th>
          </tr>
        </thead>
        <tbody>
          <xsl:for-each select="player">
            <tr>
              <td><xsl:value-of select="name" /></td>
              <td><xsl:value-of select="kills" /></td>
              <td><xsl:value-of select="assists" /></td>
              <td><xsl:value-of select="deaths" /></td>
              <td><xsl:value-of select="kdr" /></td>
            </tr>
          </xsl:for-each>
        </tbody>
      </table>
    </xsl:for-each>
  </xsl:template>
</xsl:transform>

请注意,生成完整的HTML文档是不必要的。片段(在这种情况下为<table>)完全没问题。

现在一切都已设置完毕,我们可以使用它:

<html lang="en">
<head>
  <script type="text/javascript" src="js/script.js"></script>
  <script type="text/javascript">
    function init() {
      var xml = loadXml('xml/dust2nons.xml'),
          xsl = loadXml('xml/dust2stats.xsl'),
          target = document.getElementById('dust2');

      setElementContent(target, transformXml(xml, xsl));
    }
  </script>
</head>
<body onload="init();">
  <div id="dust2"></div>
</body>
</html>

以下是transformXml(xml, xsl)产生的内容:

<table>
  <thead>
    <tr>
      <th>Player</th><th>Kills</th><th>Assists</th><th>Deaths</th><th>KDR</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Xizt</td><td>19</td><td>0</td><td>16</td><td>0.19</td>
    </tr>
  </tbody>
</table>