2010-04-10 115 views
1

我实际上是在制作一个侧边栏小工具(基于AJAX),我正在寻找一种方法从AJAX请求中提取单个元素。从XMLHttpRequest中提取单个元素

我发现的唯一办法却是做这样的事情:

var temp = document.createElement("div"); 
temp.innerHTML = HttpRequest.innerText; 
document.body.appendChild(temp); 
temp.innerHTML = document.getElementByID("WantedElement").innerText; 

但它是相当难看,我想直接从请求中提取WantedElement而不将其添加到实际的文档...

谢谢!

回答

1

如果你在控制数据,你所做的方式可能是最好的方法。其他答案有其好处,但它们都有缺陷。例如,querySelector()方法仅适用于在主机上以IE8模式运行的Windows桌面小工具。正则表达式对解析HTML尤其不可靠,因此不应使用。

如果您不控制数据或者数据不是通过安全协议传输的,那么您应该比代码美学更关心安全性 - 您可能会为小工具和小工具引入潜在的安全风险主机通过插入unsanitized HTML到文档中。由于小工具以用户或管理员级别权限运行,因此明显的安全风险是脚本注入不可信,导致恶意脚本漏洞在运行的计算机上造成严重破坏。

一个潜在的解决方案是使用htmlfile的ActiveXObject:

function getElementFromResponse(divId) 
{ 
    var h = new ActiveXObject("htmlfile"); 
    h.open(); 

    // disable activex controls 
    h.parentWindow.ActiveXObject = function() {}; 

    // write the html to the document 
    h.write(html); 

    h.close(); 
    return h.getElementById("divID").innerText; 
} 

您也可以利用IE8的toStaticHTML()方法,但您的小工具需要在IE8模式下运行。

+1

谢谢! 我总是忘记我不必在小工具中使用跨浏览器,所以我可以使用ActiveX。 – 2010-04-14 13:44:42

+0

@ m6a-uds:这可能是开发小工具的最大好处,也是专有IE功能最大的适用范围。我已经构建到小工具中的一些内容将无法在另一个浏览器上运行:-) – 2010-04-14 13:50:36

0

一种选择是使用正则表达式:

var str = response.match(/<div id="WantedElement">(.+)<\/div>/); 
str[0]; // contents of div 

但是,如果你的服务器响应比较复杂,我建议你使用的数据格式像JSON响应。那么在客户端解析会更清晰。

-1

通过AJAX请求传递HTML是有点不寻常的;通常你传递一个客户端可以直接评估的JSON字符串,并且可以使用该工具

也就是说,我不认为有一种方法可以用JavaScript来解析HTML,这是跨浏览器的方式,但这里是一个这样做在Mozilla衍生品:

var r = document.createRange(); 
r.selectNode(document.body); 
var domNode = r.createContextualFragment(HTTPRequest.innerText); 
+0

@Michael:不幸的是,Windows桌面小工具在小型Internet Explorer“服务器”窗口中运行,因此您的Mozilla解决方案在这里没有多大帮助:-) – 2010-04-10 20:57:52

0

你可以追加来自XMLHttpRequest的一个隐藏的DIV中的反应,然后调用getElementById以获得所需的元素。稍后在完成后移除div。或者也许创建一个函数来处理这个问题。

function addNinjaNodeToDOM(html) { 
    var ninjaDiv = document.createElement("div"); 
    ninjaDiv.innerHTML = html; 
    ninjaDiv.style.display = 'none'; 
    return ninjaDiv; 
} 

var wrapper = addNinjaNodeToDOM(HttpRequest.innerText); 
var requiredNode = wrapper.getElementById("WantedElement"); 
// do something with requiredNode 
document.body.removeChild(wrapper); // remove when done 

它附加到DOM的唯一原因是因为getElementById不会,除非DOM树的一部分它的工作。见MDC

但是,您仍然可以在分离的DOM节点上运行选择器和XPath查询。这会让你免于让你将元素附加到DOM。

var superNinjaDiv = document.createElement('div'); 
superNinjaDiv.innerHTML = html; 
var requiedNode = superNinjaDiv.querySelector("[id=someId]"); 
0

我认为在这种情况下使用getElementById查找元素不是一个好方法。这是因为您必须采取额外步骤来使用它。将元素包装在DIV中,注入DOM中,使用getElementById查找元素,然后从DOM中移除注入的DIV。

DOM操作很昂贵,注入也可能导致不必要的回流。问题是你有一个document.getElementById,而不是一个element.getElementById,它允许你在文档中不注入查询。

为了解决这个问题,使用querySelector是一个显而易见的解决方案。否则,我会建议使用getElementsByClassName(如果可以的话)以及您的元素是否定义了类。

getElementsByClassName在ELEMENT上定义,因此可以在不注入DOM中的元素的情况下使用。

希望这会有所帮助。

+0

@Rajat:'querySelector'在IE7中不可用,它在Vista中默认安装,因此是Windows桌面小工具的主机除非安装了IE8,并且一个小工具为元标记中的“X-UA兼容”标头指定了IE8。当前发布的IE版本不支持'getElementsByClassName'。 – 2010-04-13 15:31:44