我在接受采访时被问到这个问题。任务是在客户端解析xml并用其内容填充html页面。还有人要求不使用jQuery。
理想情况下,我甚至不知道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>
并假设文本框包含xml。我已经为xml中的文本设置了占位符标签。
我尝试运行这个JS(以及许多其他变体),但它失败了,在VS中调试它似乎没有找到原因(它确实突然把我弹入jQuery文件......)所以我&# 39;我猜我错了。
<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>
任何帮助都将不胜感激。
答案 0 :(得分:1)
当函数返回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;
};
或者,如果您不知道 cv 标记内的字段,则可以执行以下操作:
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 />';
}
}
我也在你的Aspx中禁用了ValidateRequest
:
<%@ 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:text,1:firstname,2:text,3:lastname,4:text,5:jobs,6:text
第一个名字是第1项,而不是0.但是由于xml上只有一个简历,我可以使用这个来访问:
xmlDoc.getElementsByTagName("FirstName")[0].childNodes[0].nodeValue;
答案 1 :(得分:1)
不确定服务器端HTML是否是问题的一部分,但我想不是。 为了概念验证,我将继续使用您的示例XML并从数据构建文本输入。 在AJAX调用之后,在页面加载时动态创建表单内容,因此您必须使用服务器才能在工作中查看它。所有三个文件都要并排放置。
HTML页面(index.html)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="margin:50px">
<form>
<h1>Dynamic Form</h1>
<div id="form-content"></div>
<button>some action</button>
</form>
<script src="index.js"></script>
</body>
</html>
数据(data.xml)
<?xml version="1.0" encoding="UTF-8"?>
<cv>
<FirstName>David</FirstName>
<LastName>Refaeli</LastName>
<Jobs>Aspiring JS Programmer</Jobs>
</cv>
JavaScript代码(index.js)
// create a label from a string and append to parent DOM element
function addLabel(parent, name) {
var wrapper = document.createElement('div');
var label = document.createElement('label');
label.innerHTML = name;
wrapper.appendChild(label);
parent.appendChild(wrapper);
}
// create a text input from a with id and value
// and append to parent DOM element
function addTextbox(parent, id, value) {
var box = document.createElement('input');
box.type = 'text';
box.id = id;
box.value = value;
parent.appendChild(box);
}
// create a input with label for text with id and value
function createTextbox(id, value) {
var form = document.getElementById('form-content');
addLabel(form, id);
addTextbox(form, id, value);
}
// upload the data that defines dynamic text inputs for a
// form and create the form
function update () {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var values = xhr.responseXML.documentElement.children;
var length = values.length;
for (var i = 0; i < length; i++) {
var node = values[i];
var name = node.nodeName;
var value = node.innerHTML;
createTextbox(name, value);
};
};
xhr.onerror = function (error) {
console.error(error);
};
xhr.responseType = 'document';
xhr.open('GET', 'data.xml');
xhr.send();
}
// simplistic onload :-)
update();
正如您所看到的,输入的解析和创建是分开的。现在,如果我们使用实际的输入类型(例如文本,广播,复选框)来提取XML,我们可以扩展代码以根据数据创建不同的输入字段,最终创建一个纯粹由XML定义的真实复杂形式。 / p>
答案 2 :(得分:0)
面试官想知道你是否知道如何进行XSLT转换(或者只是看看你是否知道这个概念)。
我在原始XML上添加了一个CV列表,并添加了将创建<h1>
标题的XSLT转换模板和一个将输出CV列表的表 - 每个CV在一个单独的行中,每个属性在一个单独的专栏。但是,您可以按照自己想要的方式设置样式。
单击按钮时运行的代码将从一个textarea加载XML对象,从另一个加载xslt对象。然后,它将使用XSLTProcessor
对象导入XSLT样式表,并使用它来使用transformToFragment
函数将XML转换为HTML片段,并将该片段放在<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>