Robur_131
Robur_131

Reputation: 694

Parsing XML file with FSharp XMLProvider

I have an XML file sample.xml that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
            http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">

    <changeSet author="x" id="y">
        <sqlFile
            endDelimiter="\nGO"
            path="ChangeSetScripts/1.sql"
            relativeToChangelogFile="true"
            splitStatements="true"
            stripComments="false"/>
        <rollback>
            <sqlFile path="ChangeSetScripts/1_rollback.sql" />
        </rollback>
    </changeSet>

    <changeSet author="a" id="b">
        <sqlFile
            endDelimiter="\nGO"
            path="ChangeSetScripts/2.sql"
            relativeToChangelogFile="true"
            splitStatements="true"
            stripComments="false"/>
    </changeSet>

    <changeSet author="p" id="q">
        <sqlFile
            endDelimiter="\nGO"
            path="ChangeSetScripts/3.sql"
            relativeToChangelogFile="true"
            splitStatements="true"
            stripComments="false"/>
        <rollback>
            <sqlFile path="ChangeSetScripts/5_rollback.sql" />
        </rollback>
    </changeSet>
    
    ...

</databaseChangeLog>

I want to add a new changeSet entry to this file using F# XMLProvider. There may or may not be a rollback file as apparent from the sample. How can I do this? (id, author and path will be passed as argument)

Upvotes: 1

Views: 284

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243106

The first question is whether you want to mutate the existing document or create a new one. The types generated by the XML provider are immutable, so it works better if you create a new document, however the underlying XElement objects can be mutated so you could potentially do that too.

To create a new modified document, you would just use the provided types to construct a new DatabaseChangeLog value with new ChangeSet list:

type Log = XmlProvider<"c:/temp/sample.xml">
let doc = Log.Load("c:/temp/sample.xml")

// Create a new changeset and specify all required values
let changeSet =
  Log.ChangeSet("New Author", "new_id", 
    Log.SqlFile("/", "c:/path", false, false, false), None)

// Create a new file with the new changeset
let changeSets = Array.append doc.ChangeSets [| changeSet |]  
let newFile = Log.DatabaseChangeLog(doc.SchemaLocation, doc.ChangeSets)

// To get the new XML document as a string before saving it
newFile.ToString()

EDIT: If you wanted to add the new changeSet to the existing document, the way to do this would be to do something like this:

doc.XElement.Add(changeSet.XElement)
doc.XElement.Save("sample.xml")

Upvotes: 2

Related Questions