Skip to content

How can I deserialize a <xs:choice> XML element into an OCaml variant type? #37

@ahelwer

Description

@ahelwer

This is a question, not an issue. I am trying to use this library to parse an XML format I do not have control over. Suppose it has an XSD as follows:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="modules">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="RootModule" type="xs:string"/>
        <xs:sequence maxOccurs="unbounded">
          <xs:choice>
            <xs:element ref="ModuleNode"/>
            <xs:element ref="ModuleNodeRef"/>
          </xs:choice>
        </xs:sequence>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Here is an example XML input:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<modules>
  <RootModule>Test</RootModule>
  <ModuleNodeRef>
    <UID>304</UID>
  </ModuleNodeRef>
  <ModuleNode>
    <uniquename>Test</uniquename>
  </ModuleNode>
</modules>

I would like to deserialize this into something similar to the following, where the ModuleNodeRef and ModuleNode instances are a list of variant types:

open Protocol_conv_xml

type module_node = {
  uniquename : string
} [@@deriving protocol ~driver:(module Xml_light)]

type module_node_ref = {
  uid : int [@key "UID"]
} [@@deriving protocol ~driver:(module Xml_light)]

type module_node_or_ref =
  | ModuleNode of module_node [@key "ModuleNode"]
  | ModuleNodeRef of module_node_ref [@key "ModuleNodeRef"]
[@@deriving protocol ~driver:(module Xml_light)]

type modules = {
  root_module: string; [@key "RootModule"]
  modules : module_node_or_ref list;
} [@@deriving protocol ~driver:(module Xml_light)]

let () =
  let xml = Xml.parse_file "Test.xml" in
  match modules_of_xml_light xml with
  | Ok s -> s |> modules_to_xml_light |> Xml.to_string_fmt |> Printf.printf "t serialized: %s\n";
  | Error e -> print_endline (Xml_light.error_to_string_hum e)

However, when I run the program on the example input it just produces:

t serialized: <record>             
  <RootModule>Test</RootModule>
</record>

So the variants are ignored. How can I correctly parse the variants? Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions