Xml in Racket

Our first program will demonstrate XML processing in Racket. Here’s the full source code:

#lang racket

(require xml)

; Define a structure to represent a plant
(struct plant (id name origin) #:transparent)

; Function to convert a plant to a string
(define (plant->string p)
  (format "Plant id=~a, name=~a, origin=~a"
          (plant-id p)
          (plant-name p)
          (plant-origin p)))

; Main function
(define (main)
  ; Create a coffee plant
  (define coffee (plant 27 "Coffee" '("Ethiopia" "Brazil")))
  
  ; Convert the plant to XML
  (define xml-coffee
    (xexpr->xml
     `(plant ([id ,(number->string (plant-id coffee))])
             (name ,(plant-name coffee))
             ,@(map (λ (o) `(origin ,o)) (plant-origin coffee)))))
  
  ; Print the XML
  (display (xml->string xml-coffee))
  (newline)
  
  ; Print with XML declaration
  (printf "~a~a~n" (xml-declaration) (xml->string xml-coffee))
  
  ; Parse XML back to a plant structure
  (define parsed-plant
    (let* ([xml-in (xml->xexpr xml-coffee)]
           [id (string->number (cadr (assq 'id (cadr xml-in))))]
           [name (caddr (assq 'name (cddr xml-in)))]
           [origin (map caddr (filter (λ (x) (eq? (car x) 'origin)) (cddr xml-in)))])
      (plant id name origin)))
  
  ; Print the parsed plant
  (printf "~a~n" (plant->string parsed-plant))
  
  ; Create a tomato plant
  (define tomato (plant 81 "Tomato" '("Mexico" "California")))
  
  ; Create a nested structure
  (define nested
    `(nesting
      (parent
       (child
        ,(xexpr->xml
          `(plant ([id ,(number->string (plant-id coffee))])
                  (name ,(plant-name coffee))
                  ,@(map (λ (o) `(origin ,o)) (plant-origin coffee))))
        ,(xexpr->xml
          `(plant ([id ,(number->string (plant-id tomato))])
                  (name ,(plant-name tomato))
                  ,@(map (λ (o) `(origin ,o)) (plant-origin tomato))))))))
  
  ; Print the nested XML
  (display (xml->string (xexpr->xml nested)))
  (newline))

(main)

This program demonstrates XML processing in Racket, including creating XML from data structures, parsing XML, and working with nested XML structures.

To run the program, save it as xml-example.rkt and use the Racket interpreter:

$ racket xml-example.rkt
<plant id="27"><name>Coffee</name><origin>Ethiopia</origin><origin>Brazil</origin></plant>
<?xml version="1.0" encoding="UTF-8"?>
<plant id="27"><name>Coffee</name><origin>Ethiopia</origin><origin>Brazil</origin></plant>
Plant id=27, name=Coffee, origin=(Ethiopia Brazil)
<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 example showcases how to work with XML in Racket, including:

  1. Defining structures to represent data (the plant struct).
  2. Converting data structures to XML using xexpr->xml.
  3. Printing XML as a string with xml->string.
  4. Adding an XML declaration.
  5. Parsing XML back into data structures.
  6. Creating nested XML structures.

Racket’s XML library provides a flexible way to work with XML data, allowing for easy conversion between Racket data structures and XML representations.