Мне нужно запустить быстрый и грязный редактор конфигурации. Поток выглядит примерно так:
конфигурация (POCO на сервере) сериализуются в XML.
На данный момент XML хорошо сформирован. Конфигурация отправляется на веб-сервер в XElements.
.
На веб-сервере XML (да, ВСЕ ЭТО) выгружается в текстовое поле для редактирования.
Пользователь редактирует XML прямо на веб-странице и нажимает «Отправить» .
В ответ я получаю измененный текст конфигурации XML. На данный момент ВСЕ экраны отменены в процессе их отображения на веб-странице.
Я пытаюсь загрузить строку в объект XML (XmlElement, XElement и т. д.). КАБУМ.
Проблема в том, что при сериализации строки атрибутов не используются, но при переводе они теряются.
Например, допустим, у меня есть объект с регулярным выражением. Вот конфигурация веб-сервера:
<Configuration>
<Validator Expression = "[^<]" />
</Configuration>
Итак, я поместил это в текстовое поле, где это выглядит так для пользователя:
<Configuration>
<Validator Expression = "[^<]" />
</Configuration>
Таким образом, пользователь вносит небольшие изменения и отправляет изменения обратно. На веб-сервере строка ответа выглядит так:
<Configuration>
<Validator Expression = "[^<]" />
<Validator Expression = "[^&]" />
</Configuration>
Итак, пользователь добавил еще одну штуку с валидатором, и теперь ОБА имеют атрибуты с недопустимыми символами. Если я попытаюсь загрузить это в любой XML-объект, это вызовет исключение, потому что <и & недействительны в текстовой строке. Я НЕ МОГУ НЕ МОГУ НЕ МОГУ использовать какую-либо функцию кодирования, поскольку она кодирует всю кровавую вещь:
var result = Server.HttpEncode (editedConfig);
приводит к
<Configuration>
<Validator Expression = "[^<]" />
<Validator Expression = "[^&]" />
</Configuration>
Это НЕ правильный XML. Если я попытаюсь загрузить это в какой-либо элемент XML, меня ударит падающая наковальня. Я не люблю падающие наковальни.
Итак, вопрос остается ... Единственный способ подготовить эту строку XML к синтаксическому анализу в объект XML - это использовать замену регулярных выражений? Есть ли способ «отключить ограничения» при загрузке? Как это обойти ???
Один последний ответ, а затем wiki-izing это, поскольку я не думаю, что есть действительный ответ.
XML, который я помещаю в текстовое поле, является действительным, экранированным XML. Процесс 1) размещения его в текстовой области 2) отправки его клиенту 3) отображения его клиенту 4) отправки формы, в которой он находится 5) отправки его обратно на сервер и 6) получения значения из формы УДАЛЯЕТ ЛЮБЫЕ И ВСЕ УБЕГАЕТ.
Позвольте мне сказать это еще раз: Я не убегу от НИЧЕГО. Просто отобразите его в браузере!
Над чем поразмыслить: есть ли способ предотвратить это в первую очередь? Есть ли способ взять почти корректный XML и "очистить" его безопасным способом?
За этот вопрос теперь есть награда. Чтобы получить вознаграждение, вы демонстрируете, как редактировать ДЕЙСТВИТЕЛЬНЫЙ XML в окне браузера БЕЗ стороннего инструмента / инструмента с открытым исходным кодом, который не требует от меня использования регулярного выражения для экранирования значений атрибутов вручную, что не требует от пользователей экранирования своих атрибутов, и это не дает сбоев при передаче в оба конца (& amp; amp; amp; etc;)





Эээ… Как вы сериализуете? Обычно сериализатор XML никогда не должен создавать недопустимый XML.
/ EDIT в ответ на ваше обновление: Отображает ли нет недопустимый XML для редактирования вашим пользователем! Вместо этого отобразите правильно экранированный XML в TextBox. Исправлять сломанный XML - это не весело, и я на самом деле не вижу причин не отображать / редактировать XML в допустимой, экранированной форме.
Снова я мог бы спросить: как вы показываете XML в TextBox? Кажется, в какой-то момент вы намеренно отключаете от XML.
/ EDIT в ответ на ваш последний комментарий: Да, очевидно, поскольку он может содержать HTML. Вам нужно правильно экранировать свой XML, прежде чем записывать его на HTML-страницу. Под этим я подразумеваю все XML. Итак, это:
<foo mean-attribute = "<">
становится это:
<foo mean-attribute = "&<">
Поверьте, когда вы берете экранированный xml и помещаете его в ТЕКСТОВУЮ ОБЛАСТЬ для отображения на веб-странице, он отображает экранированные символы как их неэкранированные копии. Я делаю это не специально.
Извините, там была некоторая путаница с textBLOCKS и textAREAS
Этот специальный символ - «<» - нужно было заменить другими символами, чтобы ваш XML был действителен. Проверьте эту ссылку на наличие специальных символов XML:
http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references
Попробуйте также закодировать содержимое TextBlock перед его отправкой в десериализатор:
HttpServerUtility utility = new HttpServerUtility();
string encodedText = utility.HtmlEncode(text);
Да, верно. Вопрос, однако, в том, КАК это сделать. Regex заменить? Или есть более безопасный и надежный способ сделать это?
Я отредактировал свой ответ и добавил образец кода для кодирования текста перед его отправкой в сериализатор.
Это ускользает от ВСЕГО, превращая действительный xml (с некоторыми плохими атрибутами) в не-xml. Это не работает.
Подождите: вы тоже показываете пользователям Разметка? Это делает недействительными большую часть моего другого ответа, но, по крайней мере, регулярное выражение в вопросе, на который я ссылался, все еще может вам помочь.
Как вы говорите, обычный сериализатор должен избавить вас от всего.
Таким образом, проблема заключается в текстовом блоке: вам нужно самостоятельно обрабатывать все, что проходит через текстовый блок.
Вы можете попробовать HttpUtility.HtmlEncode (), но я думаю, что самый простой способ - просто заключить все, что вы передаете через текстовый блок, в раздел CDATA.
Обычно, конечно, я бы хотел, чтобы все было правильно экранировано, вместо того, чтобы полагаться на «костыль» CDATA, но я также хотел бы использовать встроенные инструменты для экранирования. Я думаю, что для чего-то, что редактируется пользователем в "спящем" состоянии, лучше всего подойдет CDATA.
Также см. Предыдущий вопрос:
Лучший способ кодировать текстовые данные для XML
Обновлять
Основываясь на комментарии к другому ответу, я понял, что вы показываете пользователям разметку, а не только содержимое. Xml-парсеры, ну, разборчивы. Я думаю, что лучшее, что вы могли бы сделать в этом случае, - это проверить правильность формата до, принимающего отредактированный xml.
Возможно, попробуйте автоматически исправить определенные виды ошибок (например, плохие амперсанды из моего связанного вопроса), но затем получите номер строки и номер столбца первой ошибки проверки из синтаксического анализатора .Net xml и используйте это, чтобы показать пользователям, где их ошибка, пока они дают вам что-то приемлемое. Бонусные баллы, если вы также проверяете схему.
Да, я показываю необработанную, голую разметку sexxay в TextBlock. Как я уже сказал, быстрый и грязный редактор конфигурации. Конфигурация = xml, редактор = TextBlock + xml
Я бы хотел, чтобы пользователи не заставляли себя убегать. Он выходит без экранирования, что означает, что они должны прополоть СОТНИ строк XML, чтобы исправить то, что сломано, ДО того, как они изменят конфигурацию. КОШМАРНЫЙ СОН.
Идея здесь в том, чтобы вы могли исправить определенные типы распространенных ошибок для них и, по крайней мере, показать им, где проблема для ошибок, если вы не можете ее исправить.
Важно то, что независимо от того, что вы не должны принимать пользовательский ввод, который сломает объект, вы не сможете учесть каждую возможную ошибку, которую кто-то может сделать в документе. Так что вам все равно нужно будет реализовать некоторую логику проверки.
Быстро и грязно; если они сломают его, он сломается. Я не против. Но просто АКТ отображения его на веб-странице нарушает его. Я хочу как минимум предотвратить это. Регулярное выражение?
Это выражение найдет любой амперсанд, который не является частью объекта, что противоречит правилам в Xml: & (?! [A-zA-Z] {2,6}; | # [0-9] {2, 4};)
Я хотел бы хотя бы предупреждать пользователю, что представленные значения недействительны: дать им выбор, попытаться исправить или отправить в любом случае. Но я вижу, где у вас более серьезная проблема: теперь нет разницы между символом «меньше чем», который используется для тега, и символом, который используется для содержимого.
Неужели это единственный вариант? Разве это не достаточно распространенная проблема, чтобы найти решение где-нибудь в рамках?
private string EscapeAttributes(string configuration)
{
var lt = @"(?<=\w+\s*=\s*""[^""]*)<(?=[^""]*"")";
configuration = Regex.Replace(configuration, lt, "<");
return configuration;
}
(править: удаленная замена амперсанда, поскольку это вызывает проблемы с возвратом)
Я знаю. Это страшно. Вот почему я удивлен, что нет ничего, что можно было бы использовать в качестве альтернативы.
Конечно, когда вы помещаете ссылки на объекты внутри текстового поля, они выходят без экранирования. Текстовые области - это не волшебство, вам нужно & убежать; все, что вы в них вкладываете, как и любой другой элемент. Браузеры могут отображать использовать необработанный знак «<» в текстовой области, но только потому, что они пытаются исправить ваши ошибки.
Поэтому, если вы помещаете редактируемый XML в текстовое поле, вам нужно один раз экранировать значение атрибута, чтобы сделать его действительным XML, а затем вам нужно снова экранировать весь XML, чтобы сделать его действительным HTML. Конечный источник, который вы хотите разместить на странице, будет:
<textarea name = "somexml">
<Configuration>
<Validator Expression = "[^&lt;]" />
<Validator Expression = "[^&amp;]" />
</Configuration>
</textarea>
Вопрос основан на неправильном понимании модели содержимого элемента textarea - валидатор сразу понял бы проблему.
Комментарий ETA: Ну, а какая проблема остается? Это проблема сериализации. Все, что остается, - это разобрать его обратно, и для этого вы должны предположить, что пользователь может создать правильно сформированный XML.
Попытка проанализировать неверно сформированный XML, чтобы допустить ошибки, такие как наличие "<" или "&" без экранирования в значении атрибута, является потерей, полностью противоречащей тому, как должен работать XML. Если вы не можете доверять своим пользователям писать правильно сформированный XML, дайте им более простой интерфейс, отличный от XML, например простой список строк регулярного выражения, разделенных новой строкой.
Вы можете взглянуть на что-то вроде TinyMCE, которое позволяет редактировать html в поле форматированного текста. Если вы не можете настроить его так, чтобы он делал именно то, что вы хотите, вы можете использовать его как источник вдохновения.
Рассмотрены, отвергнуты. Кроме того, «продемонстрируйте, как редактировать ДЕЙСТВИТЕЛЬНЫЙ XML в окне браузера БЕЗ сторонних инструментов / инструментов с открытым исходным кодом». в любом случае спасибо за ответ.
Примечание: firefox (в моем тесте) не отменяет экранирование в текстовых областях, как вы описываете. В частности, этот код:
<textarea cols = "80" rows = "10" id = "1"></textarea>
<script>
elem = document.getElementById("1");
elem.value = '\
<Configuration>\n\
<Validator Expression = "[^<]" />\n\
</Configuration>\
'
alert(elem.value);
</script>
Предупреждается и отображается для пользователя неизменный, как:
<Configuration>
<Validator Expression = "[^<]" />
</Configuration>
Так что, возможно, одно (нежизнеспособное?) Решение для ваших пользователей - использовать firefox.
Похоже, в вашем вопросе были обнаружены две части:
1 XML, который вы показываете, не экранируется.
Например, «<» не экранируется как «<». Но поскольку «<» также не экранируется как «<», информация теряется, и вы не можете ее вернуть.
Одно из решений - экранировать все символы «&», чтобы «<» превратилось в «&lt;». Затем текстовое поле не будет экранировать его как «<». Когда вы перечитаете его, он будет таким, каким был изначально. (Я предполагаю, что текстовое поле действительно меняет строку, но firefox не работает так, как вы сообщаете, поэтому я не могу это проверить)
Другое решение (уже упоминавшееся, я думаю) - создать / купить / заимствовать пользовательскую текстовую область (неплохо, если просто, но есть все клавиши редактирования, ctrl-C, ctrl-shift-left и так далее).
2 Вы бы хотели, чтобы пользователи не беспокоились о побеге.
Ты в аду побега:
Замена регулярного выражения будет в основном работать ... но как вы можете надежно определить конечную цитату ("), когда пользователь может (законно, в рамках указанных вами условий) ввести:
<Configuration>
<Validator Expression = "[^"<]" />
</Configuration>
Глядя на это с точки зрения синтаксиса регулярного выражения, он также не может сказать, является ли последний "частью регулярного выражения или его концом. Синтаксис регулярных выражений обычно решает эту проблему с помощью явного терминатора, например:
/[^"<]/
Если пользователи использовали этот синтаксис (с терминатором), и вы написали для него синтаксический анализатор, то вы могли бы определить, когда регулярное выражение закончилось, и, следовательно, следующий "символ не является частью регулярного выражения, а является частью XML, и следовательно, какие части нужно убрать. Я не говорю, что вы должны это делать! Я говорю, что это теоретически возможно. Это довольно далеко не быстро и грязно.
BTW: такая же проблема возникает для текста внутри элемента. Следующее является допустимым в рамках указанных вами условий, но имеет те же проблемы с синтаксическим анализом:
<Configuration>
<Expression></Expression></Expression>
</Configuration>
Основное правило в синтаксисе, которое позволяет использовать «любой текст», состоит в том, что ограничитель должен должен быть экранирован (например, «или <), чтобы можно было распознать конец. Большая часть синтаксиса также экранирует множество других вещей для удобства / неудобства. (РЕДАКТИРОВАТЬ ему потребуется экранирование для самого escape-символа: для XML это "&", который, когда литерал экранирован как "&", для регулярного выражения это "\" в стиле C / unix, который, когда литерал экранирован как "\\").
Вложите синтаксисы, и вы в аду побега.
Одно простое решение для вас - сказать вашим пользователям: это редактор конфигурации быстро и грязный, так что вы не получите никаких причуд "не нужно убегать" mamby-pamby:
<».Оглядываясь назад, я вижу, что бобинс дал тот же базовый ответ до меня.
Довольно много. Мне все еще остается экранировать ввод пользователя. Проблема, с которой я столкнулся, заключается в том, что я не могу использовать правильные синтаксические анализаторы / объекты xml и «помогать» им, когда они сталкиваются с недопустимым xml; это предложение "все или ничего". Мне нужно заменить регулярное выражение, чтобы заставить его работать; Я хочу знать, есть ли другие способы.
Вы должны каким-то образом разбираться. Заменить регулярное выражение проще всего, но я надеюсь, что я показал, что вам нужно определить текстовое содержимое таким образом, чтобы вы могли определить, где заканчивается текст (поскольку вы больше не можете полагаться на "и <синтаксиса XML для выполнения это для вас), и это трудно сделать правильно с регулярным выражением.
Вставка CDATA вокруг всего текста даст вам еще один механизм экранирования, который (1) избавит пользователей от экранирования вручную и (2) позволит правильно прочитать текст, который был автоматически экранирован текстовым полем.
<Configuration>
<Validator Expression = "<![CDATA[ [^<] ]]>" />
</Configuration>
:-)
Правильный. Ошибка в вопросе. Fix'd