Support for parsing XML processing instructions.

This commit is contained in:
Yorick Peterse 2014-08-15 22:23:26 +02:00
parent 2c488f92be
commit 0d7609da88
7 changed files with 157 additions and 1 deletions

View File

@ -23,6 +23,7 @@ require_relative 'oga/xml/text'
require_relative 'oga/xml/comment' require_relative 'oga/xml/comment'
require_relative 'oga/xml/cdata' require_relative 'oga/xml/cdata'
require_relative 'oga/xml/xml_declaration' require_relative 'oga/xml/xml_declaration'
require_relative 'oga/xml/processing_instruction'
require_relative 'oga/xml/doctype' require_relative 'oga/xml/doctype'
require_relative 'oga/xml/attribute' require_relative 'oga/xml/attribute'
require_relative 'oga/xml/namespace' require_relative 'oga/xml/namespace'

View File

@ -15,6 +15,7 @@ token T_DOCTYPE_INLINE
token T_CDATA T_COMMENT token T_CDATA T_COMMENT
token T_ELEM_START T_ELEM_NAME T_ELEM_NS T_ELEM_END T_ATTR T_ATTR_NS token T_ELEM_START T_ELEM_NAME T_ELEM_NS T_ELEM_END T_ATTR T_ATTR_NS
token T_XML_DECL_START T_XML_DECL_END token T_XML_DECL_START T_XML_DECL_END
token T_PROC_INS_START T_PROC_INS_NAME T_PROC_INS_END
options no_result_var options no_result_var
@ -40,6 +41,7 @@ rule
| element | element
| text | text
| xmldecl | xmldecl
| proc_ins
; ;
# Doctypes # Doctypes
@ -95,6 +97,20 @@ rule
: T_COMMENT { on_comment(val[0]) } : T_COMMENT { on_comment(val[0]) }
; ;
# Processing Instructions
proc_ins
# <?xml?>
: T_PROC_INS_START T_PROC_INS_NAME T_PROC_INS_END
{
on_proc_ins(val[1])
}
| T_PROC_INS_START T_PROC_INS_NAME T_TEXT T_PROC_INS_END
{
on_proc_ins(val[1], val[2])
}
;
# Elements # Elements
element_open element_open
@ -155,6 +171,7 @@ rule
; ;
# XML declarations # XML declarations
xmldecl xmldecl
: T_XML_DECL_START attributes T_XML_DECL_END { on_xml_decl(val[1]) } : T_XML_DECL_START attributes T_XML_DECL_END { on_xml_decl(val[1]) }
; ;
@ -307,6 +324,15 @@ Unexpected #{name} with value #{value.inspect} on line #{@line}:
return Comment.new(:text => text) return Comment.new(:text => text)
end end
##
# @param [String] name
# @param [String] text
# @return [Oga::XML::ProcessingInstruction]
#
def on_proc_ins(name, text = nil)
return ProcessingInstruction.new(:name => name, :text => text)
end
## ##
# @param [Array] attributes # @param [Array] attributes
# @return [Oga::XML::XmlDeclaration] # @return [Oga::XML::XmlDeclaration]

View File

@ -0,0 +1,39 @@
module Oga
module XML
##
# Class used for storing information about a single processing instruction.
#
# @!attribute [rw] name
# @return [String]
#
class ProcessingInstruction < CharacterNode
attr_accessor :name
##
# @param [Hash] options
#
# @option options [String] :name The name of the instruction.
# @see [Oga::XML::CharacterNode#initialize]
#
def initialize(options = {})
super
@name = options[:name]
end
##
# @return [String]
#
def to_xml
return "<?#{name}#{text}?>"
end
##
# @return [String]
#
def inspect
return "ProcessingInstruction(name: #{name.inspect} text: #{text.inspect})"
end
end # ProcessingInstruction
end # XML
end # Oga

View File

@ -46,7 +46,8 @@ module Oga
BLOCK_CALLBACKS = [ BLOCK_CALLBACKS = [
:on_cdata, :on_cdata,
:on_comment, :on_comment,
:on_text :on_text,
:on_proc_ins
] ]
## ##

View File

@ -0,0 +1,35 @@
require 'spec_helper'
describe Oga::XML::Parser do
context 'empty processing instructions' do
before :all do
@node = parse('<?foo?>').children[0]
end
example 'return a ProcessingInstruction instance' do
@node.is_a?(Oga::XML::ProcessingInstruction).should == true
end
example 'set the name of the instruction' do
@node.name.should == 'foo'
end
end
context 'processing instructions with text' do
before :all do
@node = parse('<?foo bar ?>').children[0]
end
example 'return a ProcessingInstruction instance' do
@node.is_a?(Oga::XML::ProcessingInstruction).should == true
end
example 'set the name of the instruction' do
@node.name.should == 'foo'
end
example 'set the text of the instruction' do
@node.text.should == ' bar '
end
end
end

View File

@ -0,0 +1,29 @@
require 'spec_helper'
describe Oga::XML::ProcessingInstruction do
context '#initialize' do
example 'set the name of the node' do
described_class.new(:name => 'foo').name.should == 'foo'
end
example 'set the text of the node' do
described_class.new(:text => 'foo').text.should == 'foo'
end
end
context '#to_xml' do
example 'conver the node into XML' do
node = described_class.new(:name => 'foo', :text => ' bar ')
node.to_xml.should == '<?foo bar ?>'
end
end
context '#inspect' do
example 'return the inspect value of the node' do
node = described_class.new(:name => 'foo', :text => ' bar ')
node.inspect.should == 'ProcessingInstruction(name: "foo" text: " bar ")'
end
end
end

View File

@ -0,0 +1,25 @@
require 'spec_helper'
describe Oga::XML::PullParser do
context 'processing instructions' do
before :all do
@parser = described_class.new('<?foo bar ?>')
@node = nil
@parser.parse { |node| @node = node }
end
example 'return a ProcessingInstruction node' do
@node.is_a?(Oga::XML::ProcessingInstruction).should == true
end
example 'set the name of the node' do
@node.name.should == 'foo'
end
example 'set the text of the node' do
@node.text.should == ' bar '
end
end
end