diff --git a/README.md b/README.md index 9968fdc..f086d16 100644 --- a/README.md +++ b/README.md @@ -99,18 +99,49 @@ node["key"] = value node["key"] ``` -- `Node` is an immutable type. However, you can easily create a copy with one or more field values changed by using the `Node(::Node; kw...)` constructor where `kw` are the fields you want to change. For example: +- `Node` is an immutable type. However, you can easily create a simple copy using `copy(::Node)` or +copy with one or more changes by using the `Node(::Node, atts...; kw...)` constructor where `atts` +are new children to add and `kw` are the node attributes you want to add or change. For example: ```julia -node = XML.Element("tag", XML.Text("child")) +julia> node = XML.Element("tag", XML.Text("child")) +Node Element (1 child) -simple_value(node) -# "child" +julia> simple_value(node) +"child" -node2 = Node(node, children=XML.Text("changed")) +julia> node2 = Node(node, new_att="I'm new") +Node Element (1 child) -simple_value(node2) -# "changed" +julia> node3 = Node(node2, XML.Element("new_child", child_att="I'm new too")) +Node Element (2 children) + +julia> println(XML.write(node)) +child + +julia> println(XML.write(node2)) +child + +julia> println(XML.write(node3)) + + child + + + +julia> node4=copy(node3) +Node Element (2 children) + +julia> println(XML.write(node4)) + + child + + + +julia> node4==node3 +true + +julia> node4===node3 +false ``` ### Writing `Element` `Node`s with `XML.h` diff --git a/src/XML.jl b/src/XML.jl index 9027ade..0c4ed04 100644 --- a/src/XML.jl +++ b/src/XML.jl @@ -171,7 +171,8 @@ 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) +h(tag::Union{Symbol, String}, children...; kw...) = Node(Element, tag, length(kw)==0 ? nothing : kw, nothing, children) +# 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...) @@ -204,7 +205,12 @@ Base.setindex!(o::Node, val, i::Integer) = o.children[i] = Node(val) Base.push!(a::Node, b::Node) = push!(a.children, b) Base.pushfirst!(a::Node, b::Node) = pushfirst!(a.children, b) -Base.setindex!(o::Node, val, key::AbstractString) = (o.attributes[key] = string(val)) +function Base.setindex!(o::Node, val, key::AbstractString) # Need to deal with case that XML.attributes(o) === nothing + o = isnothing(o.attributes) ? XML.Node(o.nodetype, o.tag, OrderedDict{String, String}(), o.value, o.children) : o + o.attributes[key] = string(val) + return o +end +# Base.setindex!(o::Node, val, key::AbstractString) = (o.attributes[key] = string(val)) Base.getindex(o::Node, val::AbstractString) = o.attributes[val] Base.haskey(o::Node, key::AbstractString) = isnothing(o.attributes) ? false : haskey(o.attributes, key) Base.keys(o::Node) = isnothing(o.attributes) ? () : keys(o.attributes) @@ -240,7 +246,8 @@ function (T::NodeType)(args...; attr...) Node(T, nothing, nothing, only(args)) elseif T === Element tag = first(args) - Node(T, tag, attr, nothing, args[2:end]) + Node(T, tag, length(attr)==0 ? nothing : attr, nothing, args[2:end]) +# Node(T, tag, attr, nothing, args[2:end]) else error("Unreachable reached while trying to create a Node via (::NodeType)(args...; kw...).") end @@ -269,6 +276,10 @@ simple_value(o) = is_simple(o) ? value(only(o)) : error("`XML.simple_value` is o Base.@deprecate_binding simplevalue simple_value +#-----------------------------------------------------------------------------# copy node + +Base.copy(o::AbstractXMLNode) = Node(o.nodetype, o.tag, o.attributes, o.value, isnothing(o.children) ? nothing : [Base.copy(x) for x in o.children]) + #-----------------------------------------------------------------------------# nodes_equal function nodes_equal(a, b) out = XML.tag(a) == XML.tag(b) diff --git a/test/runtests.jl b/test/runtests.jl index d41924b..e5f5f45 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -174,6 +174,16 @@ end end end +#-----------------------------------------------------------------------------# copy +@testset "Copy node" begin + for path in all_files + node = read(path, Node) + node2 = copy(node) + @test node == node2 + @test node2==deepcopy(node) + end +end + #-----------------------------------------------------------------------------# roundtrip @testset "read/write/read roundtrip" begin for path in all_files