Xml 基于 XSD 在 C# 中的清理
Xml Cleaning based on XSD in C#
如何清理 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();
}
当我使用上面的方法时,它没有删除所有 "junk" 标签,而是只删除了第一个垃圾标签并留下了第二个。至于为什么我需要接受这个文件,我正在使用一个旧的 SQLServer 2012 实例,它 需要 XML 完全匹配 XSD 即使额外的XML 中的元素未被应用程序使用。我无法控制由第三方工具提供的源 XML 和未发布的 XSD.
示例文件:
Books.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>
Books.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>
大部分代码复制自:Validating an XML against referenced XSD in C#
如果只是删除名称未出现在架构中任何位置的所有元素的问题,那么它可能是可行的,如下所述。但是,在一般情况下 (a) 这不能确保实例对模式有效(例如,元素的顺序可能错误),以及 (b) 它可能会删除模式实际允许的元素(因为通配符)。
如果去除未知元素的方法看起来有用,您可以按如下方式进行:
(a) 编写 XSLT 样式表,通过查找 xs:element[@name]
声明从架构中提取所有元素名称,生成格式为
的文档
<allowedElements>
<allow name="book" namespace=""/>
<allow name="isbn" namespace=""/>
</allowedElement>
(b) 编写第二个(可流式传输的)XSLT 样式表:
<xsl:transform version="3.0" xmlns:xsl="....">
<xsl:mode on-no-match="shallow-copy" streamable="yes"/>
<xsl:key name="k" match="allow" use="@name, @namespace" composite="yes"/>
<xsl:template match="*[not(key('k', (local-name(), namespace-uri()), doc('allowed-elements.xml'))]"/>
</xsl:transform>
以下内容成功地从提供的示例中删除了所有垃圾标签。第二个 xsl:template 标签首先应用并匹配除特别列入白名单的标签之外的所有内容。然后第一个 xsl:template 标记将节点的副本写入 XmlWriter。
代码:
public static void Main()
{
XmlReader xmlReader = XmlReader.Create("books.xml");
XslCompiledTransform myXslTrans = new XslCompiledTransform();
myXslTrans.Load("books.xslt");
XmlTextWriter myWriter = new XmlTextWriter("books_clean.xml", null);
myXslTrans.Transform(xmlReader, null, myWriter);
xmlReader.Close();
myWriter.Close();
}
books.xslt
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:mode streamable="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[
not(name()='bookstore') and
not(name()='book') and
not(name()='title') and
not(name()='price')
]" />
</xsl:stylesheet>
如何清理 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();
}
当我使用上面的方法时,它没有删除所有 "junk" 标签,而是只删除了第一个垃圾标签并留下了第二个。至于为什么我需要接受这个文件,我正在使用一个旧的 SQLServer 2012 实例,它 需要 XML 完全匹配 XSD 即使额外的XML 中的元素未被应用程序使用。我无法控制由第三方工具提供的源 XML 和未发布的 XSD.
示例文件:
Books.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>
Books.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>
大部分代码复制自:Validating an XML against referenced XSD in C#
如果只是删除名称未出现在架构中任何位置的所有元素的问题,那么它可能是可行的,如下所述。但是,在一般情况下 (a) 这不能确保实例对模式有效(例如,元素的顺序可能错误),以及 (b) 它可能会删除模式实际允许的元素(因为通配符)。
如果去除未知元素的方法看起来有用,您可以按如下方式进行:
(a) 编写 XSLT 样式表,通过查找 xs:element[@name]
声明从架构中提取所有元素名称,生成格式为
<allowedElements>
<allow name="book" namespace=""/>
<allow name="isbn" namespace=""/>
</allowedElement>
(b) 编写第二个(可流式传输的)XSLT 样式表:
<xsl:transform version="3.0" xmlns:xsl="....">
<xsl:mode on-no-match="shallow-copy" streamable="yes"/>
<xsl:key name="k" match="allow" use="@name, @namespace" composite="yes"/>
<xsl:template match="*[not(key('k', (local-name(), namespace-uri()), doc('allowed-elements.xml'))]"/>
</xsl:transform>
以下内容成功地从提供的示例中删除了所有垃圾标签。第二个 xsl:template 标签首先应用并匹配除特别列入白名单的标签之外的所有内容。然后第一个 xsl:template 标记将节点的副本写入 XmlWriter。
代码:
public static void Main()
{
XmlReader xmlReader = XmlReader.Create("books.xml");
XslCompiledTransform myXslTrans = new XslCompiledTransform();
myXslTrans.Load("books.xslt");
XmlTextWriter myWriter = new XmlTextWriter("books_clean.xml", null);
myXslTrans.Transform(xmlReader, null, myWriter);
xmlReader.Close();
myWriter.Close();
}
books.xslt
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:mode streamable="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[
not(name()='bookstore') and
not(name()='book') and
not(name()='title') and
not(name()='price')
]" />
</xsl:stylesheet>