Skip to content

Commit

Permalink
Merge pull request #23 from JuliaComputing/jd/dev
Browse files Browse the repository at this point in the history
update benchmarks and add h function
  • Loading branch information
joshday authored Dec 16, 2023
2 parents f7998c5 + 19d3c34 commit 11a6a55
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "XML"
uuid = "72c71f33-b9b6-44de-8c94-c961784809e2"
authors = ["Josh Day <[email protected]> and contributors"]
version = "0.3.2"
version = "0.3.3"

[deps]
Mmap = "a63ad114-7e13-5084-954f-fe012c677804"
Expand Down
53 changes: 36 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ doc[end][2] # Second child of root
## `Node`: Probably What You're Looking For

- `read`-ing a `Node` loads the entire XML DOM in memory.
- **This is what you would use to build an XML document programmatically.**
- See the table above for convenience constructors.
- `Node`s have some additional methods that aid in construction/mutation:

Expand Down Expand Up @@ -114,6 +113,24 @@ simplevalue(node2)
# "changed"
```

### Writing `Element` `Node`s with `XML.h`

Similar to [Cobweb.jl](https://github.com/JuliaComputing/Cobweb.jl#-creating-nodes-with-cobwebh), `XML.h` enables you to write elements with a simpler syntax:

```julia
using XML: h

julia> node = h.parent(
h.child("content", id="my id")
)
# Node Element <parent> (1 child)

julia> XML.write(node)
# <parent>
# <child id=\"my id\">content</child>
# </parent>
```

<br>

## `XML.LazyNode`: For Fast Iteration through an XML File
Expand Down Expand Up @@ -173,45 +190,47 @@ XML.write(node) # String

```
julia> versioninfo()
Julia Version 1.8.5
Commit 17cfb8e65ea (2023-01-08 06:45 UTC)
Julia Version 1.9.4
Commit 8e5136fa297 (2023-11-14 08:46 UTC)
Build Info:
Official https://julialang.org/ release
Platform Info:
OS: macOS (arm64-apple-darwin21.5.0)
OS: macOS (arm64-apple-darwin22.4.0)
CPU: 10 × Apple M1 Pro
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-13.0.1 (ORCJIT, apple-m1)
Threads: 1 on 8 virtual cores
LLVM: libLLVM-14.0.6 (ORCJIT, apple-m1)
Threads: 8 on 8 virtual cores
```


### Reading an XML File

```
XML.LazyNode 0.012084
XML.Node ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 888.367
EzXML.readxml ■■■■■■ 200.009
XMLDict.xml_dict ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1350.63
XML.LazyNode 0.009583
XML.Node ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1071.32
EzXML.readxml ■■■■■■■■■ 284.346
XMLDict.xml_dict ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1231.47
```

### Writing an XML File

```
Write: XML ■■■■■■■■■■■■■■■■■■■■■■ 244.261
Write: EzXML ■■■■■■■■■■ 106.953
Write: XML ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 289.638
Write: EzXML ■■■■■■■■■■■■■ 93.4631
```

### Lazily Iterating over Each Node
```
LazyNode ■■■■■■■■■■■■■■■■ 55.1
EzXML.StreamReader ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 142.515
LazyNode ■■■■■■■■■ 51.752
EzXML.StreamReader ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 226.271
```

### Collecting All Names/Tags in an XML File
```
XML.LazyNode ■■■■■■■■■■■■■■■■■■■■■■■■■■ 152.298
EzXML.StreamReader ■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 165.21
EzXML.readxml ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 239.197
XML.LazyNode ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 210.482
EzXML.StreamReader ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 276.238
EzXML.readxml ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 263.269
```

<br>
Expand Down
1 change: 1 addition & 0 deletions benchmarks/Project.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
EzXML = "8f5d6c58-4d21-5cfd-889c-e3ad7ee6a615"
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"
Expand Down
14 changes: 13 additions & 1 deletion src/XML.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,16 @@ struct Node <: AbstractXMLNode
end
end

Node(o::Node; kw...) = isempty(kw) ? o : Node((get(kw, x, getfield(o, x)) for x in fieldnames(Node))...)
function Node(o::Node, x...; kw...)
attrs = !isnothing(kw) ?
merge(
OrderedDict(string(k) => string(v) for (k,v) in pairs(kw)),
isnothing(o.attributes) ? OrderedDict{String, String}() : o.attributes
) :
o.attributes
children = isempty(x) ? o.children : vcat(isnothing(o.children) ? [] : o.children, collect(x))
Node(o.nodetype, o.tag, attrs, o.value, children)
end

function Node(node::LazyNode)
nodetype = node.nodetype
Expand All @@ -162,6 +171,9 @@ Node(data::Raw) = Node(LazyNode(data))
# Anything that's not Vector{UInt8} or a (Lazy)Node is converted to a Text Node
Node(x) = Node(Text, nothing, nothing, string(x), nothing)

h(tag::Union{Symbol, String}, children...; kw...) = Node(Element, tag, kw, nothing, children)
Base.getproperty(::typeof(h), tag::Symbol) = h(tag)
(o::Node)(children...; kw...) = Node(o, Node.(children)...; kw...)

# NOT in-place for Text Nodes
function escape!(o::Node, warn::Bool=true)
Expand Down
9 changes: 8 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using XML
using XML: Document, Element, Declaration, Comment, CData, DTD, ProcessingInstruction, Text, escape, unescape, OrderedDict
using XML: Document, Element, Declaration, Comment, CData, DTD, ProcessingInstruction, Text, escape, unescape, OrderedDict, h
using Downloads: download
using Test
import AbstractTrees
Expand All @@ -15,6 +15,13 @@ simple_dtd = joinpath("data", "simple_dtd.xml")

all_files = [xml_xsd, kml_xsd, books_xml, example_kml, simple_dtd]

#-----------------------------------------------------------------------------# h
@testset "h function" begin
@test h.tag == XML.Element("tag")
@test h.tag(id="id") == XML.Element("tag"; id="id")
@test h.tag(1, 2, a="a", b="b") == XML.Element("tag", 1, 2; a="a", b="b")
end

#-----------------------------------------------------------------------------# escaping/unescaping
@testset "escaping/unescaping" begin
s = "This > string < has & some \" special ' characters"
Expand Down

2 comments on commit 11a6a55

@joshday
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/107135

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.3 -m "<description of version>" 11a6a5592610914f51030b63bfb554ae52e0c8c3
git push origin v0.3.3

Please sign in to comment.