diff options
author | ser <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-06-10 01:31:01 +0000 |
---|---|---|
committer | ser <ser@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-06-10 01:31:01 +0000 |
commit | ea7a527a2ae7024a5cf2885dee8f7a5c21fedd5d (patch) | |
tree | d3e1f95a5acf262a9dd46e9663b7034bb285b406 /lib/rexml/doctype.rb | |
parent | ca02190d8887ecd852e4e3f18f3a3ea91e9c6f7a (diff) | |
download | ruby-ea7a527a2ae7024a5cf2885dee8f7a5c21fedd5d.tar.gz |
Initial revision
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3925 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rexml/doctype.rb')
-rw-r--r-- | lib/rexml/doctype.rb | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/lib/rexml/doctype.rb b/lib/rexml/doctype.rb new file mode 100644 index 0000000000..d70ea6fd6c --- /dev/null +++ b/lib/rexml/doctype.rb @@ -0,0 +1,182 @@ +require "rexml/parent" +require "rexml/parseexception" +require "rexml/namespace" +require 'rexml/entity' +require 'rexml/attlistdecl' +require 'rexml/xmltokens' + +module REXML + # Represents an XML DOCTYPE declaration; that is, the contents of <!DOCTYPE + # ... >. DOCTYPES can be used to declare the DTD of a document, as well as + # being used to declare entities used in the document. + class DocType < Parent + include XMLTokens + START = "<!DOCTYPE" + STOP = ">" + SYSTEM = "SYSTEM" + PUBLIC = "PUBLIC" + DEFAULT_ENTITIES = { + 'gt'=>EntityConst::GT, + 'lt'=>EntityConst::LT, + 'quot'=>EntityConst::QUOT, + "apos"=>EntityConst::APOS + } + + # name is the name of the doctype + # external_id is the referenced DTD, if given + attr_reader :name, :external_id, :entities, :namespaces + + # Constructor + # + # dt = DocType.new( 'foo', '-//I/Hate/External/IDs' ) + # # <!DOCTYPE foo '-//I/Hate/External/IDs'> + # dt = DocType.new( doctype_to_clone ) + # # Incomplete. Shallow clone of doctype + # source = Source.new( '<!DOCTYPE foo "bar">' ) + # dt = DocType.new( source ) + # # <!DOCTYPE foo "bar"> + # dt = DocType.new( source, some_document ) + # # Creates a doctype, and adds to the supplied document + def initialize( first, parent=nil ) + @entities = DEFAULT_ENTITIES + @long_name = @uri = nil + if first.kind_of? String + super() + @name = first + @external_id = parent + elsif first.kind_of? DocType + super( parent ) + @name = first.name + @external_id = first.external_id + elsif first.kind_of? Array + super( parent ) + @name = first[0] + @external_id = first[1] + @long_name = first[2] + @uri = first[3] + end + end + + def node_type + :doctype + end + + def attributes_of element + rv = [] + each do |child| + child.each do |key,val| + rv << Attribute.new(key,val) + end if child.kind_of? AttlistDecl and child.element_name == element + end + rv + end + + def attribute_of element, attribute + att_decl = find do |child| + child.kind_of? AttlistDecl and + child.element_name == element and + child.include? attribute + end + return nil unless att_decl + att_decl[attribute] + end + + def clone + DocType.new self + end + + # output:: + # Where to write the string + # indent:: + # An integer. If -1, no indenting will be used; otherwise, the + # indentation will be this number of spaces, and children will be + # indented an additional amount. + # transitive:: + # Who knows? + # ie_hack:: + # Internet Explorer is the worst piece of crap to have ever been + # written, with the possible exception of Windows itself. Since IE is + # unable to parse proper XML, we have to provide a hack to generate XML + # that IE's limited abilities can handle. This hack inserts a space + # before the /> on empty tags. + # + def write( output, indent=0, transitive=false, ie_hack=false ) + indent( output, indent ) + output << START + output << ' ' + output << @name + output << " #@external_id" if @external_id + output << " #@long_name" if @long_name + output << " #@uri" if @uri + unless @children.empty? + next_indent = indent + 2 + output << ' [' + child = nil # speed + @children.each { |child| + output << "\n" + child.write( output, next_indent ) + } + output << "\n" + #output << ' '*next_indent + output << "]" + end + output << STOP + end + + def entity( name ) + @entities[name].unnormalized if @entities[name] + end + + def add child + super(child) + @entities = DEFAULT_ENTITIES.clone if @entities == DEFAULT_ENTITIES + @entities[ child.name ] = child if child.kind_of? Entity + end + end + + # We don't really handle any of these since we're not a validating + # parser, so we can be pretty dumb about them. All we need to be able + # to do is spew them back out on a write() + + # This is an abstract class. You never use this directly; it serves as a + # parent class for the specific declarations. + class Declaration < Child + def initialize src + super() + @string = src + end + + def to_s + @string+'>' + end + + def write( output, indent ) + output << (' '*indent) if indent > 0 + output << to_s + end + end + + public + class ElementDecl < Declaration + def initialize( src ) + super + end + end + + class NotationDecl < Child + def initialize name, middle, rest + @name = name + @middle = middle + @rest = rest + end + + def to_s + "<!NOTATION #@name #@middle #@rest>" + end + + def write( output, indent=-1 ) + output << (' '*indent) if indent > 0 + output << to_s + end + end +end |