如何反序列化 XML 个子元素数量可变的元素?

How to deserialize XML elements with variable number of children?

XML 被反序列化的最小示例,我们称之为 newyorker.xml:

<?xml version="1.0" encoding="utf-8"?>
<Root>
    <Periodical subscription="true" issues_per_year="47">
        <Title>The New Yorker</Title>
        <Website>newyorker.com</Website>

        <Edition available="true" date="2018-04-16">
            <Contributor>Junot Diaz</Contributor>
            <Contributor>Louisa Thomas</Contributor>
            <Contributor>D. T. Max </Contributor>
            <!-- More contributors omitted -->
        </Edition>

        <Edition available="true" date="...">
            <Contributor>David Remnick</Contributor>
            <Contributor>Malcolm Gladwell</Contributor>
            <!-- More contributors omitted -->
        </Edition>

       <!-- More editions omitted -->
    </Periodical>
    <Other>
        <Foo>Foo</Foo>
        <Foo>Bar</Foo>
    </Other>
</Root>

反序列化代码:

open System.Xml
open System.Xml.Serialization

let Deserialize<'T> file rootnode =
    file |> File.ReadAllText
         |> (fun data -> new StringReader(data))
         |> (new System.Xml.Serialization.XmlSerializer(typeof<'T>, new System.Xml.Serialization.XmlRootAttribute(rootnode))).Deserialize

EditionPeriodical 类型的当前定义:

[<CLIMutable>]
type Edition = {
    [<XmlAttribute("available")>] Available : bool
    [<XmlAttribute("date")>]   Date : string
    [<XmlElement>]   Contributor : string list // What goes here? 
}

[<CLIMutable>]
type Periodical = {
    [<XmlAttribute("subscription")>]      Subscription : bool
    [<XmlAttribute("issues_per_year")>]   IssuesPerYear: int
    [<XmlElement>] Title: string
    [<XmlElement>] Website : string
    [<XmlElement>] Edition : Edition list   // What goes here?
}

我的目标是将文件反序列化到 Periodical 节点。这可能使用 XmlSerializer 吗?如果是这样,我应该如何调整 PeriodicalEdition 的定义以使其工作?在 C# 中,appears 这可以通过声明 Periodical 包含一个 Edition 的数组(并且 Edition 包含一个 Contributor 的数组)来完成 -但我无法让它在 F# 中运行。

(我知道 XmlDocumentXDocument。这个问题专门针对 XmlSerializer。另外,修改 [=39= 的排列可能不可行] 文件由于遗留原因。)

[<CLIMutable>]
type Edition = {
    ...
    [<XmlElement>]   Contributor : string array
}

[<CLIMutable>]
type Periodical = {
    ...
    [<XmlElement>] Edition : Edition array
}

let p = Deserialize<Periodical[]> "test.xml" "Root"

适合我