Skip to content

Commit 15582b2

Browse files
committed
Remove dummy nodes from the XML tree.
1 parent 2aee731 commit 15582b2

File tree

4 files changed

+17
-39
lines changed

4 files changed

+17
-39
lines changed

src/XMLNode.coffee

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,13 @@ module.exports = class XMLNode
289289
# Adds a dummy node
290290
dummy: () ->
291291
child = new XMLDummy @
292-
@children.push child
292+
# Normally when a new node is created it is added to the child node collection.
293+
# However, dummy nodes are never added to the XML tree. They are created while
294+
# converting JS objects to XML nodes in order not to break the recursive function
295+
# chain. They can be thought of as invisible nodes. They can be traversed through
296+
# by using prev(), next(), up(), etc. functions but they do not exists in the tree.
297+
#
298+
# @children.push child
293299
return child
294300

295301
# Adds a processing instruction
@@ -435,9 +441,6 @@ module.exports = class XMLNode
435441
prev: () ->
436442
i = @parent.children.indexOf @
437443

438-
# skip dummy nodes
439-
i = i - 1 while i > 0 and @parent.children[i - 1].type is NodeType.Dummy
440-
441444
if i < 1
442445
throw new Error "Already at the first node. " + @debugInfo()
443446

@@ -448,9 +451,6 @@ module.exports = class XMLNode
448451
next: () ->
449452
i = @parent.children.indexOf @
450453

451-
# skip dummy nodes
452-
i = i + 1 while i < @parent.children.length - 1 and @parent.children[i + 1].type is NodeType.Dummy
453-
454454
if i == -1 || i == @parent.children.length - 1
455455
throw new Error "Already at the last node. " + @debugInfo()
456456

@@ -482,26 +482,6 @@ module.exports = class XMLNode
482482
"node: <" + name + ">, parent: <" + @parent.name + ">"
483483

484484

485-
# Count the number of child nodes which are not `XMLDummy`
486-
countNonDummy: () ->
487-
if not @children or @children.length is 0
488-
return 0
489-
else
490-
count = 0
491-
for child in @children
492-
count++ unless child.type is NodeType.Dummy
493-
return count
494-
495-
# Returns the first child node which is not an `XMLDummy`
496-
firstNonDummy: () ->
497-
if not @children or @children.length is 0
498-
return null
499-
else
500-
for child in @children
501-
return child unless child.type is NodeType.Dummy
502-
return null
503-
504-
505485
# Aliases
506486
ele: (name, attributes, text) -> @element name, attributes, text
507487
nod: (name, attributes, text) -> @node name, attributes, text

src/XMLStreamWriter.coffee

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ module.exports = class XMLStreamWriter extends XMLWriterBase
6262
@stream.write ' SYSTEM "' + node.sysID + '"'
6363

6464
# internal subset
65-
if node.countNonDummy() > 0
65+
if node.children.length > 0
6666
@stream.write ' ['
6767
@stream.write @endline(node, options, level)
6868
options.state = WriterState.InsideTag
@@ -90,8 +90,8 @@ module.exports = class XMLStreamWriter extends XMLWriterBase
9090
for own name, att of node.attributes
9191
@attribute att, options, level
9292

93-
childNodeCount = node.countNonDummy()
94-
firstNonDummyChildNode = node.firstNonDummy()
93+
childNodeCount = node.children.length
94+
firstChildNode = if childNodeCount is 0 then null else node.children[0]
9595
if childNodeCount == 0 or node.children.every((e) -> (e.type is NodeType.Text or e.type is NodeType.Raw) and e.value == '')
9696
# empty element
9797
if options.allowEmpty
@@ -101,13 +101,13 @@ module.exports = class XMLStreamWriter extends XMLWriterBase
101101
else
102102
options.state = WriterState.CloseTag
103103
@stream.write options.spaceBeforeSlash + '/>'
104-
else if options.pretty and childNodeCount == 1 and (firstNonDummyChildNode.type is NodeType.Text or firstNonDummyChildNode.type is NodeType.Raw) and firstNonDummyChildNode.value?
104+
else if options.pretty and childNodeCount == 1 and (firstChildNode.type is NodeType.Text or firstChildNode.type is NodeType.Raw) and firstChildNode.value?
105105
# do not indent text-only nodes
106106
@stream.write '>'
107107
options.state = WriterState.InsideTag
108108
options.suppressPrettyCount++
109109
prettySuppressed = true
110-
@writeChildNode firstNonDummyChildNode, options, level + 1
110+
@writeChildNode firstChildNode, options, level + 1
111111
options.suppressPrettyCount--
112112
prettySuppressed = false
113113
options.state = WriterState.CloseTag

src/XMLWriterBase.coffee

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ module.exports = class XMLWriterBase
156156
r += ' SYSTEM "' + node.sysID + '"'
157157

158158
# internal subset
159-
if node.countNonDummy() > 0
159+
if node.children.length > 0
160160
r += ' ['
161161
r += @endline(node, options, level)
162162
options.state = WriterState.InsideTag
@@ -189,8 +189,8 @@ module.exports = class XMLWriterBase
189189
for own name, att of node.attributes
190190
r += @attribute att, options, level
191191

192-
childNodeCount = node.countNonDummy()
193-
firstNonDummyChildNode = node.firstNonDummy()
192+
childNodeCount = node.children.length
193+
firstChildNode = if childNodeCount is 0 then null else node.children[0]
194194
if childNodeCount == 0 or node.children.every((e) -> (e.type is NodeType.Text or e.type is NodeType.Raw) and e.value == '')
195195
# empty element
196196
if options.allowEmpty
@@ -200,13 +200,13 @@ module.exports = class XMLWriterBase
200200
else
201201
options.state = WriterState.CloseTag
202202
r += options.spaceBeforeSlash + '/>' + @endline(node, options, level)
203-
else if options.pretty and childNodeCount == 1 and (firstNonDummyChildNode.type is NodeType.Text or firstNonDummyChildNode.type is NodeType.Raw) and firstNonDummyChildNode.value?
203+
else if options.pretty and childNodeCount == 1 and (firstChildNode.type is NodeType.Text or firstChildNode.type is NodeType.Raw) and firstChildNode.value?
204204
# do not indent text-only nodes
205205
r += '>'
206206
options.state = WriterState.InsideTag
207207
options.suppressPrettyCount++
208208
prettySuppressed = true
209-
r += @writeChildNode firstNonDummyChildNode, options, level + 1
209+
r += @writeChildNode firstChildNode, options, level + 1
210210
options.suppressPrettyCount--
211211
prettySuppressed = false
212212
options.state = WriterState.CloseTag

test/basic/nodetype.coffee

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ suite 'Check node type:', ->
1111

1212
doc = xml(obj, { sysID: 'hello.dtd' }).doc()
1313
root = doc.root()
14-
root.dummy()
1514

1615
eq(doc.type, builder.nodeType.Document)
1716
eq(doc.children[0].type, builder.nodeType.Declaration)
@@ -22,7 +21,6 @@ suite 'Check node type:', ->
2221
eq(root.children[2].type, builder.nodeType.CData)
2322
eq(root.children[3].type, builder.nodeType.Comment)
2423
eq(root.children[4].type, builder.nodeType.ProcessingInstruction)
25-
eq(root.children[5].type, builder.nodeType.Dummy)
2624

2725
test 'DTD node types', ->
2826
dtd = xml('root', { headless: true }).dtd()

0 commit comments

Comments
 (0)