Skip to content

Commit bb0437c

Browse files
committed
organize tests, some other fixes
1 parent fc5b3f6 commit bb0437c

File tree

10 files changed

+2032
-60
lines changed

10 files changed

+2032
-60
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,20 @@ node["key"] = value
100100
node["key"]
101101
```
102102

103+
- `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:
104+
105+
```julia
106+
node = XML.Element("tag", XML.Text("child"))
107+
108+
simplevalue(node)
109+
# "child"
110+
111+
node2 = Node(node, children=XML.Text("changed"))
112+
113+
simplevalue(node2)
114+
# "changed"
115+
```
116+
103117
<br>
104118

105119
## `XML.LazyNode`: For Fast Iteration through an XML File

src/XML.jl

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -138,24 +138,29 @@ struct Node <: AbstractXMLNode
138138
isnothing(attributes) ? nothing : Dict(string(k) => string(v) for (k, v) in pairs(attributes)),
139139
isnothing(value) ? nothing : string(value),
140140
isnothing(children) ? nothing :
141+
children isa Node ? [children] :
141142
children isa Vector{Node} ? children :
142143
children isa Vector ? map(Node, children) :
143-
map(Node, collect(children))
144+
children isa Tuple ? map(Node, collect(children)) :
145+
[Node(children)]
144146
)
145147
end
146148
end
147-
Node(o::Node; kw...) = isempty(kw) ? o : Node((get(kw, x, getfield(o, x)) for x in fieldnames(Node))...)
148-
149-
Node(data::Raw) = Node(LazyNode(data))
150149

151-
Node(x) = Node(Text, nothing, nothing, string(x), nothing)
150+
Node(o::Node; kw...) = isempty(kw) ? o : Node((get(kw, x, getfield(o, x)) for x in fieldnames(Node))...)
152151

153152
function Node(node::LazyNode)
154153
(;nodetype, tag, attributes, value) = node
155154
c = XML.children(node)
156155
Node(nodetype, tag, attributes, value, isempty(c) ? nothing : map(Node, c))
157156
end
158157

158+
Node(data::Raw) = Node(LazyNode(data))
159+
160+
# Anything that's not Vector{UInt8} or a (Lazy)Node is converted to a Text Node
161+
Node(x) = Node(Text, nothing, nothing, string(x), nothing)
162+
163+
159164
# NOT in-place for Text Nodes
160165
function escape!(o::Node, warn::Bool=true)
161166
if o.nodetype == Text
@@ -184,13 +189,9 @@ Base.parse(x::AbstractString, ::Type{Node}) = Node(parse(x, Raw))
184189
Base.setindex!(o::Node, val, i::Integer) = o.children[i] = Node(val)
185190
Base.push!(a::Node, b::Node) = push!(a.children, b)
186191

187-
function Base.setindex!(o::Node, val, key::AbstractString)
188-
if isnothing(o.attributes)
189-
o.attributes = Dict{String,String}()
190-
end
191-
o.attributes[key] = string(val)
192-
end
193-
Base.getindex(o::Node, val::AbstractString) = isnothing(o.attributes) ? nothing : get(o.attributes, val, nothing)
192+
Base.setindex!(o::Node, val, key::AbstractString) = (o.attributes[key] = string(val))
193+
Base.getindex(o::Node, val::AbstractString) = o.attributes[val]
194+
Base.haskey(o::Node, key::AbstractString) = isnothing(o.attributes) ? false : haskey(o.attributes, key)
194195

195196
Base.show(io::IO, o::Node) = _show_node(io, o)
196197

@@ -367,7 +368,7 @@ function write(io::IO, x; indentsize::Int=2, depth::Union{Missing,Int}=depth(x))
367368
end
368369
end
369370
elseif nodetype === DTD
370-
print(io, "<!DOCTYPE", value, '>')
371+
print(io, "<!DOCTYPE ", value, '>')
371372
elseif nodetype === Declaration
372373
print(io, "<?xml")
373374
_print_attrs(io, x)

src/dtd.jl

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# This is all a work in progress
2+
13
#-----------------------------------------------------------------------------# position_after
24
function position_after(needle::Vector{UInt8}, haystack::Vector{UInt8}, i)
35
x = findnext(needle, haystack, i)
@@ -7,8 +9,6 @@ end
79
position_after(needle::String, haystack::Vector{UInt8}, i) = position_after(Vector{UInt8}(needle), haystack, i)
810

911

10-
11-
1212
#-----------------------------------------------------------------------------# DeclaredElement
1313
struct DeclaredElement
1414
name::String
@@ -102,14 +102,13 @@ end
102102

103103
#-----------------------------------------------------------------------------# DTDBody
104104
struct DTDBody
105-
root::String
106105
elements::Vector{DeclaredElement}
107106
attributes::Vector{DeclaredAttribute}
108107
entities::Vector{DeclaredEntity}
109108
end
110109

111110
function Base.show(io::IO, o::DTDBody)
112-
printstyled(io, "DTDBody(root=\"", o.root, "\")\n", color=:light_cyan)
111+
printstyled(io, "DTDBody\n", color=:light_cyan)
113112
printstyled(io, " DeclaredElements (", length(o.elements), ")\n", color=:light_green)
114113
foreach(x -> println(io, " ", x), o.elements)
115114
printstyled(io, " DeclaredAttributes (", length(o.attributes), ")\n", color=:light_green)
@@ -119,22 +118,24 @@ function Base.show(io::IO, o::DTDBody)
119118
end
120119

121120

122-
123-
function DTDBody(data::Vector{UInt8})
121+
function DTDBody(data::Vector{UInt8}, file = false)
122+
file && @goto isfile
124123
i = position_after("<!DOCTYPE", data, 1)
125124
root, i = get_name(data, i)
126125

127126
i = findnext(==(UInt8('[')), data, i)
128127
isnothing(i) && return DTDBody(root, [], [], [])
129128

129+
@label isfile
130130
elements = get_declared_elements(data)
131131
attributes = get_declared_attributes(data)
132132
entities = get_declared_entities(data)
133133
return DTDBody(root, elements, attributes, entities)
134134
end
135135

136136

137-
Base.read(filename::String, ::Type{DTDBody}) = DTDBody(read(filename))
138-
Base.read(io::IO, ::Type{DTDBody}) = Raw(read(io))
137+
Base.read(filename::String, ::Type{DTDBody}) = DTDBody(read(filename), true)
138+
Base.read(io::IO, ::Type{DTDBody}) = DTDBody(read(io), true)
139+
139140
Base.parse(s::AbstractString, ::Type{DTDBody}) = DTDBody(Vector{UInt8}(s))
140141
Base.parse(::Type{DTDBody}, s::AbstractString) = parse(s, DTDBody)
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)