【发布时间】:2018-05-03 18:50:59
【问题描述】:
如何清理 XML 文件,删除提供的 XSD 中不存在的所有元素?
这不起作用:
public static void Main()
{
XmlTextReader xsdReader = new XmlTextReader(@"books.xsd");
XmlSchema schema = XmlSchema.Read(xsdReader, null);
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(schema);
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
XmlReader xmlReader = XmlReader.Create(@"books.xml", settings);
XmlWriter xmlWriter = XmlWriter.Create(@"books_clean.xml");
xmlWriter.WriteNode(xmlReader, true);
xmlWriter.Close();
xmlReader.Close();
}
private static void ValidationCallBack(object sender, ValidationEventArgs args)
{
((XmlReader)sender).Skip();
}
当我使用上述方法时,它不会删除所有“垃圾”标签,而是仅删除第一个垃圾标签并留下第二个。至于为什么我需要接受这个文件,我使用的是旧的 SQLServer 2012 实例,它 需要 XML 与 XSD 完全匹配,即使应用程序不使用 XML 中的额外元素。我无法控制由带有未发布 XSD 的 3rd 方工具提供的源 XML。
示例文件:
书籍.xsd
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="bookstore">
<xs:complexType>
<xs:sequence>
<xs:element name="book" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="title"/>
<xs:element type="xs:float" name="price"/>
</xs:sequence>
<xs:attribute type="xs:string" name="genre" use="optional"/>
<xs:attribute type="xs:string" name="ISBN" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
书籍.xml
<bookstore>
<book genre='novel' ISBN='10-861003-324'>
<title>The Handmaid's Tale</title>
<price>19.95</price>
<junk>skdjgklsdg</junk>
<junk2>skdjgklsdg</junk2>
</book>
<book genre='novel' ISBN='1-861001-57-5'>
<title>Pride And Prejudice</title>
<price>24.95</price>
<junk>skdjgssklsdg</junk>
</book>
</bookstore>
【问题讨论】:
-
源 XML 文件是 ~500mb,最后一个输入文件有 ~120K 可用节点和 ~800K 未使用节点。因此,首选基于流的方法。
-
您缺少以下内容:while (reader.Read()) ;
-
@jdweng 尝试了这个并修改了问题。 Reader.Read() 仅在每个节点的第一个无效元素上引发 ValidationEvent。它至少删除了两个
标签,而不是 标签。 -
问题是当你有像 1,2,3,4,5 这样的项目并且你删除项目“3”时,4 变成了 3,5 变成了 4。然后你最终会跳过第 4 项。所以解决方案是通过类似 for(i = list.Count() - 1; i >=0; i--) 向后枚举
标签: c# xml xsd xsd-validation