Search code examples
f#type-providersfsharp.data.typeproviders

XML manipulation with F# TypeProvider


Given the following XML structure:

<?xml version="1.0" encoding="utf-8"?>
<Persons>
  <Person>
    <Name>Person 1</Name>
    <Age>30</Age>
  </Person>
  <Person>
    <Name>Person 2</Name>
    <Age>32</Age>
  </Person>
</Persons>

I want to add a Person to the collection and I was hoping that could be accomplished with the Xml TypeProvider API.

My approach is the following:

type PersonXmlProvider = XmlProvider<""".\Persons.xml""">

let personsXml = PersonXmlProvider.GetSample()
personsXml.XElement.Add(new PersonXmlProvider.Person("Person 3", 33))
personsXml.XElement.Save("Persons.xml")

What happens: The person is added to the xml collection and written to the file.

Unexpected: But the encoding is not correct since the XML-Tags are encoded as &lt; and &gt; respectively instead of < and >.

What am I missing?

The documentation says that UTF-8 is the default.

Update

Resulting XML

<?xml version="1.0" encoding="utf-8"?>
<Persons>
  <Person>
    <Name>Person 1</Name>
    <Age>30</Age>
  </Person>
  <Person>
    <Name>Person 2</Name>
    <Age>32</Age>
  </Person>&lt;Person&gt;
  &lt;Name&gt;Person 3&lt;/Name&gt;
  &lt;Age&gt;33&lt;/Age&gt;
&lt;/Person&gt;
</Persons>

Solution

  • The method XElement.Add(content: obj) takes in a content object.

    PersonXmlProvider.Person.ToString serializes the type to XML and this gets added as a text node to your main document.

    Thus when it is serialized, the text node is escaped, and you see XML entities in the output.

    P.S.

    The solution is to use XElement all the way.

    let person = new PersonXmlProvider.Person("Person 3", 33)
    personsXml.XElement.Add(person.XElement)