在C#中测试某些东西是否是可解析的XML

use*_*122 11 .net c# xml

有没有人知道在C#中检查字符串是否可解析为XML的快速方法?最好是快速,低资源的东西,它返回一个布尔值,无论它是否会解析.

我正在开发一个数据库应用程序来处理有时存储为XML的错误,有时则不会.因此,我希望能够非常快速地测试我从数据库中获取的字符串(包含在DataTable中)...而不必诉诸任何try/catch {}语句或其他kludges ...除非这些是实现这一目标的唯一途径.

D S*_*ley 14

听起来你有时会回复XML,有时你会回到"普通"(非XML)文本.

如果是这种情况,您可以检查文本是否以<:

if (!string.IsNullOrEmpty(str) && str.TrimStart().StartsWith("<"))
    var doc = XDocument.Parse(str);
Run Code Online (Sandbox Code Playgroud)

由于"普通"消息似乎不太可能<从这开始,这可能是合理的.您唯一需要决定的是,在边缘情况下您要使用以XML开头的非XML文本<

如果是我,我会默认尝试解析它并捕获异常:

if (!string.IsNullOrEmpty(str) && str.TrimStart().StartsWith("<"))
{
    try
    {
        var doc = XDocument.Parse(str);
        return //???
    }   
    catch(Exception ex)
        return str;
}
else
{
    return str;   
}
Run Code Online (Sandbox Code Playgroud)

这样,只有当你有一个以<XML 开头但不是有效XML 的消息时,你才会有抛出异常的开销.


Joh*_*aft 10

您可以尝试将字符串解析为XDocument.如果它无法解析,那么您知道它无效.

string xml = "";
XDocument document = XDocument.Parse(xml);
Run Code Online (Sandbox Code Playgroud)

如果你不想让丑陋的try/catch可见,你可以把它扔到字符串类的扩展方法中......

public static bool IsValidXml(this string xml)
{
    try
    {
        XDocument.Parse(xml);
        return true;
    }
    catch
    {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你的代码就像 if (mystring.IsValidXml()) {

  • 这与OP称为kludge的不同之处有何不同? (3认同)
  • @Logarr如果您只关心数据是否是有效的XML,那么解析数据的方法要轻松得多.你的内存占用量从整个文件下降到几乎没有,处理时间减少等等.如果你有非常大的文件,那可能会有所不同. (2认同)

Nic*_*rey 5

真正找出某项内容是否真正解析的唯一方法是尝试并解析。

XM1文档应该(但可能不是)在BOM表(如果存在)之后的文件开头具有XML声明。它看起来应该像这样:

<?xml version="1.0" encoding="UTF-8" ?>
Run Code Online (Sandbox Code Playgroud)

尽管我相信encoding属性是可选的(默认为UTF-8。它也可能有一个standalone值为yes或的属性no。如果存在,这很好地表明了该文档应该是有效的XML。

我认为@GaryWalker的出色答案令人信服(尽管设置可能需要一些调整,也许是自定义的无操作解析器)。只是为了踢球,我使用XMark xmlgenhttp://www.xml-benchmark.org/)生成了一个300mb的随机XML文件:使用以下代码对其进行验证在我的台式机上花费了1.7-1.8秒的时间。

public static bool IsMinimallyValidXml( Stream stream )
{
  XmlReaderSettings settings = new XmlReaderSettings
    {
      CheckCharacters              = true                          ,
      ConformanceLevel             = ConformanceLevel.Document     ,
      DtdProcessing                = DtdProcessing.Ignore          ,
      IgnoreComments               = true                          ,
      IgnoreProcessingInstructions = true                          ,
      IgnoreWhitespace             = true                          ,
      ValidationFlags              = XmlSchemaValidationFlags.None ,
      ValidationType               = ValidationType.None           ,
    } ;
  bool isValid ;

  using ( XmlReader xmlReader = XmlReader.Create( stream , settings ) )
  {
    try
    {
      while ( xmlReader.Read() )
      {
        ; // This space intentionally left blank
      }
      isValid = true ;
    }
    catch (XmlException)
    {
      isValid = false ;
    }
  }
  return isValid ;
}

static void Main( string[] args )
{
  string text = "<foo>This &SomeEntity; is about as simple as it gets.</foo>" ;
  Stream stream = new MemoryStream( Encoding.UTF8.GetBytes(text) ) ;
  bool isValid = IsMinimallyValidXml( stream ) ;
  return ;
}
Run Code Online (Sandbox Code Playgroud)