代码之家  ›  专栏  ›  技术社区  ›  nicohvi

使用Nokogiri添加节点

  •  3
  • nicohvi  · 技术社区  · 11 年前

    我有一个HTML字符串(例如 <div class="input">hello</div> )如果字符串中的HTML标记是 label (例如 <label>Hi</label> ).

    doc = Nokogiri::XML(html)
    
    doc.children.each do |node|
      if node.name == 'label'
        # this code gets called
        span = Nokogiri::XML::Node.new "span", node
        span.content = "hello"
    
        puts span.parent 
        # nil
    
        span.parent = node
        # throws error "node can only have one parent"
      end
    end
    
    doc.to_html # Does not contain the span.
    

    我一辈子都无法理解我做错了什么,任何帮助都是 大大地 感谢。

    编辑 :这解决了我的问题,谢谢你的回答!

    # notice DocumentFragment rather than XML
    doc = Nokogiri::HTML::DocumentFragment.parse(html_tag)
    doc.children.each do |node|
      if node.name == 'label'
        span = Nokogiri::XML::Node.new "span", doc
        node.add_child(span)
      end
    end
    
    2 回复  |  直到 11 年前
        1
  •  4
  •   the Tin Man    11 年前

    添加/更改/删除HTML很简单:

    require 'nokogiri'
    
    doc = Nokogiri::HTML::DocumentFragment.parse('<div class="input">hello</div>')
    div = doc.at('div')
    div << '<span>Hello</span>'
    puts doc.to_html
    

    结果是:

    # >> <div class="input">hello<span>Hello</span>
    # >> </div>
    

    注意,上面的代码将一个新节点附加到 <div> 因为 << ,这意味着它们是附加的 之后 包含“hello”的文本节点。

    如果要覆盖子级,可以使用 children = :

    div.children = '<span>Hello</span>'
    puts doc.to_html
    

    结果是:

    # >> <div class="input"><span>Hello</span></div>
    

    children = 可以采用一个节点,该节点下可以有多个其他节点,或者插入的节点的HTML文本。就是这样 node_or_tags 意思是当你看到它时 the documentation .

    也就是说,改变只是一个嵌入的 <label> ,我会这样做:

    doc = Nokogiri::HTML::DocumentFragment.parse('<div class="input"><label>hello</label></div>')
    label = doc.at('div label')
    label.name = 'span' if label
    puts doc.to_html
    # >> <div class="input"><span>hello</span></div>
    

    或:

    doc = Nokogiri::HTML::DocumentFragment.parse('<div class="input"><label>hello</label></div>')
    label = doc.at('div label')
    label.replace("<span>#{ label.text }</span>") if label
    puts doc.to_html
    # >> <div class="input"><span>hello</span></div>
    

    Nokogiri使您在指向标记后很容易更改标记的名称 <span> 通过替换 #{ label.text } 无论你想要什么。

    at('div label') 是查找特定节点的一种方法。它的基本意思是“在第一个div中找到第一个标签标记”。 at 意思是找到某物的第一个,类似于使用 search(...).first 。CSS和XPath等价于两者 search Nokogiri::XML::Node documentation 如果你需要的话。

        2
  •  2
  •   Mark Silverberg    11 年前

    几个问题-你 span = .. 行正在创建节点,但实际上并没有将其添加到文档中。此外,您无法访问 span 在创建它的块之外。

    我想这就是你想要的:

    html = '<label>Hi</label>'
    
    doc = Nokogiri::XML(html)
    
    doc.children.each do |node|
      if node.name == 'label'
        # this code gets called
        span = Nokogiri::XML::Node.new "span", doc
        span.content = "hello"
        node.add_child(span)
      end
    end
    
    # NOTE: `node` nor `span` are accessible outside of the each block
    
    doc.to_s # => "<?xml version=\"1.0\"?>\n<label>Hi<span>hello</span></label>\n"
    

    注意 node.add_child(span) 线

    推荐文章