C# 检查格式良好的XML而不进行尝试/捕获?
有人知道我如何在try/catch块中不使用类似于C# 检查格式良好的XML而不进行尝试/捕获?,c#,xml,well-formed,C#,Xml,Well Formed,有人知道我如何在try/catch块中不使用类似于XmlDocument.LoadXml()的东西来检查字符串是否包含格式良好的XML吗?我得到的输入可能是XML,也可能不是XML,我希望代码能够识别输入可能不是XML,而不依赖于try/catch,无论是速度还是非异常情况不应引发异常的一般原则。我目前有这样做的代码 private bool IsValidXML(string value) { try { // Check we
XmlDocument.LoadXml()
的东西来检查字符串是否包含格式良好的XML吗?我得到的输入可能是XML,也可能不是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;
}
}
但这似乎不需要尝试/抓住。在调试过程中,异常会导致merry hell,因为每次我检查字符串时,调试器都会在这里中断,“帮助”我解决讨厌的问题 我不知道如何在没有异常的情况下进行验证,但是如果未处理,您可以将调试器设置更改为仅中断
XmlException
,这应该可以解决您眼前的问题,即使代码仍然不雅
要执行此操作,请转到调试/异常…/公共语言运行时异常并查找System.Xml.XmlException,然后确保只勾选了“User unhandled”(未抛出)。这是一种合理的方法,只是IsNullOrEmpty是冗余的(LoadXml可以很好地解决这个问题)。如果确实保持IsNullOrEmpty,请执行If(!string.IsNullOrEmpty(value))
但基本上,问题出在调试器上,而不是代码。将
[System.Diagnostics.DebuggerStepThrough]
属性添加到IsValidXml
方法中。这将禁止调试器捕获XmlException,这意味着您可以打开第一次更改异常的捕获,并且不会调试此特定方法
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();
}
string str=“AQID”;
XmlTextReader r=新的XmlTextReader(新的StringReader(str));
尝试
{
while(r.Read())
{
}
}
最后
{
r、 Close();
}
来源:我不同意问题出在调试器上。一般来说,对于非例外情况,应避免例外情况。这意味着,如果有人正在寻找类似
IsWellFormed()
的方法,该方法根据输入是否为格式良好的XML返回true/false,则无论是否捕获和处理异常,都不应在此实现中抛出异常
异常代价高昂,在正常成功执行期间不应遇到异常。例如,编写一个方法来检查文件是否存在,并使用file.Open在文件不存在的情况下捕获异常。这将是一个糟糕的实现。相反,应该使用File.Exists()
(希望它的实现不会简单地对某个方法进行try/catch操作,如果该文件不存在,就会抛出异常,我确信它不存在)。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));
}
公共静态bool IsValidXml(字符串xmlString)
{
Regex tagsWithData=newregex(“[^只要我的2美分-关于这一点有各种各样的问题,大多数人都同意“垃圾输入-垃圾输出”"事实上,我并不反对这一点——但我个人发现了以下快速而肮脏的解决方案,特别是对于处理来自第三方的xml数据的情况,这些数据根本不容易与您通信……它并没有避免使用try/catch——但它使用的粒度更细,因此在无效xml字符数量减少的情况下s没有那么大,它有帮助..我使用了XmlTextReader,它的方法ReadChars()用于每个父元素,这是一个不像ReadInner/OuterXml那样进行格式良好检查的命令。因此,它是Read()和ReadChars()的组合父节点上的存根。当然,这是可行的,因为我可以假设XML的基本结构没有问题,但某些节点的内容(值)可以包含未被替换为&;等效…(我在某处找到一篇关于此的文章,但目前找不到源链接)我的2美分。这非常简单,并且遵循一些常见的约定,因为它是关于解析的
public bool TryParse(string s, ref XmlDocument result)
{
try {
result = new XmlDocument();
result.LoadXml(s);
return true;
} catch (XmlException ex) {
return false;
}
}
使用XmlDocument
时要小心,因为可以使用
XmlDocument doc=(XmlDocument)JsonConvert.DeserializeXmlNode(对象)
,不会引发异常
数字元素名称不是有效的xml,在我的例子中,直到我尝试将xmlDoc.innerText写入Sql server数据类型xml时才发生错误
这就是我现在验证的方式,并引发异常
XmlDocument tempDoc=XmlDocument)JsonConvert.DeserializeXmlNode(formData.ToString(),“data”);
doc.LoadXml(tempDoc.InnerXml);
我使用这个函数来验证字符串/片段
<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
此外,当只验证XML字符串的语法正确性时(无需解析外部架构),我认为添加XmlResolver=null
设置可能是一个好主意。这既可以确保安全性(无Web访问)又可以确保安全性(避免恶意XML内容将代码定向到坏站点)。代码如下(要求C#2.0或更高):
C#6.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;
}
}
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;
}
}
+1用于此救生解决方案。我仅在必须调试失败的代码时启用在处理异常时中断。我同意。我已使用调试器属性[DebuggerStepThrough]标记该方法,该属性可停止调试器停止
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;
}
}