2010-04-08 61 views
3

我有继承,大约经过了大量的XML字符串作为一个传统应用程序。.NET IsValidXml扩展方法性能

我经常需要检查一个字符串是有效的XML的能力。 .NET中检查字符串是否有效的最快速和最便宜的方法是什么?

我正在使用.NET 3.5,并会在该解决方案中的这个项目最有可能使用这个作为一个扩展方法(关字符串)。

UPDATE
我在我的情况下, “有效” 的意思是格式良好的XML。我不需要验证资源或模式。

+0

在你的情况下,什么是“有效的”?你的意思是正确组成,还是你期望它匹配一个DTD /模式?这是否意味着你需要能够解决参考资源? – 2010-04-08 14:05:58

+0

好点。我会修改我的问题。 – BuddyJoe 2010-04-08 14:16:20

+0

我不知道我是否应该调用我的方法IsProperXml?或IsWellFormedXml? – BuddyJoe 2010-04-08 14:18:44

回答

1

这是不可能验证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几乎是任何替代方案的两倍。这是有道理的。虽然我还没有使用反射来检查,我想如果XmlDocumentXDocumentXPathDocument并没有全部使用XmlReader引擎盖下是非常惊讶。

+0

令人敬畏的工作。 +1并回答 – BuddyJoe 2010-04-15 15:22:07

2

我不知道在.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; 
     } 
    } 
} 
+0

@Steven,请不要在从根本上改变他们工作的方式方法编辑答案。捕捉所有例外是有意的,并且是适当的。虽然它*可以更具体,只捕获XmlException,但将其更改为使用DebuggerStepThrough并不完全相同。 – 2010-04-15 15:50:13

2

同意亚当和的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; 
     } 
    } 
} 
+1

为什么有人会编辑已经回答的问题的答案,通过更改代码的含义... 发表评论可能更友好,在我看来! – 2010-04-15 15:55:16