Общие элементы поставщика типов F# XML
Спецификации XSD для файлов XML могут иметь общие элементы. Если у меня есть несколько файлов 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 ответ
Поставщик типов 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