Fsharp.Data:XML中的可选元素

时间:2015-12-14 09:13:02

标签: f#-data

在F#-Data类型提供程序的示例xml文件中,我有可选的元素,如下所示:

showText(true)

我不知道如何将OptionalElement指定为可选项。只能有一个RootElement,因此我无法添加另一个缺少OptionalElement的RootElement。我怎样才能告诉解析器,OptionalElement实际上是可选的?

2 个答案:

答案 0 :(得分:1)

XML类型提供程序通过从样本中推断出类型来工作。您可以使用可选的SampleIsList参数提供多个示例:

open FSharp.Data

type RootElement = XmlProvider<"""
<samples>
    <RootElement>
        <MandatoryElement> ... </MandatoryElement>
        <OptionalElement> ... </OptionalElement>
        <AnotherElement> ... </AnotherElement>
    </RootElement>
    <RootElement>
        <MandatoryElement> ... </MandatoryElement>
        <AnotherElement> ... </AnotherElement>
    </RootElement>
</samples>""", SampleIsList = true>

从这个样本列表中,XML Type Provder推断出OptionalElement是,...是可选的,并将其键入string option

let x = RootElement.Parse """
    <RootElement>
        <MandatoryElement> ... </MandatoryElement>
        <OptionalElement> ... </OptionalElement>
        <AnotherElement> ... </AnotherElement>
    </RootElement>"""
let y = RootElement.Parse """
    <RootElement>
        <MandatoryElement> ... </MandatoryElement>
        <AnotherElement> ... </AnotherElement>
    </RootElement>"""

用法:

> y.OptionalElement.IsSome;;
val it : bool = false
> x.OptionalElement.IsSome;;
val it : bool = true
> x.OptionalElement |> Option.get;;
val it : string = " ... "

答案 1 :(得分:0)

无法在XML本身中明确指定“可选”。如果XML类型提供程序在某些地方看到该元素而不是其他地方,则会推断出这种情况,但这只是一种有根据的猜测。

为明确地,严格指定哪些元素是可选的,可以是多个等,我们有一个叫做“XML Schema”的东西,也称为“XSD”。不幸的是,XML类型提供程序目前不支持XSD,尽管有an open issue for it

我可以提供给你的一个黑客就是:让你的根元素嵌套在另一个“超级根”元素之下,然后创建两个“真正的根”元素,这将让类型提供者推断出可选性。然后,类型提供程序将为您生成“超级根”类型,您可以立即忽略它,并且只使用嵌套的类型,即真正的根。

当然,由于XML类型提供程序不支持解析非根元素,因此每次解析时,您还必须在“超级根”元素中“包装”XML文本,这限制了解决小文件的问题。

type Xml = XmlProvider<"""
  <SuperRoot>
    <RootElement>
        <MandatoryElement> ... </MandatoryElement>
        <OptionalElement> ... </OptionalElement>
        <AnotherElement> ... </AnotherElement>
    </RootElement>
    <RootElement>
        <MandatoryElement> ... </MandatoryElement>
        <AnotherElement> ... </AnotherElement>
    </RootElement>
  </SuperRoot>
""">

let parse xml = (Xml.Parse ("<SuperRoot>" + xml + "</SuperRoot>")).RootElements.[0]