使用 F# 反序列化 Xml

发布于 2024-10-28 08:16:07 字数 1423 浏览 1 评论 0原文

我从 Web 服务获取以下 xml,并将其转换为 .net 对象:

let xmlString = "<?xml version=\"1.0\"?>
<logInResponse>
  <result>OK</result>
  <xmlLogIn>
    <session>11C0ED6F8F7288855FC73C99979A9732.TOGKE6VP9aE8abcdLXaVXg</session>
    <user>WallStreetScumbag1</user>
    <authorizations>
      <insiderTrading>true</insiderTrading>
    </authorizations>
  </xmlLogIn>
</logInResponse>"

这是我到目前为止所拥有的:

type Result(value:XmlNode) = 
    member this.Value = value.InnerText

let (|Node|Result|) (node : #System.Xml.XmlNode) =
    if node.Name = "result" then
        Result (new Result(node))
    else
        Node (seq {for x in node.ChildNodes -> x})

let extract node =
    let rec extract node =
        match node with 
        | Result(p) ->
            Seq.singleton p
        | Node(nodes) ->
            Seq.collect (fun (n) -> extract n) nodes
    extract node

let xmlDoc = new XmlDocument()
xmlDoc.LoadXml(xmlString)

//type LogIn() =
    //This is where I would create a .net object that mirrors the xml.

正如您所看到的,一些元素在不同的元素中重复,有时元素不包括所有可以显示的元素,如您在我的示例 xml 中看到的那样。该相同的 Web 服务还将在其他类型的响应中重用许多相同的元素。是否可以使用活动模式创建一种通用方法来将我获取的 xml 反序列化回对象?看来这个 Web 服务从不使用属性来发送信息,它似乎都是元素内的元素,这可能会使这个问题变得更容易。如果我以错误的方式处理这个问题,请随时提出更好的建议。

预先感谢,

鲍勃

I get the following xml from a web service which I want to convert into .net objects:

let xmlString = "<?xml version=\"1.0\"?>
<logInResponse>
  <result>OK</result>
  <xmlLogIn>
    <session>11C0ED6F8F7288855FC73C99979A9732.TOGKE6VP9aE8abcdLXaVXg</session>
    <user>WallStreetScumbag1</user>
    <authorizations>
      <insiderTrading>true</insiderTrading>
    </authorizations>
  </xmlLogIn>
</logInResponse>"

This is what I have so far:

type Result(value:XmlNode) = 
    member this.Value = value.InnerText

let (|Node|Result|) (node : #System.Xml.XmlNode) =
    if node.Name = "result" then
        Result (new Result(node))
    else
        Node (seq {for x in node.ChildNodes -> x})

let extract node =
    let rec extract node =
        match node with 
        | Result(p) ->
            Seq.singleton p
        | Node(nodes) ->
            Seq.collect (fun (n) -> extract n) nodes
    extract node

let xmlDoc = new XmlDocument()
xmlDoc.LoadXml(xmlString)

//type LogIn() =
    //This is where I would create a .net object that mirrors the xml.

As you can see some elements are repeated within different elements and sometimes elements don't include all the elements that can show up as you can see in my sample xml. This same web service will also reuse many of these same elements in other types of responses. Is it possible to use active patterns to create a general way to deserialize the xml I get back into objects? It appears that this web service never uses attributes to send information, it all seems to be elements inside elements which might make this problem easier. If I am going about this the wrong way please feel free to suggest something better.

Thanks in advance,

Bob

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧人 2024-11-04 08:16:07

您使用活动模式来匹配不同类型节点的方法对我来说看起来不错。我可能会使用部分模式(当它们匹配时可以返回SomeNone)而不是完整模式(总是返回其中一种情况)。这允许您为正在处理的不同类型的节点编写多种模式。

let (|Result|_|) (node:#System.Xml.XmlNode) =
  if node.Name = "result" then
    Some(new Result(node))
  else
    None

在模式匹配中,您可以包含任意数量的部分模式,并使用 _ (通配符模式)覆盖所有剩余的情况:

match node with 
| Result(p) ->
    Seq.singleton p
| nd ->
    Seq.collect (fun (n) -> extract n) nd.ChildNodes

除此之外,我不确定 - 您示例中的结构看起来很规则,因此您不需要像 HTML 中那样处理情况(其中 可以嵌套在各种其他元素中)。看来您可以将 XML 的主要部分表示为帐户列表(并使用活动模式解析所有帐户属性)。

Your approach to use active patterns to match different types of nodes looks good to me. I would probably use partial patterns (that can either return Some when they match or None) instead of complete patterns (that always return one of the cases). This allows you to write several patterns for different types of nodes you're handling.

let (|Result|_|) (node:#System.Xml.XmlNode) =
  if node.Name = "result" then
    Some(new Result(node))
  else
    None

In the pattern matching, you can then include as many partial patterns as you like and cover all remaining cases using _ (wildcard pattern):

match node with 
| Result(p) ->
    Seq.singleton p
| nd ->
    Seq.collect (fun (n) -> extract n) nd.ChildNodes

Other than this, I'm not sure - the structure in your example looks quite regular, so you don't need to handle cases as in HTML (where <a> can be nested in various other elements). It seems you can just represent the main part of XML as a list of accounts (and parse all account properties using active patterns).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文