Validating XML with XSD

末鹿安然 提交于 2019-12-30 02:19:12

问题


I'm running into real difficulties validating XML with XSD. I should prefix all of this and state up front, I'm new to XSD and validation, so I'm not sure if it's a code issue or an XML issue. I've been to XML API hell and back with the bajillion different options and think that I've found what would be the ideal strategy for validating XML with XSD. Note, my XML and XSD are coming from a database, so I don't need to read anything from disk.

I've narrowed my problem down into a simple sample Windows Forms application. It has a textbox for XSD (txtXsd), a textbox for XML (txtXml), a textbox for the result (txtResult), and a button to start the validation (btnValidate).

I'm using a sample XSD file from Microsoft,

<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>

I'm using the following code in my application.

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;
}

As a test, I put in valid XML, but what I think should not conform to the XSD above.

<xml>
    <bogusNode>blah</bogusNode>
</xml>

The result is nothing, no validation errors whatsoever. How do I fix it?


回答1:


Well, for one - your XSD defines a XML namespace xmlns="urn:bookstore-schema" which is not present in your XML test file - therefore, nothing in your XML test file will be validated.

If you remove those elements form your schema:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:element name="title" type="xsd:string" />

then it will properly validate your XML test file and complain about the wrong elements.

Also using an element named <xml> might not be a great idea - since the directive <?xml ......?> is a pre-defined directive and should not appear as tag name elsewhere in your document.

Marc




回答2:


I don't want the user to submit XML that's not defined in the XSD.

Why do you care? Your schema validates the XML nodes that are in your namespace. Your processing logic processes the XML nodes that are in your namespace. Nodes that aren't in your namespace aren't relevant to either your schema or your logic.

If it's truly essential to restrict all nodes in the XML document to a specific namespace, you can accomplish that by extending the basic XmlReader validating logic found here.

    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);
    }



回答3:


You may also try XmlValidatingReader for XML validation



来源:https://stackoverflow.com/questions/943131/validating-xml-with-xsd

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!