mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	rexml: upgrade to 3.1.8
See https://github.com/ruby/rexml/blob/master/NEWS.md for change summary. Changes for spec/ has been reported: https://github.com/ruby/spec/pull/639 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66458 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									0b38221d4e
								
							
						
					
					
						commit
						0d1abb904e
					
				
					 26 changed files with 566 additions and 197 deletions
				
			
		
							
								
								
									
										3
									
								
								NEWS
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								NEWS
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -453,6 +453,9 @@ sufficient information, see the ChangeLog file or Redmine
 | 
			
		|||
 | 
			
		||||
[REXML]
 | 
			
		||||
 | 
			
		||||
  * Upgrade to REXML 3.1.8
 | 
			
		||||
    https://github.com/ruby/rexml/blob/master/NEWS.md
 | 
			
		||||
 | 
			
		||||
  [Improved some XPath implementations]
 | 
			
		||||
 | 
			
		||||
    * <code>concat()</code> function: Stringify all arguments before concatenating
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -108,13 +108,19 @@ module REXML
 | 
			
		|||
    #   Ignored
 | 
			
		||||
    def write( output, indent=0, transitive=false, ie_hack=false )
 | 
			
		||||
      f = REXML::Formatters::Default.new
 | 
			
		||||
      c = context
 | 
			
		||||
      if c and c[:prologue_quote] == :apostrophe
 | 
			
		||||
        quote = "'"
 | 
			
		||||
      else
 | 
			
		||||
        quote = "\""
 | 
			
		||||
      end
 | 
			
		||||
      indent( output, indent )
 | 
			
		||||
      output << START
 | 
			
		||||
      output << ' '
 | 
			
		||||
      output << @name
 | 
			
		||||
      output << " #@external_id" if @external_id
 | 
			
		||||
      output << " #{@long_name.inspect}" if @long_name
 | 
			
		||||
      output << " #{@uri.inspect}" if @uri
 | 
			
		||||
      output << " #{@external_id}" if @external_id
 | 
			
		||||
      output << " #{quote}#{@long_name}#{quote}" if @long_name
 | 
			
		||||
      output << " #{quote}#{@uri}#{quote}" if @uri
 | 
			
		||||
      unless @children.empty?
 | 
			
		||||
        output << ' ['
 | 
			
		||||
        @children.each { |child|
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +133,11 @@ module REXML
 | 
			
		|||
    end
 | 
			
		||||
 | 
			
		||||
    def context
 | 
			
		||||
      @parent.context
 | 
			
		||||
      if @parent
 | 
			
		||||
        @parent.context
 | 
			
		||||
      else
 | 
			
		||||
        nil
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def entity( name )
 | 
			
		||||
| 
						 | 
				
			
			@ -249,9 +259,16 @@ module REXML
 | 
			
		|||
    end
 | 
			
		||||
 | 
			
		||||
    def to_s
 | 
			
		||||
      c = nil
 | 
			
		||||
      c = parent.context if parent
 | 
			
		||||
      if c and c[:prologue_quote] == :apostrophe
 | 
			
		||||
        quote = "'"
 | 
			
		||||
      else
 | 
			
		||||
        quote = "\""
 | 
			
		||||
      end
 | 
			
		||||
      notation = "<!NOTATION #{@name} #{@middle}"
 | 
			
		||||
      notation << " #{@public.inspect}" if @public
 | 
			
		||||
      notation << " #{@system.inspect}" if @system
 | 
			
		||||
      notation << " #{quote}#{@public}#{quote}" if @public
 | 
			
		||||
      notation << " #{quote}#{@system}#{quote}" if @system
 | 
			
		||||
      notation << ">"
 | 
			
		||||
      notation
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
# frozen_string_literal: false
 | 
			
		||||
 | 
			
		||||
module REXML
 | 
			
		||||
  module Formatters
 | 
			
		||||
    class Default
 | 
			
		||||
| 
						 | 
				
			
			@ -101,11 +102,14 @@ module REXML
 | 
			
		|||
      end
 | 
			
		||||
 | 
			
		||||
      def write_instruction( node, output )
 | 
			
		||||
        output << Instruction::START.sub(/\\/u, '')
 | 
			
		||||
        output << Instruction::START
 | 
			
		||||
        output << node.target
 | 
			
		||||
        output << ' '
 | 
			
		||||
        output << node.content
 | 
			
		||||
        output << Instruction::STOP.sub(/\\/u, '')
 | 
			
		||||
        content = node.content
 | 
			
		||||
        if content
 | 
			
		||||
          output << ' '
 | 
			
		||||
          output << content
 | 
			
		||||
        end
 | 
			
		||||
        output << Instruction::STOP
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -423,7 +423,7 @@ module REXML
 | 
			
		|||
      number = number(number)
 | 
			
		||||
      begin
 | 
			
		||||
        neg = number.negative?
 | 
			
		||||
        number = number.abs.round(half: :up)
 | 
			
		||||
        number = number.abs.round
 | 
			
		||||
        neg ? -number : number
 | 
			
		||||
      rescue FloatDomainError
 | 
			
		||||
        number
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
# frozen_string_literal: false
 | 
			
		||||
 | 
			
		||||
require_relative "child"
 | 
			
		||||
require_relative "source"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6,8 +7,8 @@ module REXML
 | 
			
		|||
  # Represents an XML Instruction; IE, <? ... ?>
 | 
			
		||||
  # TODO: Add parent arg (3rd arg) to constructor
 | 
			
		||||
  class Instruction < Child
 | 
			
		||||
    START = '<\?'
 | 
			
		||||
    STOP = '\?>'
 | 
			
		||||
    START = "<?"
 | 
			
		||||
    STOP = "?>"
 | 
			
		||||
 | 
			
		||||
    # target is the "name" of the Instruction; IE, the "tag" in <?tag ...?>
 | 
			
		||||
    # content is everything else.
 | 
			
		||||
| 
						 | 
				
			
			@ -17,20 +18,25 @@ module REXML
 | 
			
		|||
    # @param target can be one of a number of things.  If String, then
 | 
			
		||||
    # the target of this instruction is set to this.  If an Instruction,
 | 
			
		||||
    # then the Instruction is shallowly cloned (target and content are
 | 
			
		||||
    # copied).  If a Source, then the source is scanned and parsed for
 | 
			
		||||
    # an Instruction declaration.
 | 
			
		||||
    # copied).
 | 
			
		||||
    # @param content Must be either a String, or a Parent.  Can only
 | 
			
		||||
    # be a Parent if the target argument is a Source.  Otherwise, this
 | 
			
		||||
    # String is set as the content of this instruction.
 | 
			
		||||
    def initialize(target, content=nil)
 | 
			
		||||
      if target.kind_of? String
 | 
			
		||||
      case target
 | 
			
		||||
      when String
 | 
			
		||||
        super()
 | 
			
		||||
        @target = target
 | 
			
		||||
        @content = content
 | 
			
		||||
      elsif target.kind_of? Instruction
 | 
			
		||||
      when Instruction
 | 
			
		||||
        super(content)
 | 
			
		||||
        @target = target.target
 | 
			
		||||
        @content = target.content
 | 
			
		||||
      else
 | 
			
		||||
        message =
 | 
			
		||||
          "processing instruction target must be String or REXML::Instruction: "
 | 
			
		||||
        message << "<#{target.inspect}>"
 | 
			
		||||
        raise ArgumentError, message
 | 
			
		||||
      end
 | 
			
		||||
      @content.strip! if @content
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			@ -45,11 +51,13 @@ module REXML
 | 
			
		|||
    def write writer, indent=-1, transitive=false, ie_hack=false
 | 
			
		||||
      Kernel.warn( "#{self.class.name}.write is deprecated", uplevel: 1)
 | 
			
		||||
      indent(writer, indent)
 | 
			
		||||
      writer << START.sub(/\\/u, '')
 | 
			
		||||
      writer << START
 | 
			
		||||
      writer << @target
 | 
			
		||||
      writer << ' '
 | 
			
		||||
      writer << @content
 | 
			
		||||
      writer << STOP.sub(/\\/u, '')
 | 
			
		||||
      if @content
 | 
			
		||||
        writer << ' '
 | 
			
		||||
        writer << @content
 | 
			
		||||
      end
 | 
			
		||||
      writer << STOP
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # @return true if other is an Instruction, and the content and target
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
# frozen_string_literal: false
 | 
			
		||||
 | 
			
		||||
require_relative 'xmltokens'
 | 
			
		||||
 | 
			
		||||
module REXML
 | 
			
		||||
| 
						 | 
				
			
			@ -14,14 +15,24 @@ module REXML
 | 
			
		|||
    # Sets the name and the expanded name
 | 
			
		||||
    def name=( name )
 | 
			
		||||
      @expanded_name = name
 | 
			
		||||
      name =~ NAMESPLIT
 | 
			
		||||
      if $1
 | 
			
		||||
        @prefix = $1
 | 
			
		||||
      case name
 | 
			
		||||
      when NAMESPLIT
 | 
			
		||||
        if $1
 | 
			
		||||
          @prefix = $1
 | 
			
		||||
        else
 | 
			
		||||
          @prefix = ""
 | 
			
		||||
          @namespace = ""
 | 
			
		||||
        end
 | 
			
		||||
        @name = $2
 | 
			
		||||
      when ""
 | 
			
		||||
        @prefix = nil
 | 
			
		||||
        @namespace = nil
 | 
			
		||||
        @name = nil
 | 
			
		||||
      else
 | 
			
		||||
        @prefix = ""
 | 
			
		||||
        @namespace = ""
 | 
			
		||||
        message = "name must be \#{PREFIX}:\#{LOCAL_NAME} or \#{LOCAL_NAME}: "
 | 
			
		||||
        message += "<#{name.inspect}>"
 | 
			
		||||
        raise ArgumentError, message
 | 
			
		||||
      end
 | 
			
		||||
      @name = $2
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Compares names optionally WITH namespaces
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ require_relative '../parseexception'
 | 
			
		|||
require_relative '../undefinednamespaceexception'
 | 
			
		||||
require_relative '../source'
 | 
			
		||||
require 'set'
 | 
			
		||||
require "strscan"
 | 
			
		||||
 | 
			
		||||
module REXML
 | 
			
		||||
  module Parsers
 | 
			
		||||
| 
						 | 
				
			
			@ -32,9 +33,9 @@ module REXML
 | 
			
		|||
      COMBININGCHAR = '' # TODO
 | 
			
		||||
      EXTENDER = ''      # TODO
 | 
			
		||||
 | 
			
		||||
      NCNAME_STR= "[#{LETTER}_:][-[:alnum:]._:#{COMBININGCHAR}#{EXTENDER}]*"
 | 
			
		||||
      NAME_STR= "(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})"
 | 
			
		||||
      UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
 | 
			
		||||
      NCNAME_STR= "[#{LETTER}_][-[:alnum:]._#{COMBININGCHAR}#{EXTENDER}]*"
 | 
			
		||||
      QNAME_STR= "(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})"
 | 
			
		||||
      QNAME = /(#{QNAME_STR})/
 | 
			
		||||
 | 
			
		||||
      NAMECHAR = '[\-\w\.:]'
 | 
			
		||||
      NAME = "([\\w:]#{NAMECHAR}*)"
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +47,7 @@ module REXML
 | 
			
		|||
      DOCTYPE_START = /\A\s*<!DOCTYPE\s/um
 | 
			
		||||
      DOCTYPE_END = /\A\s*\]\s*>/um
 | 
			
		||||
      DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
 | 
			
		||||
      ATTRIBUTE_PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\4/um
 | 
			
		||||
      ATTRIBUTE_PATTERN = /\s*(#{QNAME_STR})\s*=\s*(["'])(.*?)\4/um
 | 
			
		||||
      COMMENT_START = /\A<!--/u
 | 
			
		||||
      COMMENT_PATTERN = /<!--(.*?)-->/um
 | 
			
		||||
      CDATA_START = /\A<!\[CDATA\[/u
 | 
			
		||||
| 
						 | 
				
			
			@ -55,9 +56,9 @@ module REXML
 | 
			
		|||
      XMLDECL_START = /\A<\?xml\s/u;
 | 
			
		||||
      XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>/um
 | 
			
		||||
      INSTRUCTION_START = /\A<\?/u
 | 
			
		||||
      INSTRUCTION_PATTERN = /<\?(.*?)(\s+.*?)?\?>/um
 | 
			
		||||
      TAG_MATCH = /^<((?>#{NAME_STR}))\s*((?>\s+#{UNAME_STR}\s*=\s*(["']).*?\5)*)\s*(\/)?>/um
 | 
			
		||||
      CLOSE_MATCH = /^\s*<\/(#{NAME_STR})\s*>/um
 | 
			
		||||
      INSTRUCTION_PATTERN = /<\?#{NAME}(\s+.*?)?\?>/um
 | 
			
		||||
      TAG_MATCH = /^<((?>#{QNAME_STR}))/um
 | 
			
		||||
      CLOSE_MATCH = /^\s*<\/(#{QNAME_STR})\s*>/um
 | 
			
		||||
 | 
			
		||||
      VERSION = /\bversion\s*=\s*["'](.*?)['"]/um
 | 
			
		||||
      ENCODING = /\bencoding\s*=\s*["'](.*?)['"]/um
 | 
			
		||||
| 
						 | 
				
			
			@ -107,13 +108,6 @@ module REXML
 | 
			
		|||
        "apos" => [/'/, "'", "'", /'/]
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      ######################################################################
 | 
			
		||||
      # These are patterns to identify common markup errors, to make the
 | 
			
		||||
      # error messages more informative.
 | 
			
		||||
      ######################################################################
 | 
			
		||||
      MISSING_ATTRIBUTE_QUOTES = /^<#{NAME_STR}\s+#{NAME_STR}\s*=\s*[^"']/um
 | 
			
		||||
 | 
			
		||||
      def initialize( source )
 | 
			
		||||
        self.stream = source
 | 
			
		||||
        @listeners = []
 | 
			
		||||
| 
						 | 
				
			
			@ -224,7 +218,7 @@ module REXML
 | 
			
		|||
            standalone = standalone[1] unless standalone.nil?
 | 
			
		||||
            return [ :xmldecl, version, encoding, standalone ]
 | 
			
		||||
          when INSTRUCTION_START
 | 
			
		||||
            return [ :processing_instruction, *@source.match(INSTRUCTION_PATTERN, true)[1,2] ]
 | 
			
		||||
            return process_instruction
 | 
			
		||||
          when DOCTYPE_START
 | 
			
		||||
            md = @source.match( DOCTYPE_PATTERN, true )
 | 
			
		||||
            @nsstack.unshift(curr_ns=Set.new)
 | 
			
		||||
| 
						 | 
				
			
			@ -336,11 +330,12 @@ module REXML
 | 
			
		|||
            if @source.buffer[1] == ?/
 | 
			
		||||
              @nsstack.shift
 | 
			
		||||
              last_tag = @tags.pop
 | 
			
		||||
              #md = @source.match_to_consume( '>', CLOSE_MATCH)
 | 
			
		||||
              md = @source.match( CLOSE_MATCH, true )
 | 
			
		||||
              raise REXML::ParseException.new( "Missing end tag for "+
 | 
			
		||||
                "'#{last_tag}' (got \"#{md[1]}\")",
 | 
			
		||||
                @source) unless last_tag == md[1]
 | 
			
		||||
              if md.nil? or last_tag != md[1]
 | 
			
		||||
                message = "Missing end tag for '#{last_tag}'"
 | 
			
		||||
                message << " (got '#{md[1]}')" if md
 | 
			
		||||
                raise REXML::ParseException.new(message, @source)
 | 
			
		||||
              end
 | 
			
		||||
              return [ :end_element, last_tag ]
 | 
			
		||||
            elsif @source.buffer[1] == ?!
 | 
			
		||||
              md = @source.match(/\A(\s*[^>]*>)/um)
 | 
			
		||||
| 
						 | 
				
			
			@ -362,52 +357,17 @@ module REXML
 | 
			
		|||
              raise REXML::ParseException.new( "Declarations can only occur "+
 | 
			
		||||
                "in the doctype declaration.", @source)
 | 
			
		||||
            elsif @source.buffer[1] == ??
 | 
			
		||||
              md = @source.match( INSTRUCTION_PATTERN, true )
 | 
			
		||||
              return [ :processing_instruction, md[1], md[2] ] if md
 | 
			
		||||
              raise REXML::ParseException.new( "Bad instruction declaration",
 | 
			
		||||
                @source)
 | 
			
		||||
              return process_instruction
 | 
			
		||||
            else
 | 
			
		||||
              # Get the next tag
 | 
			
		||||
              md = @source.match(TAG_MATCH, true)
 | 
			
		||||
              unless md
 | 
			
		||||
                # Check for missing attribute quotes
 | 
			
		||||
                raise REXML::ParseException.new("missing attribute quote", @source) if @source.match(MISSING_ATTRIBUTE_QUOTES )
 | 
			
		||||
                raise REXML::ParseException.new("malformed XML: missing tag start", @source)
 | 
			
		||||
              end
 | 
			
		||||
              attributes = {}
 | 
			
		||||
              prefixes = Set.new
 | 
			
		||||
              prefixes << md[2] if md[2]
 | 
			
		||||
              @nsstack.unshift(curr_ns=Set.new)
 | 
			
		||||
              if md[4].size > 0
 | 
			
		||||
                attrs = md[4].scan( ATTRIBUTE_PATTERN )
 | 
			
		||||
                raise REXML::ParseException.new( "error parsing attributes: [#{attrs.join ', '}], excess = \"#$'\"", @source) if $' and $'.strip.size > 0
 | 
			
		||||
                attrs.each do |attr_name, prefix, local_part, quote, value|
 | 
			
		||||
                  if prefix == "xmlns"
 | 
			
		||||
                    if local_part == "xml"
 | 
			
		||||
                      if value != "http://www.w3.org/XML/1998/namespace"
 | 
			
		||||
                        msg = "The 'xml' prefix must not be bound to any other namespace "+
 | 
			
		||||
                        "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
 | 
			
		||||
                        raise REXML::ParseException.new( msg, @source, self )
 | 
			
		||||
                      end
 | 
			
		||||
                    elsif local_part == "xmlns"
 | 
			
		||||
                      msg = "The 'xmlns' prefix must not be declared "+
 | 
			
		||||
                      "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
 | 
			
		||||
                      raise REXML::ParseException.new( msg, @source, self)
 | 
			
		||||
                    end
 | 
			
		||||
                    curr_ns << local_part
 | 
			
		||||
                  elsif prefix
 | 
			
		||||
                    prefixes << prefix unless prefix == "xml"
 | 
			
		||||
                  end
 | 
			
		||||
 | 
			
		||||
                  if attributes.has_key?(attr_name)
 | 
			
		||||
                    msg = "Duplicate attribute #{attr_name.inspect}"
 | 
			
		||||
                    raise REXML::ParseException.new(msg, @source, self)
 | 
			
		||||
                  end
 | 
			
		||||
 | 
			
		||||
                  attributes[attr_name] = value
 | 
			
		||||
                end
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              attributes, closed = parse_attributes(prefixes, curr_ns)
 | 
			
		||||
              # Verify that all of the prefixes have been defined
 | 
			
		||||
              for prefix in prefixes
 | 
			
		||||
                unless @nsstack.find{|k| k.member?(prefix)}
 | 
			
		||||
| 
						 | 
				
			
			@ -415,7 +375,7 @@ module REXML
 | 
			
		|||
                end
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              if md[6]
 | 
			
		||||
              if closed
 | 
			
		||||
                @closed = md[1]
 | 
			
		||||
                @nsstack.shift
 | 
			
		||||
              else
 | 
			
		||||
| 
						 | 
				
			
			@ -438,7 +398,7 @@ module REXML
 | 
			
		|||
          raise
 | 
			
		||||
        rescue REXML::ParseException
 | 
			
		||||
          raise
 | 
			
		||||
        rescue Exception, NameError => error
 | 
			
		||||
        rescue => error
 | 
			
		||||
          raise REXML::ParseException.new( "Exception parsing",
 | 
			
		||||
            @source, self, (error ? error : $!) )
 | 
			
		||||
        end
 | 
			
		||||
| 
						 | 
				
			
			@ -508,6 +468,99 @@ module REXML
 | 
			
		|||
        return false if /\AUTF-16\z/i =~ xml_declaration_encoding
 | 
			
		||||
        true
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def process_instruction
 | 
			
		||||
        match_data = @source.match(INSTRUCTION_PATTERN, true)
 | 
			
		||||
        unless match_data
 | 
			
		||||
          message = "Invalid processing instruction node"
 | 
			
		||||
          raise REXML::ParseException.new(message, @source)
 | 
			
		||||
        end
 | 
			
		||||
        [:processing_instruction, match_data[1], match_data[2]]
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def parse_attributes(prefixes, curr_ns)
 | 
			
		||||
        attributes = {}
 | 
			
		||||
        closed = false
 | 
			
		||||
        match_data = @source.match(/^(.*?)(\/)?>/um, true)
 | 
			
		||||
        if match_data.nil?
 | 
			
		||||
          message = "Start tag isn't ended"
 | 
			
		||||
          raise REXML::ParseException.new(message, @source)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        raw_attributes = match_data[1]
 | 
			
		||||
        closed = !match_data[2].nil?
 | 
			
		||||
        return attributes, closed if raw_attributes.nil?
 | 
			
		||||
        return attributes, closed if raw_attributes.empty?
 | 
			
		||||
 | 
			
		||||
        scanner = StringScanner.new(raw_attributes)
 | 
			
		||||
        until scanner.eos?
 | 
			
		||||
          if scanner.scan(/\s+/)
 | 
			
		||||
            break if scanner.eos?
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          pos = scanner.pos
 | 
			
		||||
          loop do
 | 
			
		||||
            break if scanner.scan(ATTRIBUTE_PATTERN)
 | 
			
		||||
            unless scanner.scan(QNAME)
 | 
			
		||||
              message = "Invalid attribute name: <#{scanner.rest}>"
 | 
			
		||||
              raise REXML::ParseException.new(message, @source)
 | 
			
		||||
            end
 | 
			
		||||
            name = scanner[0]
 | 
			
		||||
            unless scanner.scan(/\s*=\s*/um)
 | 
			
		||||
              message = "Missing attribute equal: <#{name}>"
 | 
			
		||||
              raise REXML::ParseException.new(message, @source)
 | 
			
		||||
            end
 | 
			
		||||
            quote = scanner.scan(/['"]/)
 | 
			
		||||
            unless quote
 | 
			
		||||
              message = "Missing attribute value start quote: <#{name}>"
 | 
			
		||||
              raise REXML::ParseException.new(message, @source)
 | 
			
		||||
            end
 | 
			
		||||
            unless scanner.scan(/.*#{Regexp.escape(quote)}/um)
 | 
			
		||||
              match_data = @source.match(/^(.*?)(\/)?>/um, true)
 | 
			
		||||
              if match_data
 | 
			
		||||
                scanner << "/" if closed
 | 
			
		||||
                scanner << ">"
 | 
			
		||||
                scanner << match_data[1]
 | 
			
		||||
                scanner.pos = pos
 | 
			
		||||
                closed = !match_data[2].nil?
 | 
			
		||||
                next
 | 
			
		||||
              end
 | 
			
		||||
              message =
 | 
			
		||||
                "Missing attribute value end quote: <#{name}>: <#{quote}>"
 | 
			
		||||
              raise REXML::ParseException.new(message, @source)
 | 
			
		||||
            end
 | 
			
		||||
          end
 | 
			
		||||
          name = scanner[1]
 | 
			
		||||
          prefix = scanner[2]
 | 
			
		||||
          local_part = scanner[3]
 | 
			
		||||
          # quote = scanner[4]
 | 
			
		||||
          value = scanner[5]
 | 
			
		||||
          if prefix == "xmlns"
 | 
			
		||||
            if local_part == "xml"
 | 
			
		||||
              if value != "http://www.w3.org/XML/1998/namespace"
 | 
			
		||||
                msg = "The 'xml' prefix must not be bound to any other namespace "+
 | 
			
		||||
                  "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
 | 
			
		||||
                raise REXML::ParseException.new( msg, @source, self )
 | 
			
		||||
              end
 | 
			
		||||
            elsif local_part == "xmlns"
 | 
			
		||||
              msg = "The 'xmlns' prefix must not be declared "+
 | 
			
		||||
                "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
 | 
			
		||||
              raise REXML::ParseException.new( msg, @source, self)
 | 
			
		||||
            end
 | 
			
		||||
            curr_ns << local_part
 | 
			
		||||
          elsif prefix
 | 
			
		||||
            prefixes << prefix unless prefix == "xml"
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          if attributes.has_key?(name)
 | 
			
		||||
            msg = "Duplicate attribute #{name.inspect}"
 | 
			
		||||
            raise REXML::ParseException.new(msg, @source, self)
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
          attributes[name] = value
 | 
			
		||||
        end
 | 
			
		||||
        return attributes, closed
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,23 +16,65 @@ Gem::Specification.new do |spec|
 | 
			
		|||
  spec.homepage      = "https://github.com/ruby/rexml"
 | 
			
		||||
  spec.license       = "BSD-2-Clause"
 | 
			
		||||
 | 
			
		||||
  spec.files         = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile",
 | 
			
		||||
  "bin/console", "bin/setup", "lib/rexml/attlistdecl.rb", "lib/rexml/attribute.rb", "lib/rexml/cdata.rb",
 | 
			
		||||
  "lib/rexml/child.rb", "lib/rexml/comment.rb", "lib/rexml/doctype.rb", "lib/rexml/document.rb",
 | 
			
		||||
  "lib/rexml/dtd/attlistdecl.rb", "lib/rexml/dtd/dtd.rb", "lib/rexml/dtd/elementdecl.rb",
 | 
			
		||||
  "lib/rexml/dtd/entitydecl.rb", "lib/rexml/dtd/notationdecl.rb", "lib/rexml/element.rb",
 | 
			
		||||
  "lib/rexml/encoding.rb", "lib/rexml/entity.rb", "lib/rexml/formatters/default.rb",
 | 
			
		||||
  "lib/rexml/formatters/pretty.rb", "lib/rexml/formatters/transitive.rb", "lib/rexml/functions.rb",
 | 
			
		||||
  "lib/rexml/instruction.rb", "lib/rexml/light/node.rb", "lib/rexml/namespace.rb", "lib/rexml/node.rb",
 | 
			
		||||
  "lib/rexml/output.rb", "lib/rexml/parent.rb", "lib/rexml/parseexception.rb", "lib/rexml/parsers/baseparser.rb",
 | 
			
		||||
  "lib/rexml/parsers/lightparser.rb", "lib/rexml/parsers/pullparser.rb", "lib/rexml/parsers/sax2parser.rb",
 | 
			
		||||
  "lib/rexml/parsers/streamparser.rb", "lib/rexml/parsers/treeparser.rb",
 | 
			
		||||
  "lib/rexml/parsers/ultralightparser.rb", "lib/rexml/parsers/xpathparser.rb", "lib/rexml/quickpath.rb",
 | 
			
		||||
  "lib/rexml/rexml.rb", "lib/rexml/sax2listener.rb", "lib/rexml/security.rb", "lib/rexml/source.rb",
 | 
			
		||||
  "lib/rexml/streamlistener.rb", "lib/rexml/syncenumerator.rb", "lib/rexml/text.rb",
 | 
			
		||||
  "lib/rexml/undefinednamespaceexception.rb", "lib/rexml/validation/relaxng.rb",
 | 
			
		||||
  "lib/rexml/validation/validation.rb", "lib/rexml/validation/validationexception.rb", "lib/rexml/xmldecl.rb",
 | 
			
		||||
  "lib/rexml/xmltokens.rb", "lib/rexml/xpath.rb", "lib/rexml/xpath_parser.rb", "rexml.gemspec"]
 | 
			
		||||
  spec.files         = [
 | 
			
		||||
    ".gitignore",
 | 
			
		||||
    ".travis.yml",
 | 
			
		||||
    "Gemfile",
 | 
			
		||||
    "LICENSE.txt",
 | 
			
		||||
    "README.md",
 | 
			
		||||
    "Rakefile",
 | 
			
		||||
    "lib/rexml/attlistdecl.rb",
 | 
			
		||||
    "lib/rexml/attribute.rb",
 | 
			
		||||
    "lib/rexml/cdata.rb",
 | 
			
		||||
    "lib/rexml/child.rb",
 | 
			
		||||
    "lib/rexml/comment.rb",
 | 
			
		||||
    "lib/rexml/doctype.rb",
 | 
			
		||||
    "lib/rexml/document.rb",
 | 
			
		||||
    "lib/rexml/dtd/attlistdecl.rb",
 | 
			
		||||
    "lib/rexml/dtd/dtd.rb",
 | 
			
		||||
    "lib/rexml/dtd/elementdecl.rb",
 | 
			
		||||
    "lib/rexml/dtd/entitydecl.rb",
 | 
			
		||||
    "lib/rexml/dtd/notationdecl.rb",
 | 
			
		||||
    "lib/rexml/element.rb",
 | 
			
		||||
    "lib/rexml/encoding.rb",
 | 
			
		||||
    "lib/rexml/entity.rb",
 | 
			
		||||
    "lib/rexml/formatters/default.rb",
 | 
			
		||||
    "lib/rexml/formatters/pretty.rb",
 | 
			
		||||
    "lib/rexml/formatters/transitive.rb",
 | 
			
		||||
    "lib/rexml/functions.rb",
 | 
			
		||||
    "lib/rexml/instruction.rb",
 | 
			
		||||
    "lib/rexml/light/node.rb",
 | 
			
		||||
    "lib/rexml/namespace.rb",
 | 
			
		||||
    "lib/rexml/node.rb",
 | 
			
		||||
    "lib/rexml/output.rb",
 | 
			
		||||
    "lib/rexml/parent.rb",
 | 
			
		||||
    "lib/rexml/parseexception.rb",
 | 
			
		||||
    "lib/rexml/parsers/baseparser.rb",
 | 
			
		||||
    "lib/rexml/parsers/lightparser.rb",
 | 
			
		||||
    "lib/rexml/parsers/pullparser.rb",
 | 
			
		||||
    "lib/rexml/parsers/sax2parser.rb",
 | 
			
		||||
    "lib/rexml/parsers/streamparser.rb",
 | 
			
		||||
    "lib/rexml/parsers/treeparser.rb",
 | 
			
		||||
    "lib/rexml/parsers/ultralightparser.rb",
 | 
			
		||||
    "lib/rexml/parsers/xpathparser.rb",
 | 
			
		||||
    "lib/rexml/quickpath.rb",
 | 
			
		||||
    "lib/rexml/rexml.rb",
 | 
			
		||||
    "lib/rexml/sax2listener.rb",
 | 
			
		||||
    "lib/rexml/security.rb",
 | 
			
		||||
    "lib/rexml/source.rb",
 | 
			
		||||
    "lib/rexml/streamlistener.rb",
 | 
			
		||||
    "lib/rexml/syncenumerator.rb",
 | 
			
		||||
    "lib/rexml/text.rb",
 | 
			
		||||
    "lib/rexml/undefinednamespaceexception.rb",
 | 
			
		||||
    "lib/rexml/validation/relaxng.rb",
 | 
			
		||||
    "lib/rexml/validation/validation.rb",
 | 
			
		||||
    "lib/rexml/validation/validationexception.rb",
 | 
			
		||||
    "lib/rexml/xmldecl.rb",
 | 
			
		||||
    "lib/rexml/xmltokens.rb",
 | 
			
		||||
    "lib/rexml/xpath.rb",
 | 
			
		||||
    "lib/rexml/xpath_parser.rb",
 | 
			
		||||
    "rexml.gemspec",
 | 
			
		||||
  ]
 | 
			
		||||
  spec.bindir        = "exe"
 | 
			
		||||
  spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
 | 
			
		||||
  spec.require_paths = ["lib"]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
# -*- encoding: utf-8 -*-
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# frozen_string_literal: false
 | 
			
		||||
# REXML is an XML toolkit for Ruby[http://www.ruby-lang.org], in Ruby.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -24,8 +24,8 @@
 | 
			
		|||
module REXML
 | 
			
		||||
  COPYRIGHT = "Copyright © 2001-2008 Sean Russell <ser@germane-software.com>"
 | 
			
		||||
  DATE = "2008/019"
 | 
			
		||||
  VERSION = "3.1.7.3"
 | 
			
		||||
  REVISION = %w$Revision$[1] || ''
 | 
			
		||||
  VERSION = "3.1.8"
 | 
			
		||||
  REVISION = ""
 | 
			
		||||
 | 
			
		||||
  Copyright = COPYRIGHT
 | 
			
		||||
  Version = VERSION
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -254,6 +254,7 @@ module REXML
 | 
			
		|||
          end
 | 
			
		||||
        rescue
 | 
			
		||||
        end
 | 
			
		||||
        @er_source.seek(pos)
 | 
			
		||||
      rescue IOError
 | 
			
		||||
        pos = -1
 | 
			
		||||
        line = -1
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,27 +96,28 @@ module REXML
 | 
			
		|||
 | 
			
		||||
      @raw = false
 | 
			
		||||
      @parent = nil
 | 
			
		||||
      @entity_filter = nil
 | 
			
		||||
 | 
			
		||||
      if parent
 | 
			
		||||
        super( parent )
 | 
			
		||||
        @raw = parent.raw
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      @raw = raw unless raw.nil?
 | 
			
		||||
      @entity_filter = entity_filter
 | 
			
		||||
      clear_cache
 | 
			
		||||
 | 
			
		||||
      if arg.kind_of? String
 | 
			
		||||
        @string = arg.dup
 | 
			
		||||
        @string.squeeze!(" \n\t") unless respect_whitespace
 | 
			
		||||
      elsif arg.kind_of? Text
 | 
			
		||||
        @string = arg.to_s
 | 
			
		||||
        @string = arg.instance_variable_get(:@string).dup
 | 
			
		||||
        @raw = arg.raw
 | 
			
		||||
        @entity_filter = arg.instance_variable_get(:@entity_filter)
 | 
			
		||||
      elsif
 | 
			
		||||
        raise "Illegal argument of type #{arg.type} for Text constructor (#{arg})"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      @string.gsub!( /\r\n?/, "\n" )
 | 
			
		||||
      @string.squeeze!(" \n\t") unless respect_whitespace
 | 
			
		||||
      @string.gsub!(/\r\n?/, "\n")
 | 
			
		||||
      @raw = raw unless raw.nil?
 | 
			
		||||
      @entity_filter = entity_filter if entity_filter
 | 
			
		||||
      clear_cache
 | 
			
		||||
 | 
			
		||||
      Text.check(@string, illegal, doctype) if @raw
 | 
			
		||||
    end
 | 
			
		||||
| 
						 | 
				
			
			@ -181,7 +182,7 @@ module REXML
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
    def clone
 | 
			
		||||
      return Text.new(self)
 | 
			
		||||
      return Text.new(self, true)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -226,9 +227,7 @@ module REXML
 | 
			
		|||
    #   u.to_s   #-> "sean russell"
 | 
			
		||||
    def to_s
 | 
			
		||||
      return @string if @raw
 | 
			
		||||
      return @normalized if @normalized
 | 
			
		||||
 | 
			
		||||
      @normalized = Text::normalize( @string, doctype, @entity_filter )
 | 
			
		||||
      @normalized ||= Text::normalize( @string, doctype, @entity_filter )
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def inspect
 | 
			
		||||
| 
						 | 
				
			
			@ -249,8 +248,7 @@ module REXML
 | 
			
		|||
    #   u = Text.new( "sean russell", false, nil, true )
 | 
			
		||||
    #   u.value   #-> "sean russell"
 | 
			
		||||
    def value
 | 
			
		||||
      return @unnormalized if @unnormalized
 | 
			
		||||
      @unnormalized = Text::unnormalize( @string, doctype )
 | 
			
		||||
      @unnormalized ||= Text::unnormalize( @string, doctype )
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    # Sets the contents of this text node.  This expects the text to be
 | 
			
		||||
| 
						 | 
				
			
			@ -266,16 +264,16 @@ module REXML
 | 
			
		|||
      @raw = false
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
     def wrap(string, width, addnewline=false)
 | 
			
		||||
       # Recursively wrap string at width.
 | 
			
		||||
       return string if string.length <= width
 | 
			
		||||
       place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
 | 
			
		||||
       if addnewline then
 | 
			
		||||
         return "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width)
 | 
			
		||||
       else
 | 
			
		||||
         return string[0,place] + "\n" + wrap(string[place+1..-1], width)
 | 
			
		||||
       end
 | 
			
		||||
     end
 | 
			
		||||
    def wrap(string, width, addnewline=false)
 | 
			
		||||
      # Recursively wrap string at width.
 | 
			
		||||
      return string if string.length <= width
 | 
			
		||||
      place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
 | 
			
		||||
      if addnewline then
 | 
			
		||||
        return "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width)
 | 
			
		||||
      else
 | 
			
		||||
        return string[0,place] + "\n" + wrap(string[place+1..-1], width)
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def indent_text(string, level=1, style="\t", indentfirstline=true)
 | 
			
		||||
      return string if level < 0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
# frozen_string_literal: false
 | 
			
		||||
 | 
			
		||||
require_relative 'encoding'
 | 
			
		||||
require_relative 'source'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -7,11 +8,11 @@ module REXML
 | 
			
		|||
  class XMLDecl < Child
 | 
			
		||||
    include Encoding
 | 
			
		||||
 | 
			
		||||
    DEFAULT_VERSION = "1.0";
 | 
			
		||||
    DEFAULT_ENCODING = "UTF-8";
 | 
			
		||||
    DEFAULT_STANDALONE = "no";
 | 
			
		||||
    START = '<\?xml';
 | 
			
		||||
    STOP = '\?>';
 | 
			
		||||
    DEFAULT_VERSION = "1.0"
 | 
			
		||||
    DEFAULT_ENCODING = "UTF-8"
 | 
			
		||||
    DEFAULT_STANDALONE = "no"
 | 
			
		||||
    START = "<?xml"
 | 
			
		||||
    STOP = "?>"
 | 
			
		||||
 | 
			
		||||
    attr_accessor :version, :standalone
 | 
			
		||||
    attr_reader :writeencoding, :writethis
 | 
			
		||||
| 
						 | 
				
			
			@ -46,9 +47,9 @@ module REXML
 | 
			
		|||
    #   Ignored
 | 
			
		||||
    def write(writer, indent=-1, transitive=false, ie_hack=false)
 | 
			
		||||
      return nil unless @writethis or writer.kind_of? Output
 | 
			
		||||
      writer << START.sub(/\\/u, '')
 | 
			
		||||
      writer << START
 | 
			
		||||
      writer << " #{content encoding}"
 | 
			
		||||
      writer << STOP.sub(/\\/u, '')
 | 
			
		||||
      writer << STOP
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def ==( other )
 | 
			
		||||
| 
						 | 
				
			
			@ -102,14 +103,26 @@ module REXML
 | 
			
		|||
    end
 | 
			
		||||
 | 
			
		||||
    def inspect
 | 
			
		||||
      START.sub(/\\/u, '') + " ... " + STOP.sub(/\\/u, '')
 | 
			
		||||
      "#{START} ... #{STOP}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
    def content(enc)
 | 
			
		||||
      rv = "version='#@version'"
 | 
			
		||||
      rv << " encoding='#{enc}'" if @writeencoding || enc !~ /\Autf-8\z/i
 | 
			
		||||
      rv << " standalone='#@standalone'" if @standalone
 | 
			
		||||
      context = nil
 | 
			
		||||
      context = parent.context if parent
 | 
			
		||||
      if context and context[:prologue_quote] == :quote
 | 
			
		||||
        quote = "\""
 | 
			
		||||
      else
 | 
			
		||||
        quote = "'"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      rv = "version=#{quote}#{@version}#{quote}"
 | 
			
		||||
      if @writeencoding or enc !~ /\Autf-8\z/i
 | 
			
		||||
        rv << " encoding=#{quote}#{enc}#{quote}"
 | 
			
		||||
      end
 | 
			
		||||
      if @standalone
 | 
			
		||||
        rv << " standalone=#{quote}#{@standalone}#{quote}"
 | 
			
		||||
      end
 | 
			
		||||
      rv
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ describe "REXML::Attribute#inspect" do
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  it "does not escape text" do
 | 
			
		||||
    a = REXML::Attribute.new("&&", "<>")
 | 
			
		||||
    a.inspect.should == "&&='<>'"
 | 
			
		||||
    a = REXML::Attribute.new("name", "<>")
 | 
			
		||||
    a.inspect.should == "name='<>'"
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
<?xml version="1.0" encoding="ISO-8859-1"?><?pos="3"?>
 | 
			
		||||
<?xml version="1.0" encoding="ISO-8859-1"?>
 | 
			
		||||
<!-- generated by hnb 1.9.17 (http://hnb.sourceforge.net) -->
 | 
			
		||||
 | 
			
		||||
<!DOCTYPE tree[
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										19
									
								
								test/rexml/formatter/test_default.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								test/rexml/formatter/test_default.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
require_relative "../rexml_test_utils"
 | 
			
		||||
 | 
			
		||||
module REXMLTests
 | 
			
		||||
  class DefaultFormatterTest < Test::Unit::TestCase
 | 
			
		||||
    def format(node)
 | 
			
		||||
      formatter = REXML::Formatters::Default.new
 | 
			
		||||
      output = ""
 | 
			
		||||
      formatter.write(node, output)
 | 
			
		||||
      output
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class InstructionTest < self
 | 
			
		||||
      def test_content_nil
 | 
			
		||||
        instruction = REXML::Instruction.new("target")
 | 
			
		||||
        assert_equal("<?target?>", format(instruction))
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										38
									
								
								test/rexml/parse/test_element.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								test/rexml/parse/test_element.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
require "test/unit"
 | 
			
		||||
require "rexml/document"
 | 
			
		||||
 | 
			
		||||
module REXMLTests
 | 
			
		||||
  class TestParseElement < Test::Unit::TestCase
 | 
			
		||||
    def parse(xml)
 | 
			
		||||
      REXML::Document.new(xml)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class TestInvalid < self
 | 
			
		||||
      def test_no_end_tag
 | 
			
		||||
        exception = assert_raise(REXML::ParseException) do
 | 
			
		||||
          parse("<a></")
 | 
			
		||||
        end
 | 
			
		||||
        assert_equal(<<-DETAIL.chomp, exception.to_s)
 | 
			
		||||
Missing end tag for 'a'
 | 
			
		||||
Line: 1
 | 
			
		||||
Position: 5
 | 
			
		||||
Last 80 unconsumed characters:
 | 
			
		||||
</
 | 
			
		||||
        DETAIL
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def test_empty_namespace_attribute_name
 | 
			
		||||
        exception = assert_raise(REXML::ParseException) do
 | 
			
		||||
          parse("<x :a=\"\"></x>")
 | 
			
		||||
        end
 | 
			
		||||
        assert_equal(<<-DETAIL.chomp, exception.to_s)
 | 
			
		||||
Invalid attribute name: <:a="">
 | 
			
		||||
Line: 1
 | 
			
		||||
Position: 9
 | 
			
		||||
Last 80 unconsumed characters:
 | 
			
		||||
 | 
			
		||||
        DETAIL
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										25
									
								
								test/rexml/parse/test_processing_instruction.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/rexml/parse/test_processing_instruction.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
require "test/unit"
 | 
			
		||||
require "rexml/document"
 | 
			
		||||
 | 
			
		||||
module REXMLTests
 | 
			
		||||
  class TestParseProcessinInstruction < Test::Unit::TestCase
 | 
			
		||||
    def parse(xml)
 | 
			
		||||
      REXML::Document.new(xml)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    class TestInvalid < self
 | 
			
		||||
      def test_no_name
 | 
			
		||||
        exception = assert_raise(REXML::ParseException) do
 | 
			
		||||
          parse("<??>")
 | 
			
		||||
        end
 | 
			
		||||
        assert_equal(<<-DETAIL.chomp, exception.to_s)
 | 
			
		||||
Invalid processing instruction node
 | 
			
		||||
Line: 1
 | 
			
		||||
Position: 4
 | 
			
		||||
Last 80 unconsumed characters:
 | 
			
		||||
<??>
 | 
			
		||||
        DETAIL
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ class TestTreeParser < Test::Unit::TestCase
 | 
			
		|||
        parse(xml)
 | 
			
		||||
      end
 | 
			
		||||
      assert_equal(<<-MESSAGE, exception.to_s)
 | 
			
		||||
Missing end tag for 'root' (got "not-root")
 | 
			
		||||
Missing end tag for 'root' (got 'not-root')
 | 
			
		||||
Line: 1
 | 
			
		||||
Position: #{xml.bytesize}
 | 
			
		||||
Last 80 unconsumed characters:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ class TestUltraLightParser < Test::Unit::TestCase
 | 
			
		|||
        normalized_doctype[1] = normalized_parent
 | 
			
		||||
        normalized_doctype
 | 
			
		||||
      when :start_element
 | 
			
		||||
        tag, parent, name, attributes, *children = child
 | 
			
		||||
        tag, _parent, name, attributes, *children = child
 | 
			
		||||
        normalized_parent = :parent
 | 
			
		||||
        normalized_children = children.collect do |sub_child|
 | 
			
		||||
          normalize_child(sub_child)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								test/rexml/test_attribute.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								test/rexml/test_attribute.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
require_relative "rexml_test_utils"
 | 
			
		||||
 | 
			
		||||
module REXMLTests
 | 
			
		||||
  class AttributeTest < Test::Unit::TestCase
 | 
			
		||||
    def test_empty_prefix
 | 
			
		||||
      error = assert_raise(ArgumentError) do
 | 
			
		||||
        REXML::Attribute.new(":x")
 | 
			
		||||
      end
 | 
			
		||||
      assert_equal("name must be " +
 | 
			
		||||
                   "\#{PREFIX}:\#{LOCAL_NAME} or \#{LOCAL_NAME}: <\":x\">",
 | 
			
		||||
                   error.message)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -1274,14 +1274,15 @@ EOL
 | 
			
		|||
 | 
			
		||||
    def test_ticket_21
 | 
			
		||||
      src = "<foo bar=value/>"
 | 
			
		||||
      assert_raise( ParseException, "invalid XML should be caught" ) {
 | 
			
		||||
      exception = assert_raise(ParseException) do
 | 
			
		||||
        Document.new(src)
 | 
			
		||||
      }
 | 
			
		||||
      begin
 | 
			
		||||
        Document.new(src)
 | 
			
		||||
      rescue
 | 
			
		||||
        assert_match( /missing attribute quote/, $!.message )
 | 
			
		||||
      end
 | 
			
		||||
      assert_equal(<<-DETAIL, exception.to_s)
 | 
			
		||||
Missing attribute value start quote: <bar>
 | 
			
		||||
Line: 1
 | 
			
		||||
Position: 16
 | 
			
		||||
Last 80 unconsumed characters:
 | 
			
		||||
      DETAIL
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_ticket_63
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,68 +1,92 @@
 | 
			
		|||
# frozen_string_literal: false
 | 
			
		||||
require 'test/unit'
 | 
			
		||||
require 'rexml/document'
 | 
			
		||||
 | 
			
		||||
require_relative "rexml_test_utils"
 | 
			
		||||
 | 
			
		||||
module REXMLTests
 | 
			
		||||
  class TestDocTypeAccessor < Test::Unit::TestCase
 | 
			
		||||
 | 
			
		||||
    def setup
 | 
			
		||||
      @sysid = "urn:x-test:sysid1"
 | 
			
		||||
      @notid1 = "urn:x-test:notation1"
 | 
			
		||||
      @notid2 = "urn:x-test:notation2"
 | 
			
		||||
      document_string1 = <<-"XMLEND"
 | 
			
		||||
      <!DOCTYPE r SYSTEM "#{@sysid}" [
 | 
			
		||||
        <!NOTATION n1 SYSTEM "#{@notid1}">
 | 
			
		||||
        <!NOTATION n2 SYSTEM "#{@notid2}">
 | 
			
		||||
      @notation_id1 = "urn:x-test:notation1"
 | 
			
		||||
      @notation_id2 = "urn:x-test:notation2"
 | 
			
		||||
      xml_system = <<-XML
 | 
			
		||||
      <!DOCTYPE root SYSTEM "#{@sysid}" [
 | 
			
		||||
        <!NOTATION n1 SYSTEM "#{@notation_id1}">
 | 
			
		||||
        <!NOTATION n2 SYSTEM "#{@notation_id2}">
 | 
			
		||||
      ]>
 | 
			
		||||
      <r/>
 | 
			
		||||
      XMLEND
 | 
			
		||||
      @doctype1 = REXML::Document.new(document_string1).doctype
 | 
			
		||||
      <root/>
 | 
			
		||||
      XML
 | 
			
		||||
      @doc_type_system = REXML::Document.new(xml_system).doctype
 | 
			
		||||
 | 
			
		||||
      @pubid = "TEST_ID"
 | 
			
		||||
      document_string2 = <<-"XMLEND"
 | 
			
		||||
      <!DOCTYPE r PUBLIC "#{@pubid}">
 | 
			
		||||
      <r/>
 | 
			
		||||
      XMLEND
 | 
			
		||||
      @doctype2 = REXML::Document.new(document_string2).doctype
 | 
			
		||||
 | 
			
		||||
      document_string3 = <<-"XMLEND"
 | 
			
		||||
      <!DOCTYPE r PUBLIC "#{@pubid}" "#{@sysid}">
 | 
			
		||||
      <r/>
 | 
			
		||||
      XMLEND
 | 
			
		||||
      @doctype3 = REXML::Document.new(document_string3).doctype
 | 
			
		||||
      xml_public = <<-XML
 | 
			
		||||
      <!DOCTYPE root PUBLIC "#{@pubid}">
 | 
			
		||||
      <root/>
 | 
			
		||||
      XML
 | 
			
		||||
      @doc_type_public = REXML::Document.new(xml_public).doctype
 | 
			
		||||
 | 
			
		||||
      xml_public_system = <<-XML
 | 
			
		||||
      <!DOCTYPE root PUBLIC "#{@pubid}" "#{@sysid}">
 | 
			
		||||
      <root/>
 | 
			
		||||
      XML
 | 
			
		||||
      @doc_type_public_system = REXML::Document.new(xml_public_system).doctype
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_public
 | 
			
		||||
      assert_equal(nil, @doctype1.public)
 | 
			
		||||
      assert_equal(@pubid, @doctype2.public)
 | 
			
		||||
      assert_equal(@pubid, @doctype3.public)
 | 
			
		||||
      assert_equal([
 | 
			
		||||
                     nil,
 | 
			
		||||
                     @pubid,
 | 
			
		||||
                     @pubid,
 | 
			
		||||
                   ],
 | 
			
		||||
                   [
 | 
			
		||||
                     @doc_type_system.public,
 | 
			
		||||
                     @doc_type_public.public,
 | 
			
		||||
                     @doc_type_public_system.public,
 | 
			
		||||
                   ])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_to_s
 | 
			
		||||
      assert_equal("<!DOCTYPE root PUBLIC \"#{@pubid}\" \"#{@sysid}\">",
 | 
			
		||||
                   @doc_type_public_system.to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_to_s_apostrophe
 | 
			
		||||
      @doc_type_public_system.parent.context[:prologue_quote] = :apostrophe
 | 
			
		||||
      assert_equal("<!DOCTYPE root PUBLIC '#{@pubid}' '#{@sysid}'>",
 | 
			
		||||
                   @doc_type_public_system.to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_system
 | 
			
		||||
      assert_equal(@sysid, @doctype1.system)
 | 
			
		||||
      assert_equal(nil, @doctype2.system)
 | 
			
		||||
      assert_equal(@sysid, @doctype3.system)
 | 
			
		||||
      assert_equal([
 | 
			
		||||
                     @sysid,
 | 
			
		||||
                     nil,
 | 
			
		||||
                     @sysid,
 | 
			
		||||
                   ],
 | 
			
		||||
                   [
 | 
			
		||||
                     @doc_type_system.system,
 | 
			
		||||
                     @doc_type_public.system,
 | 
			
		||||
                     @doc_type_public_system.system,
 | 
			
		||||
                   ])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_notation
 | 
			
		||||
      assert_equal(@notid1, @doctype1.notation("n1").system)
 | 
			
		||||
      assert_equal(@notid2, @doctype1.notation("n2").system)
 | 
			
		||||
      assert_equal([
 | 
			
		||||
                     @notation_id1,
 | 
			
		||||
                     @notation_id2,
 | 
			
		||||
                   ],
 | 
			
		||||
                   [
 | 
			
		||||
                     @doc_type_system.notation("n1").system,
 | 
			
		||||
                     @doc_type_system.notation("n2").system,
 | 
			
		||||
                   ])
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_notations
 | 
			
		||||
      notations = @doctype1.notations
 | 
			
		||||
      assert_equal(2, notations.length)
 | 
			
		||||
      assert_equal(@notid1, find_notation(notations, "n1").system)
 | 
			
		||||
      assert_equal(@notid2, find_notation(notations, "n2").system)
 | 
			
		||||
      notations = @doc_type_system.notations
 | 
			
		||||
      assert_equal([
 | 
			
		||||
                     @notation_id1,
 | 
			
		||||
                     @notation_id2,
 | 
			
		||||
                   ],
 | 
			
		||||
                   notations.collect(&:system))
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def find_notation(notations, name)
 | 
			
		||||
      notations.find { |notation|
 | 
			
		||||
        name == notation.name
 | 
			
		||||
      }
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class TestNotationDeclPublic < Test::Unit::TestCase
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +106,19 @@ module REXMLTests
 | 
			
		|||
                   decl(@id, @uri).to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_to_s_apostrophe
 | 
			
		||||
      document = REXML::Document.new(<<-XML)
 | 
			
		||||
      <!DOCTYPE root SYSTEM "urn:x-test:sysid" [
 | 
			
		||||
        #{decl(@id, @uri).to_s}
 | 
			
		||||
      ]>
 | 
			
		||||
      <root/>
 | 
			
		||||
      XML
 | 
			
		||||
      document.context[:prologue_quote] = :apostrophe
 | 
			
		||||
      notation = document.doctype.notations[0]
 | 
			
		||||
      assert_equal("<!NOTATION #{@name} PUBLIC '#{@id}' '#{@uri}'>",
 | 
			
		||||
                   notation.to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
    def decl(id, uri)
 | 
			
		||||
      REXML::NotationDecl.new(@name, "PUBLIC", id, uri)
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +136,19 @@ module REXMLTests
 | 
			
		|||
                   decl(@id).to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_to_s_apostrophe
 | 
			
		||||
      document = REXML::Document.new(<<-XML)
 | 
			
		||||
      <!DOCTYPE root SYSTEM "urn:x-test:sysid" [
 | 
			
		||||
        #{decl(@id).to_s}
 | 
			
		||||
      ]>
 | 
			
		||||
      <root/>
 | 
			
		||||
      XML
 | 
			
		||||
      document.context[:prologue_quote] = :apostrophe
 | 
			
		||||
      notation = document.doctype.notations[0]
 | 
			
		||||
      assert_equal("<!NOTATION #{@name} SYSTEM '#{@id}'>",
 | 
			
		||||
                   notation.to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    private
 | 
			
		||||
    def decl(id)
 | 
			
		||||
      REXML::NotationDecl.new(@name, "SYSTEM", id, nil)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								test/rexml/test_instruction.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								test/rexml/test_instruction.rb
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
require_relative "rexml_test_utils"
 | 
			
		||||
 | 
			
		||||
module REXMLTests
 | 
			
		||||
  class InstructionTest < Test::Unit::TestCase
 | 
			
		||||
    def test_target_nil
 | 
			
		||||
      error = assert_raise(ArgumentError) do
 | 
			
		||||
        REXML::Instruction.new(nil)
 | 
			
		||||
      end
 | 
			
		||||
      assert_equal("processing instruction target must be String or " +
 | 
			
		||||
                   "REXML::Instruction: <nil>",
 | 
			
		||||
                   error.message)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -15,8 +15,8 @@ module REXMLTests
 | 
			
		|||
    def test_listener
 | 
			
		||||
      data = %Q{<session1 user="han" password="rootWeiler" />\n<session2 user="han" password="rootWeiler" />}
 | 
			
		||||
 | 
			
		||||
      b = RequestReader.new( data )
 | 
			
		||||
      b = RequestReader.new( data )
 | 
			
		||||
      RequestReader.new( data )
 | 
			
		||||
      RequestReader.new( data )
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_ticket_49
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,52 @@ module REXMLTests
 | 
			
		|||
  class TextTester < Test::Unit::TestCase
 | 
			
		||||
    include REXML
 | 
			
		||||
 | 
			
		||||
    def test_new_text_response_whitespace_default
 | 
			
		||||
      text = Text.new("a  b\t\tc", true)
 | 
			
		||||
      assert_equal("a b\tc", Text.new(text).to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_new_text_response_whitespace_true
 | 
			
		||||
      text = Text.new("a  b\t\tc", true)
 | 
			
		||||
      assert_equal("a  b\t\tc", Text.new(text, true).to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_new_text_raw_default
 | 
			
		||||
      text = Text.new("&lt;", false, nil, true)
 | 
			
		||||
      assert_equal("&lt;", Text.new(text).to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_new_text_raw_false
 | 
			
		||||
      text = Text.new("&lt;", false, nil, true)
 | 
			
		||||
      assert_equal("&amp;lt;", Text.new(text, false, nil, false).to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_new_text_entity_filter_default
 | 
			
		||||
      document = REXML::Document.new(<<-XML)
 | 
			
		||||
<!DOCTYPE root [
 | 
			
		||||
  <!ENTITY a "aaa">
 | 
			
		||||
  <!ENTITY b "bbb">
 | 
			
		||||
]>
 | 
			
		||||
<root/>
 | 
			
		||||
      XML
 | 
			
		||||
      text = Text.new("aaa bbb", false, document.root, nil, ["a"])
 | 
			
		||||
      assert_equal("aaa &b;",
 | 
			
		||||
                   Text.new(text, false, document.root).to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_new_text_entity_filter_custom
 | 
			
		||||
      document = REXML::Document.new(<<-XML)
 | 
			
		||||
<!DOCTYPE root [
 | 
			
		||||
  <!ENTITY a "aaa">
 | 
			
		||||
  <!ENTITY b "bbb">
 | 
			
		||||
]>
 | 
			
		||||
<root/>
 | 
			
		||||
      XML
 | 
			
		||||
      text = Text.new("aaa bbb", false, document.root, nil, ["a"])
 | 
			
		||||
      assert_equal("&a; bbb",
 | 
			
		||||
                   Text.new(text, false, document.root, nil, ["b"]).to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_shift_operator_chain
 | 
			
		||||
      text = Text.new("original\r\n")
 | 
			
		||||
      text << "append1\r\n" << "append2\r\n"
 | 
			
		||||
| 
						 | 
				
			
			@ -18,5 +64,11 @@ module REXMLTests
 | 
			
		|||
      text << "append3\r\n" << "append4\r\n"
 | 
			
		||||
      assert_equal("original\nappend1\nappend2\nappend3\nappend4\n", text.to_s)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_clone
 | 
			
		||||
      text = Text.new("&lt; <")
 | 
			
		||||
      assert_equal(text.to_s,
 | 
			
		||||
                   text.clone.to_s)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
# -*- coding: utf-8 -*-
 | 
			
		||||
# frozen_string_literal: false
 | 
			
		||||
#
 | 
			
		||||
#  Created by Henrik Mårtensson on 2007-02-18.
 | 
			
		||||
| 
						 | 
				
			
			@ -10,11 +9,11 @@ require "test/unit"
 | 
			
		|||
module REXMLTests
 | 
			
		||||
  class TestXmlDeclaration < Test::Unit::TestCase
 | 
			
		||||
    def setup
 | 
			
		||||
      xml = <<-'END_XML'
 | 
			
		||||
      xml = <<-XML
 | 
			
		||||
      <?xml encoding= 'UTF-8' standalone='yes'?>
 | 
			
		||||
      <root>
 | 
			
		||||
      </root>
 | 
			
		||||
      END_XML
 | 
			
		||||
      XML
 | 
			
		||||
      @doc = REXML::Document.new xml
 | 
			
		||||
      @root = @doc.root
 | 
			
		||||
      @xml_declaration = @doc.children[0]
 | 
			
		||||
| 
						 | 
				
			
			@ -32,5 +31,12 @@ module REXMLTests
 | 
			
		|||
      assert_kind_of(REXML::XMLDecl, @root.previous_sibling.previous_sibling)
 | 
			
		||||
      assert_kind_of(REXML::Element, @xml_declaration.next_sibling.next_sibling)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def test_write_prologue_quote
 | 
			
		||||
      @doc.context[:prologue_quote] = :quote
 | 
			
		||||
      assert_equal("<?xml version=\"1.0\" " +
 | 
			
		||||
                   "encoding=\"UTF-8\" standalone=\"yes\"?>",
 | 
			
		||||
                   @xml_declaration.to_s)
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue