F#XML类型提供程序公共元素

时间:2014-07-02 06:25:38

标签: xml f# xsd type-providers f#-data

XML文件的XSD规范可以共享共同的元素。如果我有几个共享一个公共元素的XML文件,有没有办法提取公共元素而不重复每个XML文件类型的代码?

例如:有许多XML文件通过XSD定义,具有共同的描述元素,但在其他地方有不同的内容结构。描述有子元素,如作者,日期等。当我为每个XML文件创建一个类型提供者时,类型是不同的,所以如果我只想从每个文件中提取描述部分,代码必须是复制粘贴每种类型。

XML文件1:

<root>
  <description >
     <author> Me </author>     
  </description>
  <element > Data </element>
  <otherelement> Data </otherelement>
</root>

XML文件2:

<root2>
  <description >
     <author> Me </author>     
  </description>
  <elem > Data </elem>
  <diffelem> Data </diffelem >
</root2>

需要代码类似于:

type File1 = XmlProvider<""".\file1.xml""">
type File2 = XmlProvider<""".\file2.xml""">

let descript1 = 
    File1.GetSample().description.author   
let descript2 = 
    File2.GetSample().description.author    //duplicated code

在这种情况下很简单,但更多地涉及更长的描述和更多的xml文件类型。

有解决方法吗?是否可以为XML文件的子集创建类型提供程序,并仅提取这些部分,以便代码可以更加可重用?

1 个答案:

答案 0 :(得分:4)

当您的输入相当规律时,XML类型提供程序的效果最佳。因此,如果您需要处理多个不同的模式,最好使用标准的XML工具(如XDocument)。

也就是说,你可以使用一些技巧让你的场景变得更好。首先,您可以指定样本的列表。为此,只需创建一个包含一些(任何)根和两个样本的XML文件:

<?xml version="1.0" encoding="utf-8"?>
<samples>
  <root>
    <description><author> Me </author></description>
    <element > Data </element>
    <otherelement> Data </otherelement>
  </root>
  <root2>
    <description ><author> Me </author></description>
    <elem > Data </elem>
    <diffelem> Data </diffelem >
  </root2>
</samples>

现在您可以创建XML类型提供程序并告诉它您的示例文件是一个列表(SampleIsList=true)并且它应该使用全局解析(意味着名为description的所有元素都将被视为值相同类型):

type X = XmlProvider<"C:/temp/sample1.xml", SampleIsList=true, Global=true>

现在,你有不同的命名根,这使得情况更加棘手,但你现在可以编写从一个或另一个根获取<description>元素的代码:

let i = X.Load("...")

let description = 
  match i.Root, i.Root2 with
  | Some r1, _ -> r1.Description
  | _, Some r2 -> r2.Description
  | _ -> failwith "Missing"

这为您提供了一个带有author子节点的描述节点,您可以为两个文档获取该节点:

description.Author