有没有办法为F#类型生成.xsd?

我们正在考虑在未来将F#用于我们的项目,并希望能够自动从F#类型生成.xsd模式。

在Web上搜索会返回很多从.xsd生成类型的答案,但不是相反。

有没有人知道一种方法来做到这一点?


这种依赖于你实际上的意思。

如果您的意思是:“我如何从dll生成XSD?” 那么它可以很简单地完成与svcutil ...好吧,考虑到其他一些条件得到满足,但有点可行:

以下命令为装配中的服务合同和关联类型生成元数据文档。

svcutil myAssembly.dll

https://msdn.microsoft.com/en-us/library/aa347733(v=vs.110).aspx

xsd.exe也应该能够做同样的事情。 我不知道这里的条件是什么,但是文档并不像svcutil那么“严格”。

以下命令为程序集myAssembly.dll中的所有类型生成XML模式,并将它们作为schema0.xsd保存在当前目录中。

xsd myAssembly.dll 

https://msdn.microsoft.com/en-us/library/x6c1kb0s(v=vs.110).aspx

如果你的意思是“从给定的* .fs文件生成XSD”,那么你有点不幸(据我所知)。


我可能是错的,但我不明白如何才能以比使用基于XSD的F#类型提供者更实用的方式来实现,如果有足够好的工作。 但是,我不确定是否有一个。

尝试使用FSharp.Data.Xsd类型提供程序。 您可以在源中将XSD指定为字符串,或者通过引用源外部的XSD文件。 它可能无法创建任何您想要的XSD。

我认为,问题在于F#类型本身并不是一种指定XSD应该是什么样子的实用方法,除非您做出一些妥协,或许您不打算做出。

  • 你会在F#中创建一些特定类型来控制映射吗? 我不认为使用这种类型将是“利用F#”。

  • 你会使用代码属性或其他元数据? 在这种情况下,是不是更好地编辑XSD而不是F#类型?

  • 你会简单地创建一些暗示一对一映射的规则吗? 它可以工作,但可能不会产生你想要的XSD和XML。 它可能变得太冗长。

  • 你将不得不生成XSD。 另一方面,如果您使用类型提供程序从XSD生成F#类型,则生成的类型将立即可用。 这不是更实际和令人愉快吗?


    我会用'typeclasses'来解决这个问题。 快速示例(在REPL中)。 假设你有一个Person类型,比如type Person = { id : int64; name : string} type Person = { id : int64; name : string} 。 然后:

    > ("id", Xsd.int64, "name", Xsd.string)
      |> Xsd.record2 "Person"
      |> Xsd.root
      |> Xsd.to_string;;
    val it : string =
      "<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <xsd:complexType name="Person">
      <xsd:sequence>
        <xsd:element name="id" type="long"/>
        <xsd:element name="name" type="string"/>
      </xsd:sequence>
    </xsd:complexType>
    </xsd:schema>"
    

    这是通过在Xsd模块中为每种类型放置很少的转换器函数以及类型的组合(即总和和产品类型)来实现的。 这应该涵盖大多数需求。 Xsd模块的外观可能如下所示:

    (* xsd.fsi *)
    
    /// Just a string marked by the type of data whose XSD it holds.
    /// Implementation is private so that callers can't create any XSD
    /// they like.
    type 'a t
    
    /// Gives us the string representation of the XSD.
    val to_string : 'a t -> string
    
    /// Wraps an XSD encoding inside the <xsd:schema> tag pair.
    val root : 'a t -> 'a t
    
    // Primitive types.
    
    val int : int t
    val int64 : int64 t
    val string : string t
    
    /// Encode a two-field record's type (name and fields along with their
    /// types) as XSD.
    val record2 : string -> string * 'a1 t * string * 'a2 t -> 'a t
    
    (* xsd.fs *)
    
    type 'a t = { to_string : string }
    
    let to_string xsd = xsd.to_string
    let root xsd =
      { to_string =
          sprintf "<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      %s
    </xsd:schema>" xsd.to_string }
    
    let int = { to_string = "integer" }
    let int64 = { to_string = "long" }
    let string = { to_string = "string" }
    
    /// Helper for record fields.
    let element name typ =
      sprintf "<xsd:element name="%s" type="%s"/>" name typ
    
    let record2 name (field1, xsd1, field2, xsd2) =
      { to_string =
          sprintf
            "<xsd:complexType name="%s">
      <xsd:sequence>
        %s
        %s
      </xsd:sequence>
    </xsd:complexType>"
            name
            (element field1 xsd1.to_string)
            (element field2 xsd2.to_string) }
    

    无可否认,与使用运行时反射相比,这是一种不熟悉的技术。 但它也更加类型安全,并且可以更好地控制编码。 你也可能不需要实现所有的XSD - 你只需要你的类型实际使用的部分。

    链接地址: http://www.djcxy.com/p/95265.html

    上一篇: Is there a way to generate an .xsd for F# types?

    下一篇: Accordion doesn't work in Bootstrap 4 collapse