一个用于解析DOM的JavaScript解析器

8
我们在一个项目中有一个特殊的需求,需要通过JavaScript解析客户端端的HTML字符串(来自AJAX响应)。是的,不能用PHP或Java解析!我已经整整一个星期在StackOverflow上搜寻,但仍未找到可接受的解决方案。
更多要求细节:
  • 我们可以使用任何库(最好是dojo和/或jQuery),或者选择原生实现!

  • 我们需要解析作为字符串接收到的整个HTML文档,包括和。

  • 有时,我们还需要将解析后的DOM结构序列化为字符串。

  • 最后,我们不想将解析后的DOM附加到当前文档中。相反,我们将其发送回服务器进行永久存储。

例如:我们需要类似以下内容:
var dom = HTMLtoDOM('<html><head><title> This is the old title. </title></head></html>');
    dom.getElementsByTagName('title')[0].innerHTML = "This is a new Title";

根据我的研究,以下是我们的选择:

  1. TinyMCE解析器。问题?我认为我们需要必须包含一个编辑器。那么在我们不需要编辑器的情况下,如何解析HTML呢?

  2. John Resig的解析器。应该是我们最好的选择。不幸的是,当给它整个页面的内容时,解析器会崩溃!

  3. jQuery $(htmlString) 或 dojo.toDom(htmlString)。两者都依赖于DocumentFragment,因此会吞掉 <head><body>

编辑:我们想要序列化HTML,以便通过RegExp捕获某些自定义HTML注释。我们需要给用户编辑meta标签、title标签等的机会,因此需要HTML解析器。

哦,我感觉即使我只是暗示通过RegExp解析HTML,我也会被Stack Overflow上的人谋杀!!!


创建一个IFRAME节点并将其嵌入其中? - Jens Roland
但是我不明白为什么你要在将HTML字符串发送到服务器之前“解析”已序列化的字符串。无论如何,你都必须重新将其序列化为字符串才能将其传回服务器,对吧? - Jens Roland
1
@DreamFactory:给他们 <input>!不要给用户机会进行XSS或其他危险的操作。他们不需要编辑文档!而且,您绝不能显示来自不受信任来源的HTML。永远不要相信客户端!这是很危险的! - jwueller
@elusive 通常我会同意,但我们正在制作一个CMS。我们怎么能不显示客户的代码呢? - Gaurav Ramanan
如果您需要此功能在旧版本的IE中运行,请查看:https://dev59.com/gWHVa4cB1Zd3GeqPjhsp - joeytwiddle
显示剩余2条评论
5个回答

11
您可以利用当前文档而不必附加任何节点。尝试像这样做:
function toNode(html) {
    var doc = document.createElement('html');
    doc.innerHTML = html;
    return doc;
}

var node = toNode('<html><head><title> This is the old title. </title></head></html>');

console.log(node);​

http://jsfiddle.net/6SvqA/3/


2
@elusive 这可能是针对可信用户的,比如现场特工之类的,你永远不知道。 - Dagg Nabbit
@GGG 还有,它是跨浏览器的吗?我对 IE7+ 有疑问。在 IE9 中,控制台会在 doc.innerHTML 处中断。如果您能看一下,我将不胜感激... - Gaurav Ramanan
@DreamFactory 很不幸,我手头没有IE可以检查。我对答案进行了更新,可能会起作用(在其他浏览器中仍然有效)。如果还是不行,请告诉我,下次我在Windows机器旁边时会再看一下。 - Dagg Nabbit
1
还可以尝试使用outerHTML,不要告诉任何人我让你这么做的 :p - Dagg Nabbit
1
@GGG 也想试试 DOCTYPE,因为它在 <html> 前面。我已经尝试过 $(string)(第二点)。outerHTML 也一样吗?无法设置 outerHTML 属性。此操作的目标元素无效。 - Gaurav Ramanan
显示剩余8条评论

1

由于HTML本质上是XML,您可以使用jQuery parseXML

var dom = $.parseXML(html);

$('title', dom).text("This is a new Title");

编辑:

如果您想将其转换回字符串,您需要使用xml插件,但我找不到它的原始来源,因此在这里提供:

/**
 * jQuery xml plugin
 * Converts XML node(s) to string 
 *
 * Copyright (c) 2009 Radim Svoboda
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * @author  Radim Svoboda, user Zzzzzz
 * @version 1.0.0
 */


/**
 * Converts XML node(s) to string using web-browser features.
 * Similar to .html() with HTML nodes 
 * This method is READ-ONLY.
 *  
 * @param all set to TRUE (1,"all",etc.) process all elements,
 * otherwise process content of the first matched element 
 *  
 * @return string obtained from XML node(s)  
 */         
jQuery.fn.xml = function(all) {

  //result to return
  var s = "";

   //Anything to process ?
   if( this.length )

    //"object" with nodes to convert to string  
   (
      ( ( typeof all != 'undefined' ) && all ) ?
      //all the nodes 
      this 
      :
      //content of the first matched element 
      jQuery(this[0]).contents()
    )
   //convert node(s) to string  
   .each(function(){
    s += window.ActiveXObject ?//==  IE browser ?
       //for IE
         this.xml
         :
         //for other browsers
         (new XMLSerializer()).serializeToString(this)
         ;
  }); 


  return    s;      

  };

这会保留HTML文档结构吗?例如<head> <body>和<html>标签? - Gaurav Ramanan
jQuery.parseXML() 不是用来解析 HTML 的,它只能用于 XML。所以在处理 HTML 时需要使用其他方法。 - jwueller
据我所知,是的,但测试取决于您。我已经在类似的情况下使用过这个,到目前为止还没有出现任何问题 :) - d_inevitable

1
我建议采用两部分的方案,首先读取jQuery无法解析的标签,然后将剩余部分传递给jQuery。如果你正在寻找一种纯JavaScript解决方案来解析HTML数据结构,jQuery可能是你最好的选择,因为它有许多内置函数可以操作数据。实际上,你可以将自己的插件构建为一个jQuery插件,可以通过$.parser或类似的方式进行调用。如果使用自己的函数扩展jQuery来解析数据,还可以返回一个扩展了特定数据元素读取函数的jQuery对象,即使从标题中也可以手动解析...信息并将其存储在同一对象中。

1

我不知道为什么有人需要这个,但我建议你将源代码简单地转储到一个iframe中。浏览器可以为您解析。您甚至可以在结果上运行DOM查询。


是的,我尝试过这个!但是请参考我们可能需要将DOM序列化回字符串的地方。对于iframe,我们该如何做到这一点?我们正在为自定义CMS制作此功能,其中可编辑区域将通过自定义HTML注释标记。 - Gaurav Ramanan

1
如果你想要一个完整的解析器,而不是依赖于浏览器中的现有工具来引导你的解释器,那么 dom.js 中的 HTML 解析器是非常出色的。它的整个目的是解析 HTML 以在 JavaScript 托管的 DOM 中使用,因此它必须同时满足 DOM 规范和解析和在 JS 中使用结果的需要,同时不假设除了基本 JS 之外存在任何现有工具。它可以在 node.js 或 spidermonkey 的 jsshell 或 webworkers 中使用。https://github.com/andreasgal/dom.js 它还具有序列化部分,但要做到这一点,您需要承诺使用不仅仅是解析器部分。不过,您可以找到独立的序列化程序,可以与任何类似 DOM 的结构一起使用。

不错,但它是客户端的吗? - Gaurav Ramanan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接