JS:基于节点解析XML和更新控件

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (81)

我在一次面试中被问到这个问题。任务是在客户端解析XML并用其内容填充html页面。也有人问使用jQuery。

理想情况下,我甚至不知道XML上有什么,只需为XML中的每个节点/元素添加一个标签。但是,假设我确实知道XML是什么样子的:

<?xml version="1.0" encoding="UTF-8"?> 
<cv>
    <FirstName>David</FirstName>
    <LastName>Refaeli</LastName>
    <Jobs>Worst JS Programmer</Jobs>
</cv>

我的服务器端html是:

<body>
    <form id="form1" runat="server">
        <div>
            <asp:TextBox ID="TextBox1" runat="server" Height="185px" Width="279px"></asp:TextBox><br />
            <asp:Button ID="Button1" runat="server" Text="Button" OnClientClick="return ParseXml();" /><br />
            <br />
            <asp:Label ID="FirstName" runat="server" Text=""></asp:Label><br />
            <asp:Label ID="LastName" runat="server" Text=""></asp:Label><br />
            <asp:Label ID="Jobs" runat="server" Text=""></asp:Label><br />
        </div>
    </form>
</body>
</html>

并假设TextBox包含XML。我已经为XML中的文本设置了占位符标签。

我试着运行这个JS(和许多其他版本),但是它失败了,在VS中调试它似乎找不到原因(它突然把我弹到一个jQuery文件中.),所以我猜我走错了方向。

<script>
    function ParseXml() {
        var text = document.getElementById('<% = TextBox1.ClientID %>');
        parser = new DOMParser();
        xmlDoc = parser.parseFromString(text.textContent, "text/xml");
        var a1 = xmlDoc.getElementsByTagName("cv")[0].childNodes[0].nodeValue;
        var a2 = xmlDoc.getElementsByTagName("cv")[0].childNodes[1].nodeValue;
        var a3 = xmlDoc.getElementsByTagName("cv")[0].childNodes[2].nodeValue;
        document.getElementById('<% = FirstName.ClientID %>').textContent = a1;
        document.getElementById('<% = LastName.ClientID %>').textContent = a2;
        document.getElementById('<% = Jobs.ClientID %>').textContent = a3;
        return true;
    }
</script>
提问于
用户回答回答于

当函数返回true时,将表单提交给服务器,因此你将获得新表单并丢失所有Javascript更改。第一个更改是返回false,以防止回发。然后,我改变了从XML检索文本的方式。

function ParseXml() {
    var xml = document.getElementById('<% = TextBox1.ClientID %>').value;
    var parser = new DOMParser();
    xmlDoc = parser.parseFromString(xml, "text/xml");
    var firstName = xmlDoc.getElementsByTagName("FirstName")[0].childNodes[0].nodeValue;
    var lastName = xmlDoc.getElementsByTagName("LastName")[0].childNodes[0].nodeValue;
    var jobs = xmlDoc.getElementsByTagName("Jobs")[0].childNodes[0].nodeValue;
    document.getElementById('<% = FirstName.ClientID %>').innerText = firstName;
    document.getElementById('<% = LastName.ClientID %>').textContent = lastName;
    document.getElementById('<% = Jobs.ClientID %>').textContent = jobs;
    return false;
};

或者,如果你不知道里面的字段CVTag,可以这样做:

var tags = xmlDoc.getElementsByTagName("cv")[0].childNodes;
for (key in tags)
{
    if (tags[key].nodeName.length) {
        document.body.innerHTML += '<b>'
            + tags[key].nodeName + ':</b> '
            + tags[key].textContent + '<br />';
    }
}

我也有残疾ValidateRequest在你的ASPX中:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication14.WebForm2" ValidateRequest="false" %>

通过这些更改,代码应该能够解析如下所示的XML:

<?xml version="1.0" encoding="UTF-8"?> 
<cv>
    <FirstName>David</FirstName>
    <LastName>Refaeli</LastName>
    <Jobs>Worst JS Programmer</Jobs>
</cv>

在你的尝试中,为什么xmlDoc.getElementsByTagName("cv")[0].childNodes[0].nodeValue不返回名字是因为childNodes包含额外的text节点,用于标记之间的空格和新行字符。因此,数组看起来如下:

0:文本,1:First Name,2:text,3:lastName,4:text,5:Jobs,6:text

名字是第1项,而不是0。但是由于XML上只有一份简历,所以我可以使用以下方法访问:

xmlDoc.getElementsByTagName("FirstName")[0].childNodes[0].nodeValue;
用户回答回答于

面试官想知道你是否知道如何进行XSLT转换(或者只是看看你是否知道这个概念)。

我在原始xml中添加了一个CVs列表,并添加了xslt转换模板,该模板将创建<h1>标题和一个表,它将输出简历列表-每个简历在单独的行中,每个属性在单独的列中。然而,你真的可以用任何你想要的方式来修饰它。

单击按钮运行的代码将从一个TextArea加载XML对象,从另一个TextArea加载XSLT对象。然后它会用XSLTProcessor对象导入XSLT样式表,并使用它将XML转换为HTML片段。transformToFragment函数并将该片段放置在<div>元素。

以下是你可以查看的所有片段:

function Transform()
{
  var parser = new DOMParser();
  var xml = parser.parseFromString(document.getElementById('xml').value, 'text/xml');
  var xslt = parser.parseFromString(document.getElementById('xslt').value, 'text/xml');
  
  var xsltProcessor = new XSLTProcessor();
  xsltProcessor.importStylesheet(xslt);
  resultDocument = xsltProcessor.transformToFragment(xml, document);
  document.getElementById('output').appendChild(resultDocument);
}
<html>
<body>
<p><label for="xml">XML:</label></p>
<textarea id="xml" rows=14 cols=100>
<?xml version="1.0" encoding="UTF-8"?>
<cvs>
  <cv>
    <FirstName>David</FirstName>
    <LastName>Refaeli</LastName>
    <Jobs>Worst JS Programmer</Jobs>
  </cv>
  <cv>
    <FirstName>Ivan</FirstName>
    <LastName>Ferić</LastName>
    <Jobs>Bounty hunter</Jobs>
  </cv>
</cvs>
</textarea>

<p><label for="xslt">XSLT:</label></p>
<textarea id="xslt" rows=21 cols=100>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <h2>CVs</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th style="text-align:left">First Name</th>
        <th style="text-align:left">Last Name</th>
        <th style="text-align:left">Jobs</th>
      </tr>
      <xsl:for-each select="cvs/cv">
      <tr>
        <td><xsl:value-of select="FirstName" /></td>
        <td><xsl:value-of select="LastName" /></td>
        <td><xsl:value-of select="Jobs" /></td>
      </tr>
      </xsl:for-each>
    </table>
  </xsl:template>
</xsl:stylesheet>
</textarea>

<p><button onclick="Transform()">Transform</button></p>

<p>Output:</p>
<div id="output"></div>
</body>
</html>

扫码关注云+社区

领取腾讯云代金券