Cat*_*h22 6 c# xml validation html-agility-pack
我正在从第三方提供程序解析一些XML文件,不幸的是,它并不总是格式良好的XML,因为有时某些元素包含重复的属性.
我无法控制源,我不知道哪些元素可能有重复的属性,也不知道重复的属性名称.
显然,将内容加载到XMLDocument对象中会在重复属性上引发XmlException,因此我可以使用a XmlReader逐个元素地逐步执行XML元素,并在到达有问题的元素时处理重复的属性.
然而,在我有机会对元素的属性进行插入之前,它XmlException被提升了reader.Read().
以下是演示此问题的示例方法:
public static void ParseTest()
{
const string xmlString =
@"<?xml version='1.0'?>
<!-- This is a sample XML document -->
<Items dupattr=""10"" id=""20"" dupattr=""33"">
<Item>test with a child element <more/> stuff</Item>
</Items>";
var output = new StringBuilder();
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
XmlWriterSettings ws = new XmlWriterSettings();
ws.Indent = true;
using (XmlWriter writer = XmlWriter.Create(output, ws))
{
while (reader.Read()) /* Exception throw here when Items element encountered */
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
writer.WriteStartElement(reader.Name);
if (reader.HasAttributes){ /* CopyNonDuplicateAttributes(); */}
break;
case XmlNodeType.Text:
writer.WriteString(reader.Value);
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
writer.WriteProcessingInstruction(reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
writer.WriteComment(reader.Value);
break;
case XmlNodeType.EndElement:
writer.WriteFullEndElement();
break;
}
}
}
}
string str = output.ToString();
}
Run Code Online (Sandbox Code Playgroud)
有没有其他方法来解析输入并删除重复的属性,而不必使用正则表达式和字符串操作?
我通过将 XML 视为 HTML 文档找到了解决方案。然后使用开源Html Agility Pack库,我能够获得有效的 XML。
诀窍是首先使用 HTML 标头保存 xml。
因此,将 XML 声明替换
<?xml version="1.0" encoding="utf-8" ?>
为 HTML 声明,如下所示:
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
将内容保存到文件后,此方法将返回有效的 XML 文档。
// Requires reference to HtmlAgilityPack
public XmlDocument LoadHtmlAsXml(string url)
{
var web = new HtmlWeb();
var m = new MemoryStream();
var xtw = new XmlTextWriter(m, null);
// Load the content into the writer
web.LoadHtmlAsXml(url, xtw);
// Rewind the memory stream
m.Position = 0;
// Create, fill, and return the xml document
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml((new StreamReader(m)).ReadToEnd());
return xmlDoc;
}
Run Code Online (Sandbox Code Playgroud)
重复的属性节点会自动删除,后面的属性值会覆盖前面的属性值。
| 归档时间: |
|
| 查看次数: |
4684 次 |
| 最近记录: |