.net与其他技术之间的XSD验证错误的区别

时间:2017-12-05 11:17:13

标签: c# xml xsd

我使用以下架构来验证c#应用程序中的XML。 以下代码是我正在做的事情的例子。但我发现,与其他技术的验证相比,验证存在差异。我不确定它是否与正则表达式有关。

<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/XMLSchema.xsd"
    xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
  <xsd:simpleType name="DateCCYYType">
    <xsd:annotation>
      <xsd:documentation>A type that is used for any century/year combination field.</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
      <xsd:maxLength value="4"/>
      <xsd:pattern value="(^$|[1-2][0-9][0-9][0-9])"/>
    </xsd:restriction>
  </xsd:simpleType>  
  <xsd:complexType name="PersonalDetails">
    <xsd:sequence>
      <xsd:element name="yearJoined" type="mstns:DateCCYYType"></xsd:element>
      <xsd:element name="yearReleased" type="mstns:DateCCYYType"></xsd:element>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:element name="PersonalDetails" type="mstns:PersonalDetails"></xsd:element>
</xsd:schema>

类文件如下

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            /*textBox1 Contains the xml text
            <urn:PersonalDetails xmlns:urn="http://tempuri.org/XMLSchema.xsd">
                <urn:yearJoined></urn:yearJoined>
                <urn:yearReleased>5000</urn:yearReleased>
            </urn:PersonalDetails>
             */
            StringReader reader = new StringReader(textBox1.Text);
            XmlTextReader xmlReader = new XmlTextReader(@"C:\visual studio 2015\Projects\WindowsFormsApplication1\SampleSchema.xsd");
            Exception xsdException = new Exception();
            try
            {
                bool isValid = IsXmlValidForSchema(reader, xmlReader, ref xsdException);
                if (isValid)
                {
                    MessageBox.Show("Success");
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }


        }

        public static void ValidateXml(
            StringReader srXML,
            XmlTextReader xtrSchema)
        {

            XmlSchemaSet xssValidate = null;
            try
            {
                xssValidate = new XmlSchemaSet();
                xssValidate.Add(null, xtrSchema);
                xssValidate.Compile();
                XPathDocument xpdValidate = new XPathDocument(srXML);
                XPathNavigator editor = xpdValidate.CreateNavigator();
                if (!editor.CheckValidity(xssValidate, ValidateEventHandler))
                {
                    throw new System.Xml.Schema.XmlSchemaValidationException();
                }
            }
            finally
            {
                if (xssValidate != null) xssValidate = null;
            }
        }

        public static bool IsXmlValidForSchema(
            StringReader xmlReader,
            XmlTextReader schemaReader, ref Exception xsdException)
        {
            bool result = true;
            try
            {
                ValidateXml(xmlReader, schemaReader);
            }
            catch (XmlSchemaValidationException ex)
            {

                xsdException = ex;
                result = false;
            }
            return result;
        }

        private static void ValidateEventHandler(object sender, ValidationEventArgs e)
        {
            if (e.Severity == XmlSeverityType.Error || e.Severity == XmlSeverityType.Warning)
            {
                XmlSchemaException schemaException = new XmlSchemaException(e.Message, e.Exception);
                throw schemaException;
            }
        }

    }

如果在注释块中使用xml,它会验证正常,并且不会因yearJoined的空白而抛出错误。但是,如果我使用其他验证器(如XMLSPY或任何在线验证器)对此进行验证,则会将这些验证器显示为错误。 我可以使用minLength在.Net中修复此问题。但为什么会发生冲突呢?有没有办法纠正它。

2 个答案:

答案 0 :(得分:0)

Microsoft的XSD处理器在使用正则表达式方面不符合要求:通常它的正则表达式遵循.NET约定而不是W3C约定。

在这个特定示例中,问题是字符^$,它们是符合XSD正则表达式的普通字符,而不是元字符。

答案 1 :(得分:0)

以下是我用来测试的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.XPath;
using System.IO;


namespace ConsoleApplication16
{
    class Program
    {
        const string SCHEMA_FILENAME = @"c:\temp\test1.xml";
        static void Main(string[] args)
        {
            //textBox1 Contains the xml text
            string xml = "<urn:PersonalDetails xmlns:urn=\"http://tempuri.org/XMLSchema.xsd\">" +
                     "<urn:yearJoined></urn:yearJoined>" +
                     "<urn:yearReleased>2017</urn:yearReleased>" +
                 "</urn:PersonalDetails>";

            StringReader reader = new StringReader(xml);
            XmlTextReader xmlReader = new XmlTextReader(SCHEMA_FILENAME);
            Exception xsdException = new Exception();
            try
            {
                bool isValid = IsXmlValidForSchema(reader, xmlReader, ref xsdException);
                if (isValid)
                {
                    Console.WriteLine("Success");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

        }
        public static void ValidateXml(
    StringReader srXML,
    XmlTextReader xtrSchema)
        {

            XmlSchemaSet xssValidate = null;
            try
            {
                xssValidate = new XmlSchemaSet();
                xssValidate.Add(null, xtrSchema);
                xssValidate.Compile();
                XPathDocument xpdValidate = new XPathDocument(srXML);
                XPathNavigator editor = xpdValidate.CreateNavigator();
                if (!editor.CheckValidity(xssValidate, ValidateEventHandler))
                {
                    throw new System.Xml.Schema.XmlSchemaValidationException();
                }
            }
            finally
            {
                if (xssValidate != null) xssValidate = null;
            }
        }

        public static bool IsXmlValidForSchema(
            StringReader xmlReader,
            XmlTextReader schemaReader, ref Exception xsdException)
        {
            bool result = true;
            try
            {
                ValidateXml(xmlReader, schemaReader);
            }
            catch (XmlSchemaValidationException ex)
            {

                xsdException = ex;
                result = false;
            }
            return result;
        }

        private static void ValidateEventHandler(object sender, ValidationEventArgs e)
        {
            if (e.Severity == XmlSeverityType.Error || e.Severity == XmlSeverityType.Warning)
            {
                XmlSchemaException schemaException = new XmlSchemaException(e.Message, e.Exception);
                throw schemaException;
            }
        }
    }

}