【问题标题】:F# using XML Type Provider to modify xmlF#使用XML Type Provider修改xml
【发布时间】:2017-01-02 23:56:55
【问题描述】:

我需要处理一堆 XML 文档。它们的结构非常复杂(即节点负载),但处理包括更改一些节点的值并以不同的名称保存文件。

我正在寻找一种方法来做到这一点,而不必通过显式实例化所有类型并传入所有未更改的值来重建输出 XML,而只需从输入中复制它们。如果类型提供程序自动生成的类型是记录类型,我可以简单地通过let output = { input with changedNode = myNewValue } 创建输出,但使用类型提供程序我必须使用let output = MyXml.MyRoot(input.UnchangedNode1, input.UnchangedNode2, myNewValue, input.UnchangedNode3, ...)。由于我更改的值位于某些嵌套节点中,这使情况变得更加复杂,因此我有很多绒毛要传递给它。

【问题讨论】:

  • 我可以建议使用 Xml 类型提供程序并改用一些 XSLT 吗?更多信息可能会有所启发。对我来说,这听起来像是某种条件搜索和替换,但它当然可能只是我。
  • 镜头!你想要镜头!
  • @MarkSeemann 是和不是。但大多是的。更没有。所以也许。或 ... ;-) 在这种情况下,这实际上是一件“好事”(如果类型提供者允许这样做,正如 Tomas '欺骗'解释的那样)。直到“编写这个新的 XML”,哪些类型提供者仍然不擅长......
  • @HelgeReneUrholm,很可能 XSLT 是解决这个问题的有效方式,但是: - 在(过去)在一个逻辑应用程序引擎上工作之后,我对 XSLT 有过可怕的经历在 XSLT 转换中指定 - 它不可调试(没有 Xml Spy 等) - 我更愿意用代码编写转换,我发现它更清晰 - 函数式编程似乎是以下场景的理想工具:获取输入 -> 处理它 -> 输出
  • 从这个意义上说,@MarkSeemann 是在正确的轨道上并回答了我未提出的问题,提供了一个函数式编程习惯的建议

标签: f# f#-data fsharp.data.typeproviders


【解决方案1】:

F# 数据类型提供程序的主要设计目的是在读取数据时提供轻松访问,因此它们没有很好的数据写入故事(部分原因是底层 JSON 表示与底层 XML 表示完全不同) )。

对于 XML,类型提供者只是包装了标准的 XElement 类型,它们恰好是可变的。这意味着您实际上可以使用提供的类型导航到元素,然后使用底层 LINQ to XML 来改变值。例如:

type X = XmlProvider<"<foos><foo a=\"1\" /><foo a=\"2\" /></foos>">

// Change the 'a' attribute of all 'foo' nodes to 1234
let doc = X.GetSample()
for f in doc.Foos do
  f.XElement.SetAttributeValue(XName.Get "a", 1234)

// Prints the modified document    
doc.ToString()

这可能并不完美 - 有时,您需要更改父元素(就像这里,提供的 f.A 属性是不可变的),但它可能会成功。我不知道这是否是解决问题的最佳方式,或者像 XSLT 这样的东西是否更容易——这可能取决于具体的转换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 2013-08-31
    相关资源
    最近更新 更多