我们有一个字符串字段,可以包含XML或纯文本。 XML不包含<?xml
标头,也没有根元素,即格式不正确。
我们需要能够编辑XML数据,清空元素和属性值,只留下它们的名称,所以我需要在编辑之前测试这个字符串是否为XML。
目前我正在使用这种方法:
string redact(string eventDetail)
{
string detail = eventDetail.Trim();
if (!detail.StartsWith("<") && !detail.EndsWith(">")) return eventDetail;
...
有更好的方法吗?
这种方法可能会遗漏任何边缘情况吗?
我感谢我可以使用XmlDocument.LoadXml
并抓住XmlException
,但这感觉就像一个昂贵的选项,因为我已经知道很多数据都不是XML格式。
这是一个XML数据的例子,除了缺少一个根元素(为了节省空间而省略,因为会有很多数据),我们可以假设它已经很好地形成了:
<TableName FirstField="Foo" SecondField="Bar" />
<TableName FirstField="Foo" SecondField="Bar" />
...
目前我们只使用基于属性的值,但如果数据变得更复杂,我们将来可能会使用元素。
解决方案
基于多条评论(谢谢大家!)
string redact(string eventDetail)
{
if (string.IsNullOrEmpty(eventDetail)) return eventDetail; //+1 for unit tests :)
string detail = eventDetail.Trim();
if (!detail.StartsWith("<") && !detail.EndsWith(">")) return eventDetail;
XmlDocument xml = new XmlDocument();
try
{
xml.LoadXml(string.Format("<Root>{0}</Root>", detail));
}
catch (XmlException e)
{
log.WarnFormat("Data NOT redacted. Caught {0} loading eventDetail {1}", e.Message, eventDetail);
return eventDetail;
}
... // redact
答案 0 :(得分:8)
如果您首先要接受格式不正确的XML,我认为捕获异常是处理它的最佳方式。
答案 1 :(得分:3)
一种可能性是混合两种解决方案。您可以使用您的编辑方法并尝试加载它(在if中)。这样,您只会尝试加载可能是格式正确的xml,并丢弃大多数非xml条目。
答案 2 :(得分:2)
如果您的目标是可靠性,那么最好的选择是使用XmlDocument.LoadXml来确定它是否是有效的XML。完整的数据解析可能很昂贵,但它是可靠地判断它是否是有效XML的唯一方法。否则,您未在缓冲区中检查的任何字符都可能导致数据为非法XML。
答案 3 :(得分:1)
取决于您想要的测试准确度。考虑到你已经没有官方的&lt; xml,你已经在尝试检测不是XML的东西了。理想情况下,您将通过完整的XML解析器解析文本(如您所建议的那样);它拒绝的任何东西都不是XML。问题是,您是否关心是否接受非XML字符串?例如, 你接受
没关系吗? <the quick brown fox jumped over the lazy dog's back>
作为XML并剥离它?如果是这样,你的技术很好。如果没有,你必须决定你想要的测试紧密程度,并用那种程度的紧密度来编码识别器。
答案 4 :(得分:1)
数据是如何传递给您的?围绕它的其他类型的数据是什么?也许有更好的方法;也许你可以标记你控制的数据,然后推断出那些不在这些标记中的东西是XML,但我们需要知道更多。
如果没有这样一个可爱的解决方案,我认为你拥有的很好(用于验证它是以这些角色开始和结束的。)
我们需要真正了解有关数据格式的更多信息。
答案 5 :(得分:0)
如果XML不包含根元素(即它是一个XML片段,而不是一个完整的文档),那么以下内容也是完全有效的样本 - 但与您的探测器不匹配:
foo<bar/>baz
实际上,任何文本字符串都是有效的XML片段(考虑原始XML文档是否只是包装一些文本的根元素,并且你将根元素标记带走了)!
答案 6 :(得分:0)
try
{
XmlDocument myDoc = new XmlDocument();
myDoc.LoadXml(myString);
}
catch(XmlException ex)
{
//take care of the exception
}