我遇到了使用XSD验证XML的真正困难。我应该在所有这些前面加上前缀,我是XSD和验证的新手,所以我不确定这是代码问题还是XML问题。我已经使用了大量不同的选项来回到XML API,并认为我已经找到了使用XSD验证XML的理想策略。请注意,我的XML和XSD来自数据库,所以我不需要从磁盘读取任何内容。
我已将问题缩小为简单的示例Windows Forms应用程序。它有一个XSD文本框(txtXsd),一个XML文本框(txtXml),一个结果文本框(txtResult),以及一个启动验证的按钮(btnValidate)。
我正在使用Microsoft的示例XSD文件,
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:bookstore-schema" elementFormDefault="qualified" targetNamespace="urn:bookstore-schema">
<xsd:element name="title" type="xsd:string" />
<xsd:element name="comment" type="xsd:string" />
<xsd:element name="author" type="authorName"/>
<xsd:complexType name="authorName">
<xsd:sequence>
<xsd:element name="first-name" type="xsd:string" />
<xsd:element name="last-name" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
我在我的应用程序中使用以下代码。
private void btnValidate_Click (object sender, EventArgs e)
{
try
{
XmlTextReader reader = new XmlTextReader(txtXsd.Text, XmlNodeType.Document, new XmlParserContext(null, null, String.Empty, XmlSpace.None));
XmlSchema schema = XmlSchema.Read(reader, null);
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(schema);
XDocument doc = XDocument.Parse(txtXml.Text);
doc.Validate(schemas, ValidateSchema);
}
catch (Exception exception)
{
txtResult.Text += exception.Message + Environment.NewLine;
}
}
private void ValidateSchema (Object sender, ValidationEventArgs e)
{
txtResult.Text += e.Message + Environment.NewLine;
}
作为测试,我输入了有效的XML,但我认为不应该符合上面的XSD。
<xml>
<bogusNode>blah</bogusNode>
</xml>
结果是什么,没有任何验证错误。我该如何解决?
答案 0 :(得分:4)
嗯,对于一个 - 您的XSD定义了一个XML命名空间xmlns="urn:bookstore-schema"
,它不存在于您的XML测试文件中 - 因此,您的XML测试文件中的任何内容都不会被验证。
如果从架构中删除这些元素:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="title" type="xsd:string" />
然后它将正确验证您的XML测试文件并抱怨错误的元素。
同样使用名为<xml>
的元素可能不是一个好主意 - 因为指令<?xml ......?>
是预定义的指令,不应在文档的其他位置显示为标记名称。
马克
答案 1 :(得分:2)
我不希望用户提交未在XSD中定义的XML。
为什么要关心?您的模式验证命名空间中的XML节点。您的处理逻辑处理命名空间中的XML节点。不在命名空间中的节点与架构或逻辑无关。
如果将XML文档中的所有节点限制为特定命名空间是非常必要的,则可以通过扩展here找到的基本XmlReader
验证逻辑来实现此目的。
public static void Main()
{
const string myNamespaceURN = "urn:my-namespace";
XmlSchemaSet sc = new XmlSchemaSet();
sc.Add(myNamespaceURN, "mySchema.xsd");
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas = sc;
settings.ValidationEventHandler += ValidationCallBack;
XmlReader reader = XmlReader.Create("myDocument.xml", settings);
while (reader.Read())
{
if ((reader.NodeType == XmlNodeType.Element ||
reader.NodeType == XmlNodeType.Attribute)
&&
reader.NamespaceURI != myNamespaceURN)
{
LogError(reader.NamespaceURI + " is not a valid namespace.");
}
}
}
private static void ValidationCallBack(object sender, ValidationEventArgs e)
{
LogError(e.Message);
}
private static void LogError(string msg)
{
Console.WriteLine(msg);
}
答案 2 :(得分:1)
您也可以尝试XmlValidatingReader进行XML验证