C#中使用MemoryStream进行Xml Schema验证失败

5

这是我的函数。

如果您将MemoryStream传递给XmlReader,则有时无法验证正确的xml文件。我在内存中存储了XmlDocument对象,我想根据最终用户提供的xsd模式文件对其进行验证。

ValidateSchema1(string XMLPath, string XSDPath)
    {
        XmlDocument xmlDocument = new XmlDocument();

        xmlDocument.Load(XMLPath);

          using (MemoryStream mstream = new MemoryStream())
          {
              //StreamWriter writer = new StreamWriter(mstream);
              xmlDocument.Save(mstream);
              mstream.Seek(0, SeekOrigin.Begin);
              XmlSchemaSet sc = new XmlSchemaSet();

              // Add the schema to the collection.
              sc.Add(null, XSDPath);

              // Set the validation settings.
              XmlReaderSettings settings = new XmlReaderSettings();
              settings.ValidationType = ValidationType.Schema;
              settings.Schemas = sc;
              settings.ValidationEventHandler += ValidationCallBack;

              // Create the XmlReader object.

              // Not woking
              XmlReader reader = XmlReader.Create(mstream, settings);

              // Working
              //XmlReader reader = XmlReader.Create(new StringReader(xmlDocument.InnerXml), settings);

              // Working
              //XmlReader reader = XmlReader.Create(XMLPath, settings);

              // Parse the file. 
              while (reader.Read()) ;
          }

    }

2
当验证失败时,您确定XML是有效的吗?验证异常应该告诉您它为什么失败。 - Oded
2个回答

2
这可能会起作用: http://www.experts-exchange.com/Programming/Languages/.NET/Visual_CSharp/Q_23387252.html
这个可以正常工作: 如何在运行时验证XML与XSD,而不保存本地文件中的XSD文件?

编辑1:修复了您提供的代码,现在代码按预期工作,对我的2个文件进行了验证。您收到错误的原因是您试图使用自身验证和Xsd,并且根元素不存在。请查看解决方案以自行查看。

public void Xsd_whithout_saved()  
    {  
        XmlDocument xmlDoc = new XmlDocument();  
        xmlDoc.Load(@"file.xsd");  
        //In the futute, strArquivoInteiro will be fullfill by xsd comming from   database as nvarchar(max) and I will //not be allowed to save as a file locally    
        string strArquivoInteiro = xmlDoc.OuterXml;  

        byte[] byteArray = Encoding.ASCII.GetBytes(strArquivoInteiro);
        MemoryStream streamXSD = new MemoryStream(byteArray);
        //<<<
        streamXSD.Position = 0;
        StreamReader readerXsd = new StreamReader(streamXSD);

        XmlReaderSettings settings = new XmlReaderSettings();
        settings.ValidationEventHandler += this.MyValidationEventHandler;

        settings.ValidationType = ValidationType.Schema;
        settings.Schemas.Add(null, XmlReader.Create(readerXsd));
        settings.CheckCharacters = true;

        XmlReader XmlValidatingReader = XmlReader.Create(@"file.xml", settings);

        XmlTextReader Reader = new XmlTextReader(@"file.xsd");
        //Created another reader for xml to use for validation
        XmlTextReader Reader2 = new XmlTextReader(@"file.xml");

        XmlSchema Schema = new XmlSchema();

        //IN THIS LINE I RECEIVED THE XmlException "Root Element is Missing" and I can't understand the reason
        //This was the first problem, a xsd root element isn't equal to an xml root element , and you where trying to validate and xsd with xsd here, and of course the error.
        Schema = XmlSchema.Read(Reader, MyValidationEventHandler);

        XmlValidatingReader ValidatingReader = new XmlValidatingReader(Reader2);

        ValidatingReader.ValidationType = ValidationType.Schema;

        ValidatingReader.Schemas.Add(Schema);

        try
        {

            XmlValidatingReader.Read();
            XmlValidatingReader.Close();

            ValidatingReader.ValidationEventHandler += MyValidationEventHandler;

            while ((ValidatingReader.Read()))
            {

            }

            ValidatingReader.Close();
        }
        catch (Exception ex)
        {
            ValidatingReader.Close();
            XmlValidatingReader.Close();
        }
    }

0
为什么你的代码中不使用另外两个被注释掉的方法,而是使用内存流呢?
【更新】:
尝试一下这个答案:
    public static bool ValidateXmlFromXsd(string xml, string xsdFile)
    {

        bool returned = false;
        XmlValidatingReader reader = null;
        XmlSchemaCollection myschema = new XmlSchemaCollection();
        ValidationEventHandler eventHandler = new ValidationEventHandler(ShowCompileErrors);
        try
        {
            XmlParserContext context = new XmlParserContext(null, null, "", XmlSpace.None);
            reader = new XmlValidatingReader(xml, XmlNodeType.Element, context);
            myschema.Add("urn:schemas-microsoft-com:xml-msdata", xsdFile);
            reader.ValidationType = ValidationType.Schema;
            reader.Schemas.Add(myschema);

            while (reader.Read()) { }

            Console.WriteLine("Completed validating xmlfragment");
            returned = true;
        }
        catch (XmlException XmlExp)
        {
            Console.WriteLine(XmlExp.Message);
        }
        catch (XmlSchemaException XmlSchExp)
        {
            Console.WriteLine(XmlSchExp.Message);
        }
        catch (Exception GenExp)
        {
            Console.WriteLine(GenExp.Message);
        }
        finally
        {
            Console.Read();
        }
        return returned;
    }

因为提供的解决方案无法与我已有的类一起使用。 - radu florescu
我可以问一下你为什么要踩我吗?那只是一个建议,不是答案! - Azhar Khorasany
你本可以发表评论,而不是回答。 - radu florescu
1
我回家后会尝试这个。 - radu florescu
很遗憾,不是这样的。还有一个问题,你使用的几乎所有类都已经过时了,很快它们就会消失。 - radu florescu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接