.Net ISVALIDXML Расширение метода
-
25-09-2019 - |
Вопрос
У меня есть наследие приложение, которое я унаследовал, что проходит много XML вокруг как строки.
Мне часто нужна возможность проверки, будет ли строка действительной XML. Какой самый быстрый и наименее дорогой способ проверить, является ли строка действительна XML в .NET?
Я работаю в .NET 3.5 и, скорее всего, использовал это как метод расширения (вне строки) в этом одном проекте в рамках решения.
ОБНОВИТЬ:
То, что я подразумеваю под «действительным» в моем случае, правильно сформирован XML. Мне не нужно подтверждать ресурсы или схема.
Решение
Невозможно проверить хорошо сформированную строку XML без разбора его. И быстрый ориентир показывает, что самый быстрый способ анализировать строку, чтобы увидеть, действительно ли это (фактически самый быстрый способ анализа конкретной строки, которую я использую в качестве теста), является с XMLReader:
static void Main(string[] args)
{
const int iterations = 20000;
const string xml = @"<foo><bar><baz a='b' c='d'/><foo><bar><baz a='b' c='d'/></bar><bar/></foo><foo><bar><baz a='b' c='d'/></bar><bar/></foo><foo><bar><baz a='b' c='d'/></bar><bar/></foo><foo><bar><baz a='b' c='d'/></bar><bar/></foo><foo><bar><baz a='b' c='d'/></bar><bar/></foo><foo><bar><baz a='b' c='d'/></bar><bar/></foo><foo><bar><baz a='b' c='d'/></bar><bar/></foo><foo><bar><baz a='b' c='d'/></bar><bar/></foo><foo><bar><baz a='b' c='d'/></bar><bar/></foo></bar><bar/></foo>";
Stopwatch st = new Stopwatch();
st.Start();
for (int i=0; i<iterations; i++)
{
using (StringReader sr = new StringReader(xml))
using (XmlReader xr = XmlReader.Create(sr))
{
while (xr.Read())
{
}
}
}
st.Stop();
Console.WriteLine(String.Format("XmlReader: {0} ms.", st.ElapsedMilliseconds));
st.Reset();
st.Start();
for (int i=0; i<iterations; i++)
{
XElement.Parse(xml);
}
st.Stop();
Console.WriteLine(String.Format("XElement: {0} ms.", st.ElapsedMilliseconds));
st.Reset();
st.Start();
for (int i = 0; i < iterations; i++)
{
XmlDocument d= new XmlDocument();
d.LoadXml(xml);
}
st.Stop();
Console.WriteLine(String.Format("XmlDocument: {0} ms.", st.ElapsedMilliseconds));
st.Reset();
st.Start();
for (int i = 0; i < iterations; i++)
{
using (StringReader sr = new StringReader(xml))
{
XPathDocument d = new XPathDocument(new StringReader(xml));
}
}
st.Stop();
Console.WriteLine(String.Format("XPathDocument: {0} ms.", st.ElapsedMilliseconds));
Console.ReadKey();
}
На моей машине XmlReader
почти в два раза быстрее, чем любая из альтернатив. Это имеет смысл. Хотя я не использовал отражатель, чтобы проверить, я был бы очень удивлен, если XmlDocument
, XDocument
, а также XPathDocument
Разве все не использовали XmlReader
под капотом.
Другие советы
Я не знаю о встроенном объекте в .NET, чтобы подтвердить формируемую (?) XML без разбора. Учитывая это, что-то вроде этого должно работать:
public static class XmlUtilities
{
public static bool IsXml(this string data)
{
if (string.IsNullOrEmpty(data)) return false;
try
{
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.LoadXml(data);
return true;
}
catch
{
return false;
}
}
}
Согласитесь с Adam и версией XElement:
public static class XmlUtilities
{
public static bool IsXml(this string data)
{
if (string.IsNullOrEmpty(data)) return false;
try
{
var doc = XElement.Parse(data)
return true;
}
catch (XmlException)
{
return false;
}
}
}