Feature/xmltree additions (#20988)

* [change] add/insert/delete family of xmltree expanded with several variations. Added replace methods family

* [change] Lifted child limitations on insert methods (consulted with @araq)

* [tests] add/insert/replace/delete of xmltree XmlNodes tests added
This commit is contained in:
Michael Voronin
2022-12-22 10:32:12 +03:00
committed by GitHub
parent 93b59da490
commit 7931bdac95
9 changed files with 552 additions and 3 deletions

View File

@@ -31,7 +31,7 @@ runnableExamples:
## * `htmlgen module <htmlgen.html>`_ for html code generator
import std/private/since
import macros, strtabs, strutils
import macros, strtabs, strutils, sequtils
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -298,26 +298,60 @@ proc innerText*(n: XmlNode): string =
proc add*(father, son: XmlNode) {.inline.} =
## Adds the child `son` to `father`.
## `father` must be of `xnElement` type
##
## See also:
## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
## * `insert proc <#insert,XmlNode,XmlNode,int>`_
## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
## * `delete proc <#delete,XmlNode,Natural>`_
## * `delete proc <#delete.XmlNode,Slice[int]>`_
## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
runnableExamples:
var f = newElement("myTag")
f.add newText("my text")
f.add newElement("sonTag")
f.add newEntity("my entity")
assert $f == "<myTag>my text<sonTag />&my entity;</myTag>"
assert father.k == xnElement
add(father.s, son)
proc add*(father: XmlNode, sons: openArray[XmlNode]) {.inline.} =
## Adds the children `sons` to `father`.
## `father` must be of `xnElement` type
##
## See also:
## * `add proc <#add,XmlNode,XmlNode>`_
## * `insert proc <#insert,XmlNode,XmlNode,int>`_
## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
## * `delete proc <#delete,XmlNode,Natural>`_
## * `delete proc <#delete.XmlNode,Slice[int]>`_
## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
runnableExamples:
var f = newElement("myTag")
f.add(@[newText("my text"), newElement("sonTag"), newEntity("my entity")])
assert $f == "<myTag>my text<sonTag />&my entity;</myTag>"
assert father.k == xnElement
add(father.s, sons)
proc insert*(father, son: XmlNode, index: int) {.inline.} =
## Inserts the child `son` to a given position in `father`.
##
## `father` and `son` must be of `xnElement` kind.
## `father` must be of `xnElement` kind.
##
## See also:
## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
## * `add proc <#add,XmlNode,XmlNode>`_
## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
## * `delete proc <#delete,XmlNode,Natural>`_
## * `delete proc <#delete.XmlNode,Slice[int]>`_
## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
runnableExamples:
var f = newElement("myTag")
f.add newElement("first")
@@ -327,18 +361,52 @@ proc insert*(father, son: XmlNode, index: int) {.inline.} =
<first />
</myTag>"""
assert father.k == xnElement and son.k == xnElement
assert father.k == xnElement
if len(father.s) > index:
insert(father.s, son, index)
else:
insert(father.s, son, len(father.s))
proc insert*(father: XmlNode, sons: openArray[XmlNode], index: int) {.inline.} =
## Inserts the children openArray[`sons`] to a given position in `father`.
##
## `father` must be of `xnElement` kind.
##
## See also:
## * `insert proc <#insert,XmlNode,XmlNode,int>`_
## * `add proc <#add,XmlNode,XmlNode>`_
## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
## * `delete proc <#delete,XmlNode,Natural>`_
## * `delete proc <#delete.XmlNode,Slice[int]>`_
## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
runnableExamples:
var f = newElement("myTag")
f.add newElement("first")
f.insert([newElement("second"), newElement("third")], 0)
assert $f == """<myTag>
<second />
<third />
<first />
</myTag>"""
assert father.k == xnElement
if len(father.s) > index:
insert(father.s, sons, index)
else:
insert(father.s, sons, len(father.s))
proc delete*(n: XmlNode, i: Natural) =
## Deletes the `i`'th child of `n`.
##
## See also:
## * `delete proc <#delete.XmlNode,Slice[int]>`_
## * `add proc <#add,XmlNode,XmlNode>`_
## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
## * `insert proc <#insert,XmlNode,XmlNode,int>`_
## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
runnableExamples:
var f = newElement("myTag")
f.add newElement("first")
@@ -351,6 +419,85 @@ proc delete*(n: XmlNode, i: Natural) =
assert n.k == xnElement
n.s.delete(i)
proc delete*(n: XmlNode, slice: Slice[int]) =
## Deletes the items `n[slice]` of `n`.
##
## See also:
## * `delete proc <#delete.XmlNode,int>`_
## * `add proc <#add,XmlNode,XmlNode>`_
## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
## * `insert proc <#insert,XmlNode,XmlNode,int>`_
## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
runnableExamples:
var f = newElement("myTag")
f.add newElement("first")
f.insert([newElement("second"), newElement("third")], 0)
f.delete(0..1)
assert $f == """<myTag>
<first />
</myTag>"""
assert n.k == xnElement
n.s.delete(slice)
proc replace*(n: XmlNode, i: Natural, replacement: openArray[XmlNode]) =
## Replaces the `i`'th child of `n` with `replacement` openArray.
##
## `n` must be of `xnElement` kind.
##
## See also:
## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
## * `add proc <#add,XmlNode,XmlNode>`_
## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
## * `delete proc <#delete,XmlNode,Natural>`_
## * `delete proc <#delete.XmlNode,Slice[int]>`_
## * `insert proc <#insert,XmlNode,XmlNode,int>`_
## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
runnableExamples:
var f = newElement("myTag")
f.add newElement("first")
f.insert(newElement("second"), 0)
f.replace(0, @[newElement("third"), newElement("fourth")])
assert $f == """<myTag>
<third />
<fourth />
<first />
</myTag>"""
assert n.k == xnElement
n.s.delete(i)
n.s.insert(replacement, i)
proc replace*(n: XmlNode, slice: Slice[int], replacement: openArray[XmlNode]) =
## Deletes the items `n[slice]` of `n`.
##
## `n` must be of `xnElement` kind.
##
## See also:
## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
## * `add proc <#add,XmlNode,XmlNode>`_
## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
## * `delete proc <#delete,XmlNode,Natural>`_
## * `delete proc <#delete.XmlNode,Slice[int]>`_
## * `insert proc <#insert,XmlNode,XmlNode,int>`_
## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
runnableExamples:
var f = newElement("myTag")
f.add newElement("first")
f.insert([newElement("second"), newElement("fifth")], 0)
f.replace(0..1, @[newElement("third"), newElement("fourth")])
assert $f == """<myTag>
<third />
<fourth />
<first />
</myTag>"""
assert n.k == xnElement
n.s.delete(slice)
n.s.insert(replacement, slice.a)
proc len*(n: XmlNode): int {.inline.} =
## Returns the number of `n`'s children.
runnableExamples: