Проверить правильно сформированный XML без try / catch? - PullRequest
25 голосов
/ 22 июня 2009

Кто-нибудь знает, как я могу проверить, содержит ли строка правильно сформированный XML, не используя что-то вроде XmlDocument.LoadXml() в блоке try / catch? У меня есть входные данные, которые могут быть или не быть XML, и мне нужен код, который распознает, что входные данные не могут быть XML, не полагаясь на попытку / улов, как по скорости, так и по общему принципу, что не исключительные обстоятельства не должны вызывать исключения. В настоящее время у меня есть код, который делает это;

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;
        }
    }

Но, похоже, что-то, что не должно требовать попытки / улова. Исключение вызывает веселый ад во время отладки, потому что каждый раз, когда я проверяю строку, отладчик ломается здесь, «помогая» мне с моей неприятной проблемой.

Ответы [ 9 ]

23 голосов
/ 22 июня 2009

Я не знаю способа проверки без исключения, но вы можете изменить настройки отладчика так, чтобы они ломались только на XmlException, если он не обрабатывается - это должно решить ваши непосредственные проблемы, даже если код все еще не элегантен.

Для этого перейдите в раздел «Отладка / Исключения ... / Исключения времени выполнения общего языка» и найдите System.Xml.XmlException, а затем убедитесь, что отмечен только «Необработанный пользователь» (не выброшен).

7 голосов
/ 05 апреля 2013

Стив,

У нас была третья сторона, которая иногда отправляла нам 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 = "<result>true</result>";
    Assert.IsTrue(Utility.IsValidXml(xml));
}

[TestMethod()]
public void TestIsNotValidXml()
{
    string json = "{ \"result\": \"true\" }";
    Assert.IsFalse(Utility.IsValidXml(json));
}
5 голосов
/ 22 июня 2009

Это разумный способ сделать это, за исключением того, что IsNullOrEmpty является избыточным (LoadXml может в этом разобраться). Если вы сохраняете IsNullOrEmpty, делайте if (! String.IsNullOrEmpty (value)).

По сути, проблема в отладчике, а не в коде.

4 голосов
/ 22 сентября 2010

Добавьте атрибут [System.Diagnostics.DebuggerStepThrough] к методу IsValidXml. Это исключает возможность отлова исключения XmlException отладчиком, что означает, что вы можете включить перехват исключений первого изменения, и этот конкретный метод не будет отлажен.

2 голосов
/ 09 ноября 2015

Осторожно при использовании XmlDocument, чтобы можно было загружать элемент в соответствии с <0>some text</0>, используя XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(object) без исключение.

Числовые имена элементов не являются допустимыми xml, и в моем случае ошибка не возникала, пока я не попытался записать xmlDoc.innerText в тип данных Sql-сервера xml.

Вот как я проверяю сейчас, и генерируется исключение
XmlDocument tempDoc = XmlDocument)JsonConvert.DeserializeXmlNode(formData.ToString(), "data"); doc.LoadXml(tempDoc.InnerXml);

1 голос
/ 22 марта 2011

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

И пример из другой статьи MSDN, к которой я добавил код для чтения все содержимое потока XML.

string str = "<ROOT>AQID</ROOT>";
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

0 голосов
/ 23 января 2015

Мои два цента. Это было довольно просто и следует некоторым общепринятым правилам, поскольку речь идет о разборе ...

public bool TryParse(string s, ref XmlDocument result)
{
    try {
        result = new XmlDocument();
        result.LoadXml(s);
        return true;
    } catch (XmlException ex) {
        return false;
    }
}
0 голосов
/ 01 июня 2013

Только мои 2 цента - есть разные вопросы по этому поводу, и большинство людей согласны с фактом «вывоз мусора». Я не согласен с этим - но лично я нашел следующее быстрое и грязное решение, особенно для случаев, когда вы имеете дело с XML-данными от третьих лиц, которые просто не общаются с вами легко ... Это не мешает использовать try / поймать - но он использует его с более высокой степенью детализации, поэтому в случаях, когда количество недопустимых символов XML не так велико, это помогает .. Я использовал XmlTextReader и его метод ReadChars () для каждого родительского элемента, который является одной из команд которые не делают правильные проверки, как ReadInner / OuterXml. Таким образом, это комбинация Read () и ReadChars (), когда Read () натыкается на родительский узел. Конечно, это работает, потому что я могу предположить, что базовая структура XML в порядке, но содержимое (значения) определенных узлов может содержать специальные символы, которые не были заменены на & ..; эквивалент ... (я где-то нашел статью об этом, но в данный момент не могу найти ссылку на источник)

0 голосов
/ 23 октября 2012

Я не согласен с тем, что проблема в отладчике. В целом, для неисключительных случаев следует избегать исключений. Это означает, что если кто-то ищет такой метод, как IsWellFormed(), который возвращает истину / ложь в зависимости от того, правильно ли введен XML, или нет, исключения не должны создаваться в этой реализации, независимо от того, были ли они перехвачены и обработаны или нет ,

Исключения являются дорогостоящими и не должны встречаться при нормальном успешном выполнении. Примером является написание метода, который проверяет наличие файла и использует File.Open и перехватывает исключение в случае, если файл не существует. Это было бы плохой реализацией. Вместо этого следует использовать File.Exists() (и, надеюсь, реализация этого не просто помещает попытку / перехват в некоторый метод, который выдает исключение, если файл не существует, я уверен, что это не так).

...