尝试覆盖 Nokogiri 的序列化行为



我使用Nokogiri修改HTML树并输出代码。我需要改变一个特定节点输出到html的方式(详情如下),所以我已经子类化了Nokogiri::XML::Node

我如何重写子类的输出行为?

现在,如果我覆盖to_html(),那么我在为Nokogiri::HTML::DocumentFragment实例调用to_html()时得到我想要的显示,但是当我在Nokogiri::HTML::Document实例上调用它时,正常的输出行为接管。这样做是不行的,因为我实际上需要更改文档头部(它被排除在DocumentFragment实例之外)。

为什么我需要改变HTML输出:

我需要能够包括一个非合作的</noscript>标签,为了使用GWO与我的代码。但是,我不能在HTML树中添加非合作结束标记。

使用Nokogiri,我也不能将其添加为文本,因为<>被转义为html字符代码。

我不能在这个项目中使用Hpricot,因为我在一些糟糕的代码(由其他人在工作中编写)上运行它,并且Hpricot不会保留有问题的错误(例如将块元素放在<a>元素中)。(不,我不打算追踪所有糟糕的HTML并修复它。)

规格: WinXP, Ruby 1.8.6, Nokogiri 1.4.4

更新:

由于我无法猜测的原因,当我为子类创建构造函数时,无论我为子类构造函数需要多少参数,如果我提供了两个以外的任何数字(超类所需的参数数量),我都会得到错误。

class NoScript < Nokogiri::XML::Node
  def initialize(doc)
    super("string", doc)
  end
end

我在其他课程中没有遇到过这个问题。我错过什么了吗?

最有可能的是,您的代码在某个点调用write_to (to_html调用serialize, serialize调用write_to)。然后在当前节点上调用native_write_to。让我们来看看。

static VALUE native_write_to(
    VALUE self,
    VALUE io,
    VALUE encoding,
    VALUE indent_string,
    VALUE options
) {
  xmlNodePtr node;
  const char * before_indent;
  xmlSaveCtxtPtr savectx;
  Data_Get_Struct(self, xmlNode, node);
  xmlIndentTreeOutput = 1;
  before_indent = xmlTreeIndentString;
  xmlTreeIndentString = StringValuePtr(indent_string);
  savectx = xmlSaveToIO(
      (xmlOutputWriteCallback)io_write_callback,
      (xmlOutputCloseCallback)io_close_callback,
      (void *)io,
      RTEST(encoding) ? StringValuePtr(encoding) : NULL,
      (int)NUM2INT(options)
  );
  xmlSaveTree(savectx, node);
  xmlSaveClose(savectx);
  xmlTreeIndentString = before_indent;
  return io;
}

代码在github。如果您阅读它,您将看到它没有在任何地方调用to_html,因此您的自定义方法永远不会运行。如果你使用Nokogiri::HTML::DocumentFragment,它会被调用,因为DocumentFragment#to_html依赖于Nokogiri::XML::NodeSet#to_html,它是一个普通的映射:

def to_html *args
  if Nokogiri.jruby?
    options = args.first.is_a?(Hash) ? args.shift : {}
    if !options[:save_with]
      options[:save_with] = Node::SaveOptions::NO_DECLARATION | Node::SaveOptions::NO_EMPTY_TAGS | Node::SaveOptions::AS_HTML
    end
    args.insert(0, options)
  end
  map { |x| x.to_html(*args) }.join
end

相关内容

  • 没有找到相关文章

最新更新