REXML переносит длинные строки.Как мне это отключить? - PullRequest
2 голосов
/ 17 ноября 2010

Я создаю документ XML с использованием REXML

File.open(xmlFilename,'w') do |xmlFile|
    xmlDoc = Document.new
    # add stuff to the document...
    xmlDoc.write(xmlFile,4)
end

Некоторые элементы содержат довольно много аргументов, и, следовательно, соответствующие строки могут быть довольно длинными. Если они получают более 166 символов, REXML вставляет разрыв строки. Это, конечно, все еще совершенно допустимый XML, но мой рабочий процесс включает в себя некоторые сравнения и слияния, которые лучше всего работают, если каждый элемент содержится в одной строке.

Итак, есть ли способ заставить REXML не вставлять эти переносы строк?

Редактировать: В итоге я протолкнул готовый файл XML через tidy в качестве последнего шага моего сценария. Если бы кто-то знал более хороший способ сделать это, я все равно был бы благодарен.

Ответы [ 2 ]

3 голосов
/ 19 ноября 2010

Как сказал Райан Кэлхун в своем предыдущем ответе, REXML использует 80 в качестве длины строки переноса.Я уверен, что это ошибка (хотя я не мог найти отчет об ошибке только сейчас).Я смог исправить , переписав метод write_text класса Formatters :: Pretty, чтобы он использовал настраиваемый атрибут @width вместо жестко заданного 80.

require "rubygems"
require "rexml/document"
include REXML

long_xml = "<root><tag>As Ryan Calhoun said in his previous answer, REXML uses 80 as its wrap line length.  I'm pretty sure this is a bug (although I couldn't find a bug report just now).  I was able to *fix* it by overwriting the Formatters::Pretty class's write_text method.</tag></root>"

xml = Document.new(long_xml)

#fix bug in REXML::Formatters::Pretty
class MyPrecious < REXML::Formatters::Pretty
    def write_text( node, output )
        s = node.to_s()
        s.gsub!(/\s/,' ')
        s.squeeze!(" ")

        #The Pretty formatter code mistakenly used 80 instead of the @width variable
        #s = wrap(s, 80-@level)
        s = wrap(s, @width-@level)

        s = indent_text(s, @level, " ", true)
        output << (' '*@level + s)
    end
end

printer = MyPrecious.new(5)
printer.width = 1000
printer.compact = true
printer.write(xml, STDOUT)
1 голос
/ 18 ноября 2010

Краткий ответ: да и нет.

REXML использует различные средства форматирования в зависимости от значения, указанного вами для indent. Если вы оставите значение по умолчанию -1, он будет использовать REXML::Formatters::Default. Если вы дадите ему значение, подобное 4, оно будет использовать REXML::Formatters::Pretty. У симпатичного форматера есть логика для переноса строк (хотя, похоже, он переносится на 80, а не на 166), когда имеешь дело с текстом (не тегами или атрибутами). Например, содержимое

<p> a paragraph tag </p>

будет заключено в 80 символов, но

<a-tag with='a' long='list' of='attributes'/>

не будет упакован.

В любом случае, 80 жестко запрограммирован в rexml/formatters/pretty.rb и не настраивается. И если вы используете форматтер по умолчанию без отступа, то это в основном простой дамп без добавленных разрывов строк. Вы можете попробовать переходный форматер (см. Документацию для Document.write), но он не работает в какой-то версии ruby ​​и может потребовать взлома кода. В любом случае, это, вероятно, не то, что вы хотите.


Вы можете попробовать взглянуть на Builder::XmlMarkup из камня строителя.

...