2010-04-08 4 views
3

J'ai hérité d'une application héritée qui transmet beaucoup de données XML en tant que chaînes..NET IsValidXml Méthode d'extension Performance

J'ai souvent besoin de la possibilité de vérifier si une chaîne XML sera valide. Quel est le moyen le plus rapide et le moins coûteux de vérifier si une chaîne est XML valide dans .NET?

Je travaille dans .NET 3.5 et je l'utiliserais très probablement comme une méthode d'extension (hors chaîne) dans ce projet unique au sein de la solution.

MISE À JOUR:
Ce que je veux dire par dans mon cas « valide » est correctement formé XML. Je n'ai pas besoin de valider les ressources ou le schéma.

+0

Qu'est-ce qui, dans votre cas, est "valide"? Voulez-vous dire juste formé, ou attendez-vous qu'il corresponde à un DTD/schéma? Cela signifie-t-il que vous devez être en mesure de résoudre les ressources référencées? –

+0

Bon point. Je vais modifier ma question. – BuddyJoe

+0

Je me demande si je devrais appeler ma méthode IsProperXml? ou IsWellFormedXml? – BuddyJoe

Répondre

1

Il est impossible de valider le bien-formedness d'une chaîne XML sans l'analyser. Et une référence rapide montre que la façon la plus rapide pour analyser une chaîne pour voir si elle est valide (en fait le moyen le plus rapide pour analyser la chaîne particulière I en utilisant comme un cas de test) est avec un 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(); 
    } 

Sur ma machine XmlReader est presque deux fois plus rapide que l'une des alternatives. C'est logique. Bien que je n'ai pas utilisé Reflector pour vérifier, je serais très surpris si XmlDocument, XDocument, et XPathDocument n'utilisaient pas tous XmlReader sous le capot.

+0

Super travail. +1 et répondez – BuddyJoe

2

Je ne suis pas au courant d'une fonctionnalité intégrée dans .NET pour valider le format (?) De XML sans l'analyser. Étant donné que, quelque chose comme cela devrait fonctionner:

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, S'il vous plaît ne pas modifier les réponses d'une manière qui modifie fondamentalement la façon dont ils fonctionnent. Attraper toutes les exceptions était intentionnel et approprié. Bien que cela puisse * être * plus spécifique et attraper seulement 'XmlException', le changer pour utiliser' DebuggerStepThrough' n'est pas du tout le même. –

2

D'accord avec Adam, et la version 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

pourquoi quelqu'un éditerait-il une réponse à une question qui a déjà été répondue, en changeant la signification du code ... en postant un commentaire pourrait être plus amical, à mon avis! –

Questions connexes