Xml in PureScript

Our program demonstrates XML handling in PureScript. Here’s the full source code:

module Main where

import Prelude

import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Console (log)
import Data.Array ((:))
import Data.Either (Either(..))
import Data.Generic.Rep (class Generic)
import Data.Show.Generic (genericShow)
import Text.Parsing.Parser (Parser, runParser)
import Text.Parsing.Parser.String (string)
import Text.Parsing.Parser.Combinators (many)
import Text.Parsing.Parser.Token (stringLiteral)

-- Plant will be mapped to XML. We'll use a record to represent the structure.
newtype Plant = Plant
  { id :: Int
  , name :: String
  , origin :: Array String
  }

derive instance genericPlant :: Generic Plant _
instance showPlant :: Show Plant where
  show = genericShow

-- Helper function to create a Plant
mkPlant :: Int -> String -> Array String -> Plant
mkPlant id name origin = Plant { id, name, origin }

-- Simple XML parser (for demonstration purposes)
parseXML :: Parser String Plant
parseXML = do
  _ <- string "<plant id=\""
  id <- parseInt
  _ <- string "\">"
  _ <- string "<name>"
  name <- stringLiteral
  _ <- string "</name>"
  origins <- many parseOrigin
  _ <- string "</plant>"
  pure $ mkPlant id name origins
  where
    parseOrigin = do
      _ <- string "<origin>"
      origin <- stringLiteral
      _ <- string "</origin>"
      pure origin

    parseInt :: Parser String Int
    parseInt = do
      digits <- many $ string "0" <|> string "1" <|> string "2" <|> string "3" <|> string "4" 
                   <|> string "5" <|> string "6" <|> string "7" <|> string "8" <|> string "9"
      pure $ read $ fold digits

-- Simple XML generation (for demonstration purposes)
generateXML :: Plant -> String
generateXML (Plant { id, name, origin }) =
  "<plant id=\"" <> show id <> "\">" <>
  "<name>" <> name <> "</name>" <>
  foldMap (\o -> "<origin>" <> o <> "</origin>") origin <>
  "</plant>"

main :: Effect Unit
main = do
  let coffee = mkPlant 27 "Coffee" ["Ethiopia", "Brazil"]
  
  -- Generate XML
  let coffeeXML = generateXML coffee
  log "Generated XML:"
  log coffeeXML
  
  -- Parse XML
  case runParser coffeeXML parseXML of
    Right parsedPlant -> do
      log "Parsed Plant:"
      log $ show parsedPlant
    Left err ->
      log $ "Failed to parse XML: " <> show err

  -- Nested structure
  let tomato = mkPlant 81 "Tomato" ["Mexico", "California"]
  let nesting = 
        "<nesting>" <>
          "<parent>" <>
            "<child>" <>
              generateXML coffee <>
              generateXML tomato <>
            "</child>" <>
          "</parent>" <>
        "</nesting>"
  
  log "Nested XML:"
  log nesting

To run the program, you would typically use the PureScript compiler (psc) to compile the code and then execute it with Node.js. Here’s a simplified process:

$ pulp build
$ node output/Main/index.js
Generated XML:
<plant id="27"><name>Coffee</name><origin>Ethiopia</origin><origin>Brazil</origin></plant>
Parsed Plant:
(Plant { id: 27, name: "Coffee", origin: ["Ethiopia","Brazil"] })
Nested XML:
<nesting><parent><child><plant id="27"><name>Coffee</name><origin>Ethiopia</origin><origin>Brazil</origin></plant><plant id="81"><name>Tomato</name><origin>Mexico</origin><origin>California</origin></plant></child></parent></nesting>

This PureScript example demonstrates basic XML generation and parsing. It uses a simple string-based approach for XML generation and a basic parser for XML parsing. In a real-world application, you would likely use more robust libraries for XML handling.

PureScript doesn’t have built-in XML support like Go’s encoding/xml package, so we’ve implemented basic functionality to demonstrate the concepts. The Plant type is defined as a record, similar to Go’s struct. We’ve created functions to generate XML strings and parse them back into Plant values.

The example shows how to create XML representations of data, parse XML back into data structures, and work with nested XML structures. While the implementation details differ from Go, the core concepts of working with XML remain similar.