No release in over 3 years
Low commit activity in last 3 years
Nokogiri DOM Range Implementatin based on DOM Standard specification.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

 Project Readme

Nokogiri::XML::Range

pipeline status coverage report Gem Version

DOM Range implementation on Nokogiri

Description

Nokogiri DOM Range Implementatin based on DOM Standard specification.

Features

Nokogiri::XML::Range expresses a range on DOM tree. It can:

  • test a node is in the range or not,
  • delete contents the range expresses from DOM tree,
  • extract contents alike,
  • clone contents alike,
  • surround the range by specified DOM element,
  • and so on...

Examples

Initialization

require 'nokogiri/xml/range'

doc = Nokogiri.XML(<<EOX)
<root>
  <parent>
    <child>child 1</child>
    <child>child 2</child>
  </parent>
</root>
EOX
parent = doc.search('parent')[0]
child1 = doc.search('child')[0]
child2 = doc.search('child')[1]
child1_text = child1.child
child2_text = child2.child

# Initialize range with nodes and offsets of start and end point
range = Nokogiri::XML::Range.new(child1_text, 0, child2_text, 5)

# This range expresses `child 1</child>\n        <child>child`
# Pseudoly expressed as:
# <root>
#   <parent>
#     <child>[**START POINT**]child 1</child>
#     <child>child[**END POINT**] 2</child>
#   </parent>
# </root>

Deleting contents

range.delete_contents
puts doc
# <?xml version="1.0"?>
# <root>
#   <parent>
#     <child></child><child> 2</child>
#   </parent>
# </root>

Extracting contents

Nokogiri::XML::Range#extract_contents remove the range from DOM tree and returns contents in the range.

extracted = range.extract_contents
# => #(DocumentFragment:0x3fa87891eaa0 {
#   name = "#document-fragment",
#   children = [
#     #(Element:0x3fa87891e12c { name = "child", children = [ #(Text "child 1")] }),
#     #(Text "\n        "),
#     #(Element:0x3fa8789177f0 { name = "child", children = [ #(Text "child")] })]
#   })
puts doc
# <?xml version="1.0"?>
# <root>
#   <parent>
#     <child></child><child> 2</child>
#   </parent>
# </root>
puts extracted
# <child>child 1</child>
#     <child>child</child>

Cloning contents

cloned = range.clone_contents
# => #(DocumentFragment:0x3fa87809fb90 {
#   name = "#document-fragment",
#   children = [
#     #(Element:0x3fa87809e394 { name = "child", children = [ #(Text "child 1")] }),
#     #(Text "\n        "),
#     #(Element:0x3fa87808dcd8 { name = "child", children = [ #(Text "child")] })]
#   })
puts cloned
# <child>child 1</child>
#     <child>child</child>

Nokogiri::XML::Range#clone_contents doesn't affect original DOM tree.

Inserting node

Nokogiri::XML::Range#insert_node inserts a node just before the range start point.

text = Nokogiri::XML::Text.new('inserted', doc)
# => #(Text "inserted")
range.insert_node text
puts doc
# <?xml version="1.0"?>
# <root>
#   <parent>
#     <child>insertedchild 1</child>
#     <child>child 2</child>
#   </parent>
# </root>

Surrounding range contents

range = Nokogiri::XML::Range.new(child1_text, 6, child1_text, 7)
number = Nokogiri::XML::Element.new('number', doc)
range.surround_contents number
puts doc
# <?xml version="1.0"?>
# <root>
#   <parent>
#     <child>child <number>1</number></child>
#     <child>child 2</child>
#   </parent>
# </root>

Requirements

  • Ruby 2.1.0 or later
  • Nokogiri gem
  • C compiler like gcc to install Nokogiri gem
  • patch command to install Nokogiri gem

Install

$ gem install nokogiri-xml-range

Todos

  • Helpful error messages
  • C0 coverage 100%
  • More test cases from use cases in the wild
  • Performance optimization, especially caching

Copyright

Copyright (c) 2015 KITAITI Makoto

See {file:COPYING.txt} for details.