有没有人知道如何检查字符串是否包含格式良好的XML而不在try / catch块中使用XmlDocument.LoadXml()
之类的东西?我有输入可能是也可能不是XML,我希望代码能够识别输入可能不是XML而不依赖于try / catch,速度和非特殊情况不应该提高的一般原则例外。我目前有代码执行此操作;
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;
}
}
但它似乎不应该需要try / catch。异常是在调试期间导致快乐的地狱,因为每次我检查一个字符串调试器都会在这里打破,“帮助”我解决我的麻烦问题。
答案 0 :(得分:23)
我不知道如何在没有例外的情况下进行验证,但您可以将调试器设置更改为仅在XmlException
处理时如果未处理 - 这应解决您的即时问题,即使代码仍然不优雅
要执行此操作,请转到Debug / Exceptions ... / Common Language Runtime Exceptions并找到System.Xml.XmlException,然后确保仅选中“User-unhandled”(不是Thrown)。
答案 1 :(得分:7)
史蒂夫,
我们有一个第三方偶然发送了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));
}
答案 2 :(得分:5)
这是一种合理的方法,除了IsNullOrEmpty是冗余的(LoadXml可以很好地解决这个问题)。如果确实保留了IsNullOrEmpty,请执行if(!string.IsNullOrEmpty(value))。
但基本上,您的调试器是问题,而不是代码。
答案 3 :(得分:4)
将[System.Diagnostics.DebuggerStepThrough]
属性添加到IsValidXml
方法。这样可以防止调试器捕获XmlException,这意味着您可以启用捕获首次更改的异常,并且不会调试此特定方法。
答案 4 :(得分:2)
谨慎使用XmlDocument
可以使用<0>some text</0>
加载元素
XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(object)
没有抛出异常。
数字元素名称无效xml,在我的情况下,在我尝试将xmlDoc.innerText写入xml的Sql server数据类型之前,没有发生错误。
我现在如何验证,并抛出异常
XmlDocument tempDoc = XmlDocument)JsonConvert.DeserializeXmlNode(formData.ToString(), "data");
doc.LoadXml(tempDoc.InnerXml);
答案 5 :(得分:1)
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
答案 6 :(得分:0)
我不同意问题是调试器。一般而言,对于非例外情况,应避免例外。这意味着如果某人正在寻找类似IsWellFormed()
的方法,该方法根据输入是否格式良好而返回true / false,则不应在此实现中抛出异常,无论它们是否被捕获和处理或不。
异常是昂贵的,在正常成功执行期间不应该遇到它们。一个例子是编写一个方法来检查文件的存在并使用File.Open并在文件不存在的情况下捕获异常。这将是一个糟糕的实施。相反应该使用File.Exists()
(并且希望实现它不会简单地将try / catch放在一个抛出异常的方法中,如果文件不存在,我相信它不会。) / p>
答案 7 :(得分:0)
仅仅是我的2美分 - 关于这个问题存在各种各样的问题,并且大多数人都同意“垃圾进入垃圾”的事实。我并不反对 - 但我个人发现了以下快速而肮脏的解决方案,特别是对于处理来自第三方的xml数据的情况,这些数据根本就不能与您轻松沟通..它不会避免使用try / catch - 但是它使用更精细的粒度,所以在无效的xml字符数量不那么大的情况下,它会有所帮助..我使用XmlTextReader,并为每个父元素使用其方法ReadChars(),这是其中一个命令没有像ReadInner / OuterXml那样进行格式良好的检查。所以当Read()收敛于父节点时,它是Read()和ReadChars()的组合。当然这是有效的,因为我可以假设XML的基本结构是可以的,但某些节点的内容(值)可以包含未被&amp; ...取代的特殊字符。相当于......(我在某处发现了一篇关于此的文章,但目前找不到源链接)
答案 8 :(得分:0)
我正在使用此功能来验证字符串/片段
<Runtime.CompilerServices.Extension()>
Public Function IsValidXMLFragment(ByVal xmlFragment As String, Optional Strict As Boolean = False) As Boolean
IsValidXMLFragment = True
Dim NameTable As New Xml.NameTable
Dim XmlNamespaceManager As New Xml.XmlNamespaceManager(NameTable)
XmlNamespaceManager.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema")
XmlNamespaceManager.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")
Dim XmlParserContext As New Xml.XmlParserContext(Nothing, XmlNamespaceManager, Nothing, Xml.XmlSpace.None)
Dim XmlReaderSettings As New Xml.XmlReaderSettings
XmlReaderSettings.ConformanceLevel = Xml.ConformanceLevel.Fragment
XmlReaderSettings.ValidationType = Xml.ValidationType.Schema
If Strict Then
XmlReaderSettings.ValidationFlags = (XmlReaderSettings.ValidationFlags Or XmlSchemaValidationFlags.ProcessInlineSchema)
XmlReaderSettings.ValidationFlags = (XmlReaderSettings.ValidationFlags Or XmlSchemaValidationFlags.ReportValidationWarnings)
Else
XmlReaderSettings.ValidationFlags = XmlSchemaValidationFlags.None
XmlReaderSettings.ValidationFlags = (XmlReaderSettings.ValidationFlags Or XmlSchemaValidationFlags.AllowXmlAttributes)
End If
AddHandler XmlReaderSettings.ValidationEventHandler, Sub() IsValidXMLFragment = False
AddHandler XmlReaderSettings.ValidationEventHandler, AddressOf XMLValidationCallBack
Dim XmlReader As Xml.XmlReader = Xml.XmlReader.Create(New IO.StringReader(xmlFragment), XmlReaderSettings, XmlParserContext)
While XmlReader.Read
'Read entire XML
End While
End Function
我正在使用此功能来验证文件:
Public Function IsValidXMLDocument(ByVal Path As String, Optional Strict As Boolean = False) As Boolean
IsValidXMLDocument = IO.File.Exists(Path)
If Not IsValidXMLDocument Then Exit Function
Dim XmlReaderSettings As New Xml.XmlReaderSettings
XmlReaderSettings.ConformanceLevel = Xml.ConformanceLevel.Document
XmlReaderSettings.ValidationType = Xml.ValidationType.Schema
If Strict Then
XmlReaderSettings.ValidationFlags = (XmlReaderSettings.ValidationFlags Or XmlSchemaValidationFlags.ProcessInlineSchema)
XmlReaderSettings.ValidationFlags = (XmlReaderSettings.ValidationFlags Or XmlSchemaValidationFlags.ReportValidationWarnings)
Else
XmlReaderSettings.ValidationFlags = XmlSchemaValidationFlags.None
XmlReaderSettings.ValidationFlags = (XmlReaderSettings.ValidationFlags Or XmlSchemaValidationFlags.AllowXmlAttributes)
End If
XmlReaderSettings.CloseInput = True
AddHandler XmlReaderSettings.ValidationEventHandler, Sub() IsValidXMLDocument = False
AddHandler XmlReaderSettings.ValidationEventHandler, AddressOf XMLValidationCallBack
Using FileStream As New IO.FileStream(Path, IO.FileMode.Open)
Using XmlReader As Xml.XmlReader = Xml.XmlReader.Create(FileStream, XmlReaderSettings)
While XmlReader.Read
'Read entire XML
End While
End Using
End Using
End Function
答案 9 :(得分:0)
此外,当仅验证XML字符串的语法正确性时(不需要解析外部模式时),我认为添加XmlResolver = null
设置可能是一个好主意。这既保证了安全性(没有Web访问权限)又保证了安全性(避免恶意XML内容指示代码访问不良站点)。代码如下(需要C#2.0或更高版本):
public static bool IsValidXml(string candidateString)
{
try
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.XmlResolver = null;
XmlDocument document = new XmlDocument();
document.XmlResolver = null;
document.Load(XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(candidateString)), settings));
return true;
}
catch (XmlException)
{
return false;
}
}
针对C#6.0或更高版本的优化版本:
public static bool IsValidXml(string candidateString)
{
try
{
var settings = new XmlReaderSettings { XmlResolver = null };
var document = new XmlDocument() { XmlResolver = null };
document.Load(XmlReader.Create(new MemoryStream(Encoding.UTF8.GetBytes(candidateString)), settings));
return true;
}
catch (XmlException)
{
return false;
}
}
答案 10 :(得分:-2)
我的两分钱。这很简单,遵循一些常见的约定,因为它是关于解析...
public bool TryParse(string s, ref XmlDocument result)
{
try {
result = new XmlDocument();
result.LoadXml(s);
return true;
} catch (XmlException ex) {
return false;
}
}