Интерполяция строки XML, содержащей двойные кавычки и двоеточия в Ruby

В Ruby я получаю входящие данные из файла, представляющего XML-документ, но содержащего некоторый код интерполяции Ruby. Вот пример:

<ns1: xmlns:ns1="http://example.com" attr="#{Time.now}">

Теперь, когда я хочу оценить строку для разрешения ссылок Ruby, я попробовал следующее:

xs = '<ns1: xmlns:ns1="http://example.com" attr="#{Time.now}">'
eval("'" + xs + "'") #=> "<ns1: xmlns:ns1=\"http://example.com\" attr=\"\#{Time.now}\">"
eval %Q{"'" + #{xs} + "'"} # SyntaxError: (eval):1: syntax error, unexpected '<'
eval('"' + %Q{#{xs}} + '"') # SyntaxError: (eval):1: syntax error, unexpected tIDENTIFIER, expecting end-of-input

Я не знаю, как еще это сделать. Как я могу оценить строку с интерполяцией, чтобы получить следующее:

<ns1: xmlns:ns1="http://example.com" attr="2017-06-22 11:58:39 +0200">

person mydoghasworms    schedule 22.06.2017    source источник
comment
Если бы вы только могли изменить #{ } на <%= %> :)   -  person Sergio Tulentsev    schedule 22.06.2017
comment
@SergioTulentsev Да, но тогда, вероятно, мне нужно будет использовать ERB, и я просто хочу использовать встроенную возможность интерполяции, если это возможно.   -  person mydoghasworms    schedule 22.06.2017
comment
Использование ERB совсем не сложно. ERB.new(xs).result(binding). Вот и все. Заставить работать интерполяцию здесь будет более проблематично (если вообще возможно)   -  person Sergio Tulentsev    schedule 22.06.2017
comment
Я выбрал решение, включающее gsub и замену любых экземпляров синтаксиса интерполяции Ruby и оценку содержимого. (Так что на самом деле это не интерполяция, а дополнительные библиотеки не используются). Спасибо, в любом случае.   -  person mydoghasworms    schedule 22.06.2017
comment
@SergioTulentsev Почему бы вам не отправить предложение ERB в качестве ответа? Я думаю, что могу пойти на это сейчас, попробовав свое собственное решение.   -  person mydoghasworms    schedule 23.06.2017
comment
но он не использует никаких дополнительных библиотек - ERB встроен. Это не дополнительная библиотека.   -  person Sergio Tulentsev    schedule 23.06.2017


Ответы (2)


Как предложил Йорг, у вас будет гораздо больше опыта, если вы будете использовать один из языков шаблонов. Я предложил ERB, потому что он встроенный.

xs = '<ns1: xmlns:ns1="http://example.com" attr="<%= Time.now %>">'

require 'erb'
ERB.new(xs).result(binding) 
# => "<ns1: xmlns:ns1=\"http://example.com\" attr=\"2017-06-23 09:11:56 +0300\">"
person Sergio Tulentsev    schedule 23.06.2017

Вы не ищете интерполяцию строк. Вы ищете язык шаблонов.

Интерполяция строк предназначена для интерполяции кода Ruby в строковый (или символьный) литерал. У вас нет литерала, у вас есть ссылка на объект. Интерполяция строк не работает, она даже не применима к этой ситуации.

Вместо этого у вас есть язык шаблонов, синтаксис которого идентичен синтаксису интерполяции строк Ruby. Вам нужна реализация для этого языка; к сожалению, насколько я знаю, его нет, поэтому вам придется написать свой собственный. Написание очень простого, не очень надежного механизма шаблонов было популярным упражнением в Ruby пару лет назад, поэтому я случайно знаю, что это занимает всего пару минут (и строк). (Однако сделать его надежным, безопасным и защищенным перед лицом ненадежного произвольного ввода — это совсем другое дело.)

Если бы вы могли изменить формат ввода на существующий язык шаблонов, это было бы проще всего. Одним из хорошо известных языков шаблонов в мире Ruby является ERb, который на самом деле имеет реализацию в стандартной библиотеке. Есть также Тенджин, Ликвид, Рути, Усач и многие другие.

person Jörg W Mittag    schedule 22.06.2017
comment
Спасибо за ответ Йорг. Я думал, что я, вероятно, неправильно использую термин интерполяция. Как вы можете видеть из моего ответа, я сделал почти то, что вы говорите, создал еще одно шаблонное решение. Это совершенно небезопасно, но, вероятно, сделает то, что мне нужно сейчас. - person mydoghasworms; 22.06.2017