# frozen_string_literal: falserequire_relative"parent"require_relative"parseexception"require_relative"namespace"require_relative'entity'require_relative'attlistdecl'require_relative'xmltokens'moduleREXMLclassReferenceWriterdefinitialize(id_type,public_id_literal,system_literal,context=nil)@id_type=id_type@public_id_literal=public_id_literal@system_literal=system_literalifcontextandcontext[:prologue_quote]==:apostrophe@default_quote="'"else@default_quote="\""endenddefwrite(output)output<<" #{@id_type}"if@public_id_literalif@public_id_literal.include?("'")quote="\""elsequote=@default_quoteendoutput<<" #{quote}#{@public_id_literal}#{quote}"endif@system_literalif@system_literal.include?("'")quote="\""elsif@system_literal.include?("\"")quote="'"elsequote=@default_quoteendoutput<<" #{quote}#{@system_literal}#{quote}"endendend# 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.classDocType<ParentincludeXMLTokensSTART="<!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 givenattr_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## +Note+ that the constructor:## Doctype.new( Source.new( "<!DOCTYPE foo 'bar'>" ) )## is _deprecated_. Do not use it. It will probably disappear.definitialize(first,parent=nil)@entities=DEFAULT_ENTITIES@long_name=@uri=niliffirst.kind_of?Stringsuper()@name=first@external_id=parentelsiffirst.kind_of?DocTypesuper(parent)@name=first.name@external_id=first.external_id@long_name=first.instance_variable_get(:@long_name)@uri=first.instance_variable_get(:@uri)elsiffirst.kind_of?Arraysuper(parent)@name=first[0]@external_id=first[1]@long_name=first[2]@uri=first[3]elsiffirst.kind_of?Sourcesuper(parent)parser=Parsers::BaseParser.new(first)event=parser.pullifevent[0]==:start_doctype@name,@external_id,@long_name,@uri,=event[1..-1]endelsesuper()endenddefnode_type:doctypeenddefattributes_ofelementrv=[]eachdo|child|child.eachdo|key,val|rv<<Attribute.new(key,val)endifchild.kind_of?AttlistDeclandchild.element_name==elementendrvenddefattribute_ofelement,attributeatt_decl=finddo|child|child.kind_of?AttlistDeclandchild.element_name==elementandchild.include?attributeendreturnnilunlessatt_declatt_decl[attribute]enddefcloneDocType.newselfend# output::# Where to write the string# indent::# An integer. If -1, no indentation will be used; otherwise, the# indentation will be this number of spaces, and children will be# indented an additional amount.# transitive::# Ignored# ie_hack::# Ignoreddefwrite(output,indent=0,transitive=false,ie_hack=false)f=REXML::Formatters::Default.newindent(output,indent)output<<STARToutput<<' 'output<<@nameif@external_idreference_writer=ReferenceWriter.new(@external_id,@long_name,@uri,context)reference_writer.write(output)endunless@children.empty?output<<' ['@children.each{|child|output<<"\n"f.write(child,output)}output<<"\n]"endoutput<<STOPenddefcontextif@parent@parent.contextelsenilendenddefentity(name)@entities[name].unnormalizedif@entities[name]enddefaddchildsuper(child)@entities=DEFAULT_ENTITIES.cloneif@entities==DEFAULT_ENTITIES@entities[child.name]=childifchild.kind_of?Entityend# This method retrieves the public identifier identifying the document's# DTD.## Method contributed by Henrik Martenssondefpubliccase@external_idwhen"SYSTEM"nilwhen"PUBLIC"@long_nameendend# This method retrieves the system identifier identifying the document's DTD## Method contributed by Henrik Martenssondefsystemcase@external_idwhen"SYSTEM"@long_namewhen"PUBLIC"@uri.kind_of?(String)?@uri:nilendend# This method returns a list of notations that have been declared in the# _internal_ DTD subset. Notations in the external DTD subset are not# listed.## Method contributed by Henrik Martenssondefnotationschildren().select{|node|node.kind_of?(REXML::NotationDecl)}end# Retrieves a named notation. Only notations declared in the internal# DTD subset can be retrieved.## Method contributed by Henrik Martenssondefnotation(name)notations.find{|notation_decl|notation_decl.name==name}endend# 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.classDeclaration<Childdefinitializesrcsuper()@string=srcenddefto_s@string+'>'end# == DEPRECATED# See REXML::Formatters#defwrite(output,indent)output<<to_sendendpublicclassElementDecl<Declarationdefinitialize(src)superendendclassExternalEntity<Childdefinitialize(src)super()@entity=srcenddefto_s@entityenddefwrite(output,indent)output<<@entityendendclassNotationDecl<Childattr_accessor:public,:systemdefinitializename,middle,pub,syssuper(nil)@name=name@middle=middle@public=pub@system=sysenddefto_scontext=nilcontext=parent.contextifparentnotation="<!NOTATION #{@name}"reference_writer=ReferenceWriter.new(@middle,@public,@system,context)reference_writer.write(notation)notation<<">"notationenddefwrite(output,indent=-1)output<<to_send# This method retrieves the name of the notation.## Method contributed by Henrik Martenssondefname@nameendendend