# Generating types using a macro from XML schema

**URL:** https://discourse.julialang.org/t/generating-types-using-a-macro-from-xml-schema/107161
**Category:** General Usage
**Tags:** question, macros
**Created:** [December 5, 2023, 12:04pm UTC](https://discourse.julialang.org/t/generating-types-using-a-macro-from-xml-schema/107161 "2023-12-05T12:04:09Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![BambOoxX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bambooxx/32/22179_2.png) [@BambOoxX](https://discourse.julialang.org/u/BambOoxX)
#### Post date: [December 5, 2023, 12:04pm UTC](https://discourse.julialang.org/t/generating-types-using-a-macro-from-xml-schema/107161/1 "2023-12-05T12:04:09Z")

</div>

Hi all, I’ve been scratching my head on this all morning, and I can’t figure what’s missing… I’m trying to define types based on the contents of an xml file and its schema. This is not unlike [Trouble understanding macros: creating a struct on the fly - #6 by JonathanAnderson](https://discourse.julialang.org/t/trouble-understanding-macros-creating-a-struct-on-the-fly/4576/6) but I did not manage to make it work anyway.

I figured that, in order to create one type per XML element, I could loop over the contents of the XML file to generate all the types using a macro.

As an example, I created a small XML string and parsed it with `EzXML`. I’m trying to use the “Name” property as a type name and the rest of the attributes as properties.

```julia
fruitsxml = parsexml("""
<Fruits>
  <Fruit Name = "Apple" Description = "Apples are indeed fruits"/>
  <Fruit Name = "Tomato" Description = "Yes tomatoes are fruits !"/>
</Fruits>
""")

```

Now to the macro. I need to retrieve the value of the “Name” property of my XML element so I need to escape it first then interpolate it, then get the property. Same thing for the description.  
However when I try to use the associated expression in a subsequent `quote` block, I get a `ERROR: syntax: invalid type signature`. So I assume some expression is not properly expanded or else there.

```julia
macro generate_fruit(fruit)
    fruit_name = :($(esc(fruit))["Name"])
    fruit_description = :($(esc(fruit))["Description"])
    ex = quote
        struct $fruit_name
            description::String
            function $fruit_name()
                return new($fruit_description)
            end
        end
    end
    return esc(ex)
end

firstfruit = firstelement(root(fruitsxml))

@macroexpand @generate_fruit(firstfruit)

```

The macro expansion gives

```julia
quote
    struct ($(Expr(:escape, :firstfruit)))["Name"]
        description::String
        function (($(Expr(:escape, :firstfruit)))["Name"])()
            return new(($(Expr(:escape, :firstfruit)))["Description"])
        end
    end
end

```

while I would like the actual values instead of the expressions, is there some `eval` magic to add there ?

While testing other syntaxes I tried

```julia
macro generate_fruit_quote(fruit)
    quote
        fruit_name = $(esc(fruit))["Name"]
        fruit_description = $(esc(fruit))["Description"]
        ex = quote
            struct $fruit_name
                description::String
                function $fruit_name()
                    return new($fruit_description)
                end
            end
        end
        return esc(ex)
    end
end

```

For which `@macroexpand` gave

```julia
:($(Expr(:escape, quote
    struct "Apple"
        description::String
        function ("Apple")()
            return new("Apples are indeed fruits")
        end
    end
end)))

```

Which shows that the underlying variables are almost properly expanded inside the `struct` definition, but not the expression itself which is quoted.  
Could someone explain the proper way to do this ?

**EDIT n°1** i was missing a `Symbol` in `fruit_name` to get a proper type name

**EDIT n°2** I think I’ve got it now. If I understand correctly, I just missed an `eval` in my initial implementation instead of the `esc`… I someone could clarify that would be perfect though.

To make it cleaner, I put everything inside a `module` which leads to

```julia
module MyFruits

using EzXML

fruitsxml = parsexml("""
<Fruits>
  <Fruit Name = "Apple" Description = "Apples are indeed fruits"/>
  <Fruit Name = "Tomato" Description = "Yes tomatoes are fruits !"/>
</Fruits>
""")

macro generate_fruit(fruit)
    fruit_name_type = eval(:(Symbol($(fruit)["Name"])))
    fruit_description = :($(fruit)["Description"])
    ex = quote
        struct $fruit_name_type
            description::String
            function $fruit_name_type()
                return new($fruit_description)
            end
        end
    end
    return ex
end

for efruit in eachelement(root(fruitsxml))
    @eval @generate_fruit $efruit
end

end

```

Upon evaluation this gives me a `Main.MyFruits` module with an `Apple` and a `Tomato` types
