XSD specifications for XML files can share common elements. If I have several XML files that share a common element, is there a way to extract the common element without repeating the code for each XML file type?
For example: There are a number of XML files defined via XSD, with a common description element, but different content structures elsewhere. The description has subelements with things like author, date, etc. When I create a type provider for each of the XML files, the types are different, so if I only want to extract the description section out of each, the code has to be copy pasted for each of the types.
XML file 1:
<root>
<description >
<author> Me </author>
</description>
<element > Data </element>
<otherelement> Data </otherelement>
</root>
XML file 2:
<root2>
<description >
<author> Me </author>
</description>
<elem > Data </elem>
<diffelem> Data </diffelem >
</root2>
Would require the code to be something like:
type File1 = XmlProvider<""".\file1.xml""">
type File2 = XmlProvider<""".\file2.xml""">
let descript1 =
File1.GetSample().description.author
let descript2 =
File2.GetSample().description.author //duplicated code
Simple in this case, but gets more involved with a longer description and more xml file types.
Is there a way around this? Can a type provider be created for a subset of an XML file and only extract those parts so the code can be more reusable?
The XML type provider works the best in the case when your inputs are fairly regular. So, if you need to process multiple different schemas, it might be better to use the standard XML tools (like XDocument
).
That said, you can use a few tricks that make your scenario nicer. First, you can specify a list of samples. To do that, just create a XML file that has some (any) root and both of your samples:
<?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>
Now you can create XML type provider and tell it that your sample file is a list (SampleIsList=true
) and that it should use global resolution (meaning that all elements named description
will be treated as values of the same type):
type X = XmlProvider<"C:/temp/sample1.xml", SampleIsList=true, Global=true>
Now, you have differently named roots, which makes the situation trickier, but you can now write code that gets the <description>
element from one or the other root:
let i = X.Load("...")
let description =
match i.Root, i.Root2 with
| Some r1, _ -> r1.Description
| _, Some r2 -> r2.Description
| _ -> failwith "Missing"
This gives you a description node with author
sub node that you can get for both of your documents:
description.Author
来源:https://stackoverflow.com/questions/24524247/f-xml-type-provider-common-elements