# \[ANN\] Announcing XML.jl

**URL:** <https://discourse.julialang.org/t/ann-announcing-xml-jl/99781>\
**Category:** Package Announcements\
**Tags:** xml\
**Created:** [June 2, 2023, 5:15pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781 "2023-06-02T17:15:03Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![joshday](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joshday/32/368_2.png) [@joshday](https://discourse.julialang.org/u/joshday)\
**Post date:** [June 2, 2023, 5:15pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/1 "2023-06-02T17:15:03Z")

</div>

Announcing [a pure Julia XML reader/writer](https://github.com/JuliaComputing/XML.jl).

It powers [KML.jl](https://github.com/JuliaComputing/KML.jl) and I’m finally ready to encourage some more testing from the community.

It’s [speed](https://github.com/JuliaComputing/XML.jl#performance) looks decent compared to EzXML.jl, but please open issues if you hit cases of poor performance.

Enjoy!

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [June 2, 2023, 5:20pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/2 "2023-06-02T17:20:30Z")

</div>

Well I’ve been telling everyone to use it for like six months 😉

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [June 2, 2023, 5:21pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/3 "2023-06-02T17:21:57Z")

</div>

The first link is not working.

---

<div class="post-metadata">

**Author:** ![joshday](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joshday/32/368_2.png) [@joshday](https://discourse.julialang.org/u/joshday)\
**Post date:** [June 2, 2023, 5:22pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/4 "2023-06-02T17:22:40Z")

</div>

Oops, thanks! Fixed.

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [June 2, 2023, 7:32pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/5 "2023-06-02T19:32:02Z")

</div>

This looks great!

I am extremely interested in this. Do you happen to have some more detailed examples and could you kindly elaborate a bit on what benefits this has compared to something like EzXML.jl?

I see the mention of it being written purely in Julia etc., perhaps someone could explain to me the benefit of this?

Kind regards

---

<div class="post-metadata">

**Author:** ![joshday](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joshday/32/368_2.png) [@joshday](https://discourse.julialang.org/u/joshday)\
**Post date:** [June 2, 2023, 10:24pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/6 "2023-06-02T22:24:59Z")

</div>

> [@Ahmed\_Salih](#):
>
> I am extremely interested in this. Do you happen to have some more detailed examples and could you kindly elaborate a bit on what benefits this has compared to something like EzXML.jl?
> 
> I see the mention of it being written purely in Julia etc., perhaps someone could explain to me the benefit of this?

1. I’m greedy. I want Julia to be the best at everything.
2. Packages that are 100% Julia are easier to debug. I’d much rather have `@edit` lead me to pure Julia code than e.g. a `Base.ccall`.
3. In secure computing environments, it can be a burden to move in external dependencies. If Julia is already installed/on your approved software list, you’re all set.

---

<div class="post-metadata">

**Author:** ![quinnj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/quinnj/32/11_2.png) [@quinnj](https://discourse.julialang.org/u/quinnj)\
**Post date:** [June 3, 2023, 4:15am UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/7 "2023-06-03T04:15:16Z")

</div>

Oh man, you beat me to it! This looks great. It’s been on my list for a while to have a native-Julia XML parser. Love the lazy functionality. Can’t wait to take it for a spin.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 3, 2023, 5:51am UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/8 "2023-06-03T05:51:00Z")

</div>

Very cool, it’s great seeing more and more infrastructure packages being added to the Julia ecosystem.

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [June 3, 2023, 8:08am UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/9 "2023-06-03T08:08:43Z")

</div>

Thanks for the package.

I have been using it already in a few occasions, mostly when working with `svg`s and it worked great so far.

However, in some cases I felt like the package could be shipped with a bit more utility:

1. E.g. I found myself often doing things like

```plaintext
   xml = Document()
   path = Element("path")
   push!(xml.root, path)

```

which feels repetitive. I then implemented helpers to overload `:(>>)` so that it could be written as

```julia
   xml = Document()
   path = Element("path") >> xml.root

```

1. Atm setting properties only works with `Symbol`s. However, in `svg` you often have property names that you can’t write as `Symbol`s, e.g.

```julia
path.stroke-width = 1 # doesn't work
path.Symbol("stroke-width") = 1 # doesn't work
setproperty!(path, Symbol("stroke-width"), 1) # works

```

Again, to cut down syntax I type pirated `getproperty/setproperty!` for `AbstractXMLNode` to accept `AbstractStrings` so that I could write instead just

```julia
path."stroke-width" = 1

```

Are there any plans on adding such utilities to `XML.jl`?

PS: Just noted that `XML.jl` is now at `v0.2.1` and the last version I used was `v0.1.3`, so perhaps some of the above functionality was already added?

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [June 3, 2023, 8:29am UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/10 "2023-06-03T08:29:06Z")

</div>

> [@fatteneder](#):
>
> ```julia
> path.Symbol("stroke-width") = 1 # doesn't work
> 
> ```

That’s `path.var"stroke-width" = 1` btw.

---

<div class="post-metadata">

**Author:** ![joshday](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joshday/32/368_2.png) [@joshday](https://discourse.julialang.org/u/joshday)\
**Post date:** [June 3, 2023, 12:56pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/11 "2023-06-03T12:56:29Z")

</div>

This is great feedback, thanks!

To your first point: I do have some ideas on making more convenient syntax, but nothing that I’ve settled on. I liked what I did with building HTML in [Cobweb](https://github.com/JuliaComputing/Cobweb.jl) so I may borrow some things from there.

To your second point, see @aplavin’s response on using `var"stroke-width"`. You can then use `setproperty!` if you’re setting attributes programmatically.

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [June 3, 2023, 1:09pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/12 "2023-06-03T13:09:13Z")

</div>

> [@joshday](#):
>
> To your second point, see @aplavin’s response on using `var"stroke-width"`. You can then use `setproperty!` if you’re setting attributes programmatically.

I still prefer the string overload, but I guess its a matter of taste.

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [June 3, 2023, 1:43pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/13 "2023-06-03T13:43:53Z")

</div>

Thank you for the detailed explanation and making the package.

I hope to be able to use the package for some of my needs and hopefully provide some valuable feedback from a user perspective.

Kind regards

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [June 3, 2023, 3:16pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/14 "2023-06-03T15:16:50Z")

</div>

I’ve also been using it for SVGs! It would be good to put together SVG.jl at some stage.

I have a bunch of messy code for extracting geometries to GeometryBasics.jl types.

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [June 3, 2023, 5:23pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/15 "2023-06-03T17:23:17Z")

</div>

> [@Raf](#):
>
> I’ve also been using it for SVGs! It would be good to put together SVG.jl at some stage.

Sounds fun … but what would it be supposed to do? 😆

I mean a `.svg` file is just a `.xml` file with lots and lots of options for the elements.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [June 3, 2023, 5:44pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/16 "2023-06-03T17:44:26Z")

</div>

If that’s your idea of fun 😜

I found it pretty painful having to learn how svg geometries are stored just to scrape some map polygons from a pdf. Things like finding and applying transformation matrices, how the geometry syntax works…

Like

```julia
function to_geoms(::Type{T}, p) where T
    matrix = get_transform(p)
    geoms = T[]
    parts = split(p.d, " ")
    local line = Point2{Float64}[]
    s = nothing
    while true
        i = isnothing(s) ? iterate(parts) : iterate(parts, s)
        if isnothing(i) # end of iteration 
            if length(line) > 1
                push!(geoms, T(line))
            end
            break
        end
        x, s = i
        if x == "M"
            line = Point2{Float64}[]
            a, s = iterate(parts, s)
            b, s = iterate(parts, s)
            push!(line, parsepoint(matrix, a, b))
        elseif x == "L"
            a, s = iterate(parts, s)
            b, s = iterate(parts, s)
            push!(line, parsepoint(matrix, a, b))
        elseif x == "Z"
            push!(line, first(line))
            if length(line) > 1
                push!(geoms, T(line))
            end
        end
    end
    geoms
end

function parse_matrix(s)
    m = parse.(Float64, split(s[8:end-1], ","))
    [m[1] m[3] m[5];
     m[2] m[4] m[6];
     0.0 0.0 0.1 ;
    ]
end

```

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [June 3, 2023, 5:57pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/17 "2023-06-03T17:57:19Z")

</div>

Oh, I see. Yeah, that’s not so fun.

And for your application you really only care about the geometric aspects of the svg doc, so that you can ignore all the other metadata like color, links etc?

I called it fun, because I only dealt with it in the other way by writing instead of parsing `.svg`s for [GitHub - fatteneder/SVGMakie.jl: SVG backend for Makie](https://github.com/fatteneder/SVGMakie.jl) (its just a proof of concept), and that’s a bit simpler 🙂

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [June 3, 2023, 6:01pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/18 "2023-06-03T18:01:42Z")

</div>

Yeah writing is way simpler! There are a bunch of arcane options you need to cover to actually read them, and I still only covered what was actually in the files I was scraping.

My svgs had a mix of regular polygons and polygons that needed transformation to the projection. I did care about colour as that was the main indicator of what the objects in the maps were. But you could extract all of that data to a FeatureCollection/Tables object that was GeoInterface.jl compatible and it would just work with all the other geometry packages.

And if you have write already from GeometryBasics.jl geoms its very little work to make that just write any Geometries at all, like `GeoInterface.convert(GeometryBasics, geom)` little work. So maybe you could extract that SVG writing code from SVGMakie.jl too?

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [June 3, 2023, 6:27pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/19 "2023-06-03T18:27:54Z")

</div>

> [@Raf](#):
>
> I found it pretty painful having to learn how svg geometries are stored just to scrape some map polygons from a pdf.

Don’t know if applicable but I once extracted a bunch of coordinates from a PDF using PDFIO.jl and GMT.jl. See this forum post.

> **[How to read a list of coordinates?](https://forum.generic-mapping-tools.org/t/how-to-read-a-list-of-coordinates/3609/12?u=joaquim)**
>
> For obvious reasons 🙂 Needs the PDFIO.jl package (to install \] add PDFIO) Put the followin in a .jl file using PDFIO, GMT function squeeze\_aip(file::String="AD 2 EDDF 1-5.pdf") # 'file' is the the (full) name of the PDF to squeeze. If not...

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [June 3, 2023, 6:29pm UTC](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781/20 "2023-06-03T18:29:07Z")

</div>

> There are a bunch of arcane options you need to cover to actually read them

I guess you are refering to things like `href`s etc. I can imagine those being nasty to extract correctly without `XML.jl`.

> But you could extract all of that data to a FeatureCollection/Tables object that was GeoInterface.jl compatible and it would just work with all the other geometry packages.

That sounds like a good plan to dump all the metadata for which you don’t know how to handle it.

> So maybe you could extract that SVG writing code from SVGMakie.jl too?

IIRC all I needed to write `svg`s for Makie were just path and polygon elements and then a ton of color and fill options, because all of Makie’s backends mostly only receive lists of points (there is only one occurrence of `GeometryBasics.Mesh` in all of `SVGMakie.jl` 😆 ). So probably not too much to extract, unfortunately.

[Next page](https://discourse.julialang.org/t/ann-announcing-xml-jl/99781.md?page=2)
