c#
  • xml
  • xsd
  • xml-namespaces
  • 2012-04-12 71 views 16 likes 
    16

    下面是一个XSD:使用的XSD与包括

    <?xml version="1.0"?> 
    <xsd:schema 
    elementFormDefault='unqualified' 
    attributeFormDefault='unqualified' 
    xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
    > 
    
        <xsd:simpleType name='TheSimpleType'> 
        <xsd:restriction base='xsd:string' /> 
        </xsd:simpleType> 
    </xsd:schema> 
    

    这里是一个第二XSD包含上面的一个:

    <?xml version="1.0" encoding="UTF-8" ?> 
    <xsd:schema 
    elementFormDefault='unqualified' 
    attributeFormDefault='unqualified' 
    xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
    targetNamespace='a' 
    xmlns='a' 
    > 
    
        <xsd:include schemaLocation='Include.xsd' /> 
    
        <xsd:element name = "TheElement" > 
        <xsd:complexType> 
        <xsd:attribute name="Code" type="TheSimpleType" use="required"/> 
        </xsd:complexType> 
        </xsd:element> 
    </xsd:schema> 
    

    我需要读取(第二)XSD到C#和:

    1. 检查,这是一个有效的XSD和
    2. 反对验证文档。

    下面是一些C#中的图式阅读:

    XmlSchemaSet schemaSet = new XmlSchemaSet(); 
        foreach (string sd in Schemas) 
        { 
         using (XmlReader r = XmlReader.Create(new FileStream(sd, FileMode.Open))) 
         { 
          schemaSet.Add(XmlSchema.Read(r, null)); 
         } 
        } 
        schemaSet.CompilationSettings = new XmlSchemaCompilationSettings(); 
        schemaSet.Compile(); 
    

    的.Compile()失败,因为 “类型。 '一:TheSimpleType' 未声明,或者不是一个简单的类型”

    但是,它的工作原理如果任:

    • 命名空间从架构移除或
    • 命名空间被添加到包括。

    问题是:如何让C#在不编辑模式的情况下接受它?

    我怀疑问题是,虽然我已经把这两个模式放到XmlSchemaSet中,但我仍然需要告诉C#一个包含在另一个中,即它没有为它自己完成。事实上,如果我只告诉XmlSchemaSet有关主XSD(而不是包含)(都没有(或带有)命名空间),那么“Type'TheSimpleType'没有声明,或者不是简单类型。

    因此,这似乎是一个关于解决包括的问题:怎么样?!

    回答

    4

    您可以使用XmlSchema.Includes将它们链接在一起。然后,你只需要到主架构添加到架构集合:

    var includeSchema = XmlSchema.Read(XmlReader.Create(...), null); 
    var mainSchema = XmlSchema.Read(XmlReader.Create(...), null); 
    
    var include = new XmlSchemaInclude(); 
    include.Schema = includeSchema; 
    mainSchema.Includes.Add(include); 
    
    var schemaSet = new XmlSchemaSet(); 
    schemaSet.Add(mainSchema); 
    schemaSet.Compile(); 
    
    +1

    +1从来不知道“XmlSchemaInclude”类。很好的答案。 – psubsee2003 2012-04-12 17:53:17

    +2

    好,好。但是现在假设我必须在运行时确定所有的包含,也就是说,我给你一个任意的包含XSD的XSD,你必须去获取它们。 – 2012-04-12 17:59:11

    +0

    's = XmlSchema.Read(r,null);' 现在我看到我们有'.Includes',它们是'XmlSchemaInclude'对象,并且它的正确填充(包含1)。 – 2012-04-12 18:02:35

    0

    试试这个:d特别是si.TargetNamespace = s.TargetNamespace;

    public static XmlSchema LoadSchema(string pathname) 
    { 
        XmlSchema s = null; 
        XmlValidationHandler h = new XmlValidationHandler(); 
        using (XmlReader r = XmlReader.Create(new FileStream(pathname, FileMode.Open))) 
        { 
         s = XmlSchema.Read(r, new ValidationEventHandler(h.HandleValidationEvent)); 
        } 
    
        if (h.Errors.Count > 0) 
        { 
         throw new Exception(string.Format("There were {1} errors reading the XSD at {0}. The first is: {2}.", pathname, h.Errors.Count, h.Errors[0])); 
        } 
    
        return s; 
    } 
    
    public static XmlSchema LoadSchemaAndResolveIncludes(string pathname) 
    { 
        FileInfo f = new FileInfo(pathname); 
        XmlSchema s = LoadSchema(f.FullName); 
    
        foreach(XmlSchemaInclude i in s.Includes) 
        { 
         XmlSchema si = LoadSchema(f.Directory.FullName + @"\" + i.SchemaLocation); 
         si.TargetNamespace = s.TargetNamespace; 
         i.Schema = si; 
        } 
    
        return s; 
    } 
    
    public static List<ValidationEventArgs> Validate(string pathnameDocument, string pathnameSchema) 
    { 
        XmlSchema s = LoadSchemaAndResolveIncludes(pathnameSchema); 
    
        XmlValidationHandler h = new XmlValidationHandler(); 
    
        XmlDocument x = new XmlDocument(); 
        x.Load(pathnameDocument); 
        x.Schemas.Add(s); 
        s.Compile(new ValidationEventHandler(h.HandleValidationEvent)); 
        x.Validate(new ValidationEventHandler(h.HandleValidationEvent)); 
        return h.Errors; 
    } 
    

    注意。

    显然,这里假定包含被指定为相对于它们所包含的模式的文件路径。

    +0

    在(A包括B和C)和(B引用但不包括C)的情况下失败。确实有必要编写一个自定义的XmlResolver来解析文件名。 – 2012-04-16 17:22:54

    25

    的问题是与该模式被打开阅读上线方式:

    XmlReader.Create(new FileStream(sd, FileMode.Open) 
    

    我不得不写我自己的XmlResolver之前,我可以看到如何包含文件的路径,正在解决的:它来自可执行文件的目录,而不是来自父模式的目录。问题是父架构没有得到它的BaseURI集。以下是如何打开模式:

    XmlReader.Create(new FileStream(pathname, FileMode.Open, FileAccess.Read),null, pathname) 
    
    +0

    同样,感谢那个理查德+ 1.花了很长时间把我的头发拉出这个! – CountZero 2013-12-03 10:36:02

    +0

    当我使用System.IO.Path(pathname)作为Create的'baseUri'参数时,这对我有效。 – 2015-05-20 20:23:35

    0

    这是我写的处理xsd验证的方法。希望这有助于某个人。

     /// <summary> 
         /// Ensure all xsd imported xsd documented are in same folder as master xsd 
         /// </summary> 
         public XsdXmlValidatorResult Validate(string xmlPath, string xsdPath, string xsdNameSpace) 
         { 
          var result = new XsdXmlValidatorResult(); 
          var readerSettings = new XmlReaderSettings {ValidationType = ValidationType.Schema}; 
          readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; 
          readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; 
          readerSettings.Schemas.Add(null, xsdPath); 
    
          readerSettings.ValidationEventHandler += (sender, args) => 
           { 
            switch (args.Severity) 
            { 
             case XmlSeverityType.Warning: 
              result.Warnings.Add(args.Message); 
              break; 
             case XmlSeverityType.Error: 
              result.IsValid = false; 
              result.Warnings.Add(args.Message); 
              break; 
            } 
           }; 
    
          var reader = XmlReader.Create(xmlPath, readerSettings); 
    
          while (reader.Read()) { } 
    
          return result; 
         } 
    
    +0

    这在我的情况下不起作用。所有的XSD(和XML)文件都在同一个文件夹中。不过,它告诉我,包含的xsd中定义的类型没有定义 – CeOnSql 2016-12-01 12:58:38

    相关问题