#ruby #rexml
#ruby #rexml
Вопрос:
Я пытаюсь проанализировать log4j.xml файл, отредактируйте некоторые атрибуты и запишите его обратно.
The log4j.xml имеет <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
декларацию, но когда я пишу ее обратно, декларация меняется на <!DOCTYPE log4j>
.
Я открыл файл для синтаксического xmlDoc = Document.new(File.new(file, 'r'))
анализа и написал с xmlDoc.write(File.new(file, 'w'), 0)
помощью .
Я также пробовал открывать с xmlDoc = Document.new(File.new(file, 'r'), { :raw => :all })
помощью .
Есть ли способ сохранить исходное объявление DOCTYPE?
Большое вам спасибо!
Ответ №1:
Я боюсь, что это невозможно при rexml
использовании. Посмотрите на это краткое резюме — это «облегченная версия» процесса, который выполняется в rexml
библиотеке
require 'rexml/source'
LETTER = '[:alpha:]'
COMBININGCHAR = ''
EXTENDER = ''
NCNAME_STR= "[#{LETTER}_:][-[:alnum:]._:#{COMBININGCHAR}#{EXTENDER}]*"
IDENTITY = /^([!*w-] )(s #{NCNAME_STR})?(s ["'](.*?)['"])?(s ['"](.*?)["'])?/u
DOCTYPE_PATTERN = /s*<!DOCTYPEs (.*?)([|>)/um
string = <<HERE
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration>
</log4j:configuration>
HERE
source = REXML::SourceFactory.create_from(string)
md = source.match( DOCTYPE_PATTERN, true )
identity = md[1]
close = md[2]
identity =~ IDENTITY
name = $1
pub_sys = $2.nil? ? nil : $2.strip
long_name = $4.nil? ? nil : $4.strip
uri = $6.nil? ? nil : $6.strip
args = [ :start_doctype, name, pub_sys, long_name, uri ]
p args # => [:start_doctype, "log4j", nil, nil, nil]
Как вы можете видеть, этот фрагмент возвращает тот же результат, что и ваш код в вопросе. И помимо этого вы видите, что во фрагменте нет параметров, которые могли бы изменить это поведение.
В качестве обходного пути я могу предложить вам использовать Nokogiri
library . При быстром просмотре он может правильно проанализировать такой doctype:
require 'nokogiri'
string = <<HERE
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration>
</log4j:configuration>
HERE
doc = Nokogiri::XML(string)
puts doc.internal_subset.to_s
# => <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">