Проверить хорошо сформированный XML без try / catch?
Кто-нибудь знает, как я могу проверить, содержит ли строка хорошо сформированный XML, не используя что-то вроде XmlDocument.LoadXml()
в блоке try / catch? У меня есть данные, которые могут быть или не быть XML, и я хочу, чтобы код, который распознает, что вход может быть не XML, не полагаясь на try / catch, как по скорости, так и по общему принципу, что не исключительные обстоятельства не должны поднимать исключения. В настоящее время у меня есть код, который делает это;
private bool IsValidXML(string value) { try { // Check we actually have a value if (string.IsNullOrEmpty(value) == false) { // Try to load the value into a document XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(value); // If we managed with no exception then this is valid XML! return true; } else { // A blank value is not valid xml return false; } } catch (System.Xml.XmlException) { return false; } }
Но это похоже на то, что не должно требовать try / catch. Исключение вызывает адский ад во время отладки, потому что каждый раз, когда я проверяю строку, отладчик будет ломаться здесь, «помогая» мне с моей надоедливой проблемой.
Я не знаю способ проверки без исключения, но вы можете изменить настройки отладчика, чтобы только перерыв для XmlException
если он необработан, – это должно решить ваши непосредственные проблемы, даже если код все еще неэлегантен.
Для этого перейдите в раздел «Отладка / Исключения …» / «Исключения для общего языка» и найдите «Исключить System.Xml.XmlException», затем убедитесь, что отмечен галочкой (не выбрасывается) только «Пользовательский необработанный».
Стив,
У нас была сторонняя сторона, которая случайно иногда посылала нам JSON вместо XML. Вот что я реализовал:
public static bool IsValidXml(string xmlString) { Regex tagsWithData = new Regex("<\\w+>[^<]+\\w+>"); //Light checking if (string.IsNullOrEmpty(xmlString) || tagsWithData.IsMatch(xmlString) == false) { return false; } try { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(xmlString); return true; } catch (Exception e1) { return false; } } [TestMethod()] public void TestValidXml() { string xml = "true "; Assert.IsTrue(Utility.IsValidXml(xml)); } [TestMethod()] public void TestIsNotValidXml() { string json = "{ \"result\": \"true\" }"; Assert.IsFalse(Utility.IsValidXml(json)); }
Это разумный способ сделать это, за исключением того, что IsNullOrEmpty является избыточным (LoadXml может оценить это отлично). Если вы сохраняете IsNullOrEmpty, выполните, если (! String.IsNullOrEmpty (значение)).
В принципе, однако, ваш отладчик – проблема, а не код.
Добавьте атрибут [System.Diagnostics.DebuggerStepThrough]
в метод IsValidXml
. Это подавляет исключение XmlException от захвата отладчиком, что означает, что вы можете включить улавливание исключений с первым изменением, и этот конкретный метод не будет отлажен.
Предостережение с использованием XmlDocument
позволяет загружать элемент по строкам <0>some text
используя XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(object)
без исключения.
Числовые имена элементов недействительны xml, и в моем случае ошибка не возникала до тех пор, пока я не попытался записать xmlDoc.innerText в тип данных сервера Sql для xml.
Это, как я проверяю сейчас, и исключение бросает
XmlDocument tempDoc = XmlDocument)JsonConvert.DeserializeXmlNode(formData.ToString(), "data"); doc.LoadXml(tempDoc.InnerXml);
Класс XmlTextReader представляет собой реализацию XmlReader и обеспечивает быстрый синтаксический анализатор. Он обеспечивает соблюдение правил, в соответствии с которыми XML должен быть хорошо сформирован. Он не является ни проверяющим, ни не проверяющим парсером, поскольку он не имеет DTD или информации о схеме. Он может читать текст в блоках или читать символы из streamа.
И пример из другой статьи MSDN, в которую я добавил код для чтения всего содержимого streamа XML.
string str = "AQID "; XmlTextReader r = new XmlTextReader(new StringReader(str)); try { while (r.Read()) { } } finally { r.Close(); }
источник: http://bytes.com/topic/c-sharp/answers/261090-check-wellformedness-xml
Я не согласен с тем, что проблема заключается в отладчике. В целом, в исключительных случаях исключения следует избегать. Это означает, что если кто-то ищет такой метод, как IsWellFormed()
который возвращает true / false на основании того, является ли вход хорошо сформированным XML или нет, исключения не должны быть выбрасываться внутри этой реализации независимо от того, пойманы они или обработаны или нет ,
Исключения являются дорогостоящими, и они не должны встречаться при нормальном успешном выполнении. Примером может быть запись метода, который проверяет существование файла и использования File.Open и перехватывает исключение в случае, если файл не существует. Это было бы плохой реализацией. Вместо File.Exists()
следует использовать File.Exists()
(и, надеюсь, реализация этого не просто ставит try / catch вокруг какого-либо метода, который генерирует исключение, если файл не существует, я уверен, что он этого не делает).
Только мои 2 цента – есть разные вопросы об этом, и большинство людей согласны с фактом «мусор в мусоре». Я не согласен с этим, но лично я нашел следующее быстрое и грязное решение, особенно для случаев, когда вы имеете дело с xml-данными от сторонних сторон, которые просто не общаются с вами легко. Это не позволяет использовать try / catch, но он использует его с меньшей детализацией, поэтому в случаях, когда количество недействительных символов xml не так велико, это помогает … Я использовал XmlTextReader и его метод ReadChars () для каждого родительского элемента, который является одной из команд которые не выполняют хорошо сформированные проверки, например ReadInner / OuterXml. Таким образом, это комбинация Read () и ReadChars (), когда Read () stubmbles на родительском узле. Конечно, это работает, потому что я могу предположить, что базовая структура XML в порядке, но содержимое (значения) определенных узлов может содержать специальные символы, которые не были заменены на & ..; эквивалент … (я нашел статью об этом где-то, но не могу найти ссылку источника на данный момент)
Мои два цента. Это было довольно просто и следует некоторым общим соглашениям, поскольку речь идет о parsingе …
public bool TryParse(string s, ref XmlDocument result) { try { result = new XmlDocument(); result.LoadXml(s); return true; } catch (XmlException ex) { return false; } }