Ваш подход к использованию активных шаблонов для сопоставления различных типов узлов мне подходит. Я бы, вероятно, использовал частичные шаблоны (которые могут возвращать Some
, когда они совпадают, или None
) вместо полных шаблонов (которые всегда возвращают один из случаев). Это позволяет вам написать несколько шаблонов для разных типов узлов, с которыми вы работаете.
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 (где <a>
может быть вложено в другие элементы). Кажется, вы можете просто представить основную часть XML в виде списка учетных записей (и проанализировать все свойства учетных записей, используя активные шаблоны).