2017-02-21 1 views
7

우리는 미래에 프로젝트에 F #을 활용하려고하고 있으며 F # 유형의 .xsd 스키마를 자동으로 생성 할 수 있기를 원합니다.F # 유형에 대해 .xsd를 생성하는 방법이 있습니까?

웹 검색은 .xsd에서 유형을 생성하는 데 많은 답을 표시하지만 그 반대의 경우는 아닙니다.

아무도이 작업을 수행하는 방법을 알고 있습니까?

답변

4

그런 의미는 실제로 의미하는 바에 달려 있습니다.

의미 : "어떻게하면 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를 생성합니다."

+0

답변 해 주셔서 감사합니다. 우리는 F #의 간결함을 이용하기 위해 F # 유형 자체에 대한 .xsd를 생성하고 기본 CLI 유형을 생성하지 않을 것입니다. 우리는 .dll을 통해 접근 방식을 시도해 보입니다. 그러나 더 직접적인 매핑이 가능하기를 희망합니다. –

0

내가 틀릴 수도 있지만, 충분히 잘 작동하는 경우 XSD를 기반으로하는 F # 유형 공급자를 사용하는 것보다 더 실용적인 방법으로 어떻게 수행 할 수 있는지 보지 못합니다. 그러나 그때, 나는 하나가 있는지 확신하지 못한다.

FSharp.Data.Xsd 유형 공급자를 사용해보십시오. 소스에서 XSD를 문자열로 지정하거나 소스 외부의 XSD 파일을 참조하여 지정할 수 있습니다. 원하는 XSD를 생성 할 수 없습니다.

문제는 필자가 준비 할 필요가없는 타협을하지 않는 한 F # 유형만으로는 XSD의 모습을 구체적으로 지정할 수 없다는 것입니다.

  • 매핑을 제어하기 위해 F #에서 특정 유형을 만들겠습니까? 그런 유형을 사용하지 않아도 "F #을 활용할 것"이라고 생각하지 않습니다.

  • 코드 속성이나 다른 메타 데이터를 사용 하시겠습니까? 이 경우 F # 형식 대신 XSD를 편집하지 않는 것이 좋습니까?

  • 일대일 매핑을 암시하는 규칙을 간단하게 만들겠습니까? 작동하지만 원하는 XSD 및 XML을 생성하지 못할 수도 있습니다. 그것은 너무 장황해질 수 있습니다.

XSD를 생성해야합니다. 반면에 유형 제공자를 사용하여 XSD에서 F # 유형을 생성하면 생성 된 유형을 즉시 사용할 수 있습니다.훨씬 더 실용적이고 즐겁지 않습니까?

0

나는 'typeclasses'를 사용하여 이것을 접근 할 것입니다. 빠른 예제 (REPL에서). type Person = { id : int64; name : string}과 같이 Person 유형이 있다고 가정합니다. 그러면 :

이것은 Xsd 모듈의 종류마다 작은 계산기 기능을 바꾸어 동작
> ("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.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의 모든을 구현할 필요는 없습니다. 유형을 실제로 사용하기 만하면됩니다.

0

코드에서 모든 유형의 XSD를 생성하려면이 F # 스크립트를 살펴보십시오. F # 레코드 유형의 XSD를 생성합니다. Script는 세 가지 .NET 어셈블리 (System.Runtime.Serialization.dll, System.Runtime.Serialization.Xml, System.Xml)를 사용합니다.

#r "System.Runtime.Serialization.dll" 
#r "System.Runtime.Serialization.Xml.dll" 
#r "System.Xml.dll" 

open System 
open System.IO 
open System.Linq 
open System.Text 
open System.Text.RegularExpressions 
open System.Xml 
open System.Runtime.Serialization 

type [<DataContract>] CommitInfo = { 
    [<field: DataMember(Name="id") >] 
    id: string 
    [<field: DataMember(Name="date") >] 
    date: DateTime 
    [<field: DataMember(Name="issueUrl") >] 
    issueUrl: string 
    [<field: DataMember(Name="issueId") >] 
    issueId: int 
    [<field: DataMember(Name="message") >] 
    message: string 
    [<field: DataMember(Name="url") >] 
    url: string 
} 

let getXmlWriter (stream: Stream) = 
    //let utf8noBOM = new UTF8Encoding(false) 
    let settings = new XmlWriterSettings() 
    settings.Indent <- true 
    settings.Encoding <- Encoding.UTF8 
    //settings.OmitXmlDeclaration <- true 
    XmlWriter.Create(stream, settings) 

let streamToString (stream: Stream) = 
    stream.Position <- int64 0 
    use sr = new StreamReader(stream) 
    sr.ReadToEnd() 

let getResultFromStream (streamWriter: Stream -> unit) = 
    use stream = new MemoryStream() 
    streamWriter stream 
    streamToString stream 

let exporter = XsdDataContractExporter() 
exporter.Export(typeof<CommitInfo array>) 
let schemas = exporter.Schemas.Schemas().Cast<Schema.XmlSchema>() |> Array.ofSeq 
let schema = schemas.[1] 

fun s -> s |> getXmlWriter |> schema.Write 
|> getResultFromStream 
|> printfn "%s" 
관련 문제