Чтение XML с помощью & в объект XMLDocument C #

Я унаследовал плохо написанное веб-приложение, которое, кажется, имеет ошибки при попытке чтения в XML-документе, хранящемся в базе данных, в котором есть символ «&». Например, будет тег с содержанием: «Prepaid & Charge». Есть ли какая-то секретная простая вещь, которую нужно сделать, чтобы он не получал ошибку при синтаксическом анализе этого символа, или я упускаю что-то очевидное?

РЕДАКТИРОВАТЬ: есть ли другие символы, которые вызовут такую ​​же ошибку парсера из-за неправильного формирования?


person Ryan Skarin    schedule 23.09.2008    source источник


Ответы (6)


Проблема в том, что xml имеет неправильный формат. Правильно сгенерированный xml будет перечислять эти данные следующим образом:

Prepaid & Charge

Раньше мне приходилось исправлять ту же проблему, и я сделал это с помощью этого регулярного выражения:

Regex badAmpersand = new Regex("&(?![a-zA-Z]{2,6};|#[0-9]{2,4};)");

Объедините это со строковой константой, определенной следующим образом:

const string goodAmpersand = "&";

Теперь вы можете просто сказать badAmpersand.Replace(<your input>, goodAmpersand);

Обратите внимание, что простого String.Replace("&", "&amp;") недостаточно, поскольку вы не можете заранее знать для данного документа, будут ли какие-либо символы & закодированы правильно, неправильно или даже оба в одном документе.

Уловка здесь в том, что вы должны сделать это со своим xml-документом перед загрузкой его в свой синтаксический анализатор, что, вероятно, означает дополнительный проход через него. Кроме того, он не учитывает амперсанды внутри раздела CDATA. Наконец, он только улавливает амперсанды, а не другие запрещенные символы, такие как ‹. Обновление: на основе комментария мне также нужно обновить выражение для сущностей с шестнадцатеричным кодом (& # x ...;).

Что касается персонажей, которые могут вызвать проблемы, настоящие правила немного сложны. Например, в данных разрешены определенные символы, но не как первая буква имени элемента. И нет простого списка запрещенных символов. Вместо этого большая (несмежная) часть UNICODE определяется как допустимая, и все, кроме этого, незаконно.

Итак, когда дело доходит до этого, вы должны доверять своему источнику документа, чтобы он имел хотя бы определенную степень соответствия и согласованности. Например, я обнаружил, что люди часто достаточно умны, чтобы убедиться, что теги работают правильно и ускользают ‹, даже если они не знают, что & запрещено, отсюда и ваша проблема сегодня. Однако лучше всего исправить это у источника.

О, и примечание о предложении CDATA: я бы использовал это, чтобы убедиться, что xml, который я создаю, правильно сформирован, но при работе с существующим xml извне я нахожу метод регулярного выражения Полегче.

person Joel Coehoorn    schedule 23.09.2008
comment
Шестнадцатеричный код & # x ...; ссылки на символы также могут присутствовать. Я предлагаю сначала попытаться проанализировать документ в обычном режиме, любые попытки применить исправление ошибок возможны только в том случае, если в результате возникнет ошибка правильного формата. Тогда вы можете быть уверены, что будущие фиксированные действительные документы всегда будут работать правильно. - person bobince; 09.02.2009

Не веб-приложение виновато, а XML-документ. Амперсанды в XML должны быть закодированы как &amp;. Невыполнение этого требования является синтаксической ошибкой.

Изменить: ответив на вопрос, да, есть все виды похожих ошибок. Например, несбалансированные теги, незакодированные знаки «меньше», значения атрибутов без кавычек, октеты за пределами кодировки символов и различные странности Unicode, ссылки на нераспознанные сущности и т. Д. Чтобы любой приличный синтаксический анализатор XML использовал документ, этот документ должен быть правильно сформирован. Спецификация XML требует, чтобы анализатор, обнаруживший искаженный документ, вызывал фатальную ошибку.

person Jim    schedule 23.09.2008
comment
Итак, вы думаете, что я могу винить мою ленивую команду по интеграции за отправку плохого XML, да? Что-то мне подсказывает, что мне все еще нужно исправить это на своей стороне. :-( - person Ryan Skarin; 23.09.2008
comment
Если возможно, да, устраните проблему в источнике. Если вам абсолютно необходимо иметь дело с плохим источником, который не может исправить свою систему, попробуйте исправить его до того, как он попадет в базу данных. - person Jim; 23.09.2008

Все остальные ответы верны, и я согласен с их советом, но позвольте мне добавить одну вещь:

ПОЖАЛУЙСТА, не создавайте приложения, которые работают с некорректным XML, это только усложняет нам жизнь :).

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

Вы, вероятно, могли бы сделать еще один шаг и сказать: «Ack! Этот XML не работает в этих местах и ​​по этим причинам, вот как я пытался исправить это, чтобы сделать его правильно сформированным: ...».

Я не слишком хорошо знаком с API-интерфейсами MSXML, но большинство хороших анализаторов XML позволяют устанавливать обработчики ошибок, чтобы вы могли уловить точный номер строки / столбца, в котором появляются ошибки, а также получить код ошибки и сообщение.

person Chris Ingrassia    schedule 23.09.2008
comment
Я склонен согласиться. Мой первый план действий - пожаловаться, и я посмотрю, исправят ли они это. Проблема в том, что это 2-х минутное исправление с моей стороны и многое другое с их стороны. В любом случае спасибо за совет. - person Ryan Skarin; 23.09.2008
comment
+1. Если вы исправите это, по крайней мере, продолжайте поднимать предупреждения. Продолжайте делать это «неправильно», и вы обязательно встретите данные, которые ломают все, что вы делаете, чтобы их исправить. - person bobince; 09.02.2009

Ваша база данных не содержит XML-документов. Он содержит несколько правильно сформированных XML-документов и несколько строк, которые для человека выглядят как XML.

Если это вообще возможно, вы должны исправить это - в частности, вы должны исправить любой процесс, генерирующий искаженные XML-документы. Чтобы исправить программу, считывающую данные из этой базы данных, достаточно просто наклеить обои на трещину в стене.

person Robert Rossney    schedule 23.09.2008

Вы можете заменить & на &amp;

Или вы также можете использовать разделы CDATA.

person Steve g    schedule 23.09.2008
comment
Глобальное кодирование & приведет к потере любых ссылок на реальные сущности в данных. - person bobince; 09.02.2009

Есть несколько символов, из-за которых данные XML будут считаться неправильно сформированными.

Из w3schools:

Такие символы, как «‹ »и« & »недопустимы в элементах XML.

Лучшее решение для ввода, которому нельзя доверять как совместимый с XML, - это заключить его в теги CDATA, например

<![CDATA[This is my wonderful & great user text]]>

Все в тегах <![CDATA[ и ]]> анализатор игнорирует.

person ConroyP    schedule 23.09.2008
comment
Возможно, пояснение, что все в тегах CDATA, кроме конечного тега, игнорируется анализатором? - person workmad3; 23.09.2008
comment
Не совсем все ..]] ›нет. Это означает, что если он отправит xml, в котором есть раздел CDATA, или даже просто]] ›кусок текста, он сломается. - person davenpcj; 23.09.2008
comment
Если вы встретите в своем вводе символ]] ›, разделите его на 2 раздела CDATA: один заканчивается на]], а другой начинается на›. Парсер снова воссоединит две части. - person MSalters; 17.10.2008