Source Edit

A simple XML tree generator.

Example:

  1. import std/xmltree
  2. var g = newElement("myTag")
  3. g.add newText("some text")
  4. g.add newComment("this is comment")
  5. var h = newElement("secondTag")
  6. h.add newEntity("some entity")
  7. let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes
  8. let k = newXmlTree("treeTag", [g, h], att)
  9. doAssert $k == """<treeTag key1="first value" key2="second value">
  10. <myTag>some text<!-- this is comment --></myTag>
  11. <secondTag>&some entity;</secondTag>
  12. </treeTag>"""

See also:

Imports

since, macros, strtabs, strutils, sequtils

Types

  1. XmlAttributes = StringTableRef

An alias for a string to string mapping.

Use toXmlAttributes proc to create XmlAttributes.

Source Edit

  1. XmlNode = ref XmlNodeObj

An XML tree consisting of XML nodes.

Use newXmlTree proc for creating a new tree.

Source Edit

  1. XmlNodeKind = enum
  2. xnText, ## a text element
  3. xnVerbatimText, xnElement, ## an element with 0 or more children
  4. xnCData, ## a CDATA node
  5. xnEntity, ## an entity (like ``&thing;``)
  6. xnComment ## an XML comment

Different kinds of XML nodes. Source Edit

Consts

  1. xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"

Header to use for complete XML output. Source Edit

Procs

  1. proc `$`(n: XmlNode): string {....raises: [], tags: [], forbids: [].}

Converts n into its string representation.

No <$xml …$> declaration is produced, so that the produced XML fragments are composable.

Source Edit

  1. proc `[]`(n: var XmlNode; i: int): var XmlNode {.inline, ...raises: [], tags: [],
  2. forbids: [].}

Returns the i’th child of n so that it can be modified. Source Edit

  1. proc `[]`(n: XmlNode; i: int): XmlNode {.inline, ...raises: [], tags: [],
  2. forbids: [].}

Returns the i’th child of n.

Example:

  1. var f = newElement("myTag")
  2. f.add newElement("first")
  3. f.insert(newElement("second"), 0)
  4. assert $f[1] == "<first />"
  5. assert $f[0] == "<second />"

Source Edit

  1. proc add(father, son: XmlNode) {.inline, ...raises: [], tags: [], forbids: [].}

Adds the child son to father. father must be of xnElement type

See also:

Example:

  1. var f = newElement("myTag")
  2. f.add newText("my text")
  3. f.add newElement("sonTag")
  4. f.add newEntity("my entity")
  5. assert $f == "<myTag>my text<sonTag />&my entity;</myTag>"

Source Edit

  1. proc add(father: XmlNode; sons: openArray[XmlNode]) {.inline, ...raises: [],
  2. tags: [], forbids: [].}

Adds the children sons to father. father must be of xnElement type

See also:

Example:

  1. var f = newElement("myTag")
  2. f.add(@[newText("my text"), newElement("sonTag"), newEntity("my entity")])
  3. assert $f == "<myTag>my text<sonTag />&my entity;</myTag>"

Source Edit

  1. proc add(result: var string; n: XmlNode; indent = 0; indWidth = 2;
  2. addNewLines = true) {.inline, ...raises: [], tags: [], forbids: [].}

Adds the textual representation of n to string result.

Example:

  1. var
  2. a = newElement("firstTag")
  3. b = newText("my text")
  4. c = newComment("my comment")
  5. s = ""
  6. s.add(c)
  7. s.add(a)
  8. s.add(b)
  9. assert s == "<!-- my comment --><firstTag />my text"

Source Edit

  1. proc addEscaped(result: var string; s: string) {....raises: [], tags: [],
  2. forbids: [].}

The same as result.add(escape(s)), but more efficient. Source Edit

  1. proc attr(n: XmlNode; name: string): string {....raises: [], tags: [], forbids: [].}

Finds the first attribute of n with a name of name. Returns “” on failure.

See also:

Example:

  1. var j = newElement("myTag")
  2. let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes
  3. j.attrs = att
  4. assert j.attr("key1") == "first value"
  5. assert j.attr("key2") == "second value"

Source Edit

  1. proc attrs(n: XmlNode): XmlAttributes {.inline, ...raises: [], tags: [],
  2. forbids: [].}

Gets the attributes belonging to n.

Returns nil if attributes have not been initialised for this node.

See also:

Example:

  1. var j = newElement("myTag")
  2. assert j.attrs == nil
  3. let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes
  4. j.attrs = att
  5. assert j.attrs == att

Source Edit

  1. proc attrs=(n: XmlNode; attr: XmlAttributes) {.inline, ...raises: [], tags: [],
  2. forbids: [].}

Sets the attributes belonging to n.

See also:

Example:

  1. var j = newElement("myTag")
  2. assert j.attrs == nil
  3. let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes
  4. j.attrs = att
  5. assert j.attrs == att

Source Edit

  1. proc attrsLen(n: XmlNode): int {.inline, ...raises: [], tags: [], forbids: [].}

Returns the number of n’s attributes.

See also:

Example:

  1. var j = newElement("myTag")
  2. assert j.attrsLen == 0
  3. let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes
  4. j.attrs = att
  5. assert j.attrsLen == 2

Source Edit

  1. proc child(n: XmlNode; name: string): XmlNode {....raises: [], tags: [],
  2. forbids: [].}

Finds the first child element of n with a name of name. Returns nil on failure.

Example:

  1. var f = newElement("myTag")
  2. f.add newElement("firstSon")
  3. f.add newElement("secondSon")
  4. f.add newElement("thirdSon")
  5. assert $(f.child("secondSon")) == "<secondSon />"

Source Edit

  1. proc clear(n: var XmlNode) {....raises: [], tags: [], forbids: [].}

Recursively clears all children of an XmlNode.

Example:

  1. var g = newElement("myTag")
  2. g.add newText("some text")
  3. g.add newComment("this is comment")
  4. var h = newElement("secondTag")
  5. h.add newEntity("some entity")
  6. let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes
  7. var k = newXmlTree("treeTag", [g, h], att)
  8. doAssert $k == """<treeTag key1="first value" key2="second value">
  9. <myTag>some text<!-- this is comment --></myTag>
  10. <secondTag>&some entity;</secondTag>
  11. </treeTag>"""
  12. clear(k)
  13. doAssert $k == """<treeTag key1="first value" key2="second value" />"""

Source Edit

  1. proc clientData(n: XmlNode): int {.inline, ...raises: [], tags: [], forbids: [].}

Gets the client data of n.

The client data field is used by the HTML parser and generator.

Source Edit

  1. proc clientData=(n: XmlNode; data: int) {.inline, ...raises: [], tags: [],
  2. forbids: [].}

Sets the client data of n.

The client data field is used by the HTML parser and generator.

Source Edit

  1. proc delete(n: XmlNode; i: Natural) {....raises: [], tags: [], forbids: [].}

Deletes the i’th child of n.

See also:

Example:

  1. var f = newElement("myTag")
  2. f.add newElement("first")
  3. f.insert(newElement("second"), 0)
  4. f.delete(0)
  5. assert $f == """<myTag>
  6. <first />
  7. </myTag>"""

Source Edit

  1. proc delete(n: XmlNode; slice: Slice[int]) {....raises: [], tags: [], forbids: [].}

Deletes the items n[slice] of n.

See also:

Example:

  1. var f = newElement("myTag")
  2. f.add newElement("first")
  3. f.insert([newElement("second"), newElement("third")], 0)
  4. f.delete(0..1)
  5. assert $f == """<myTag>
  6. <first />
  7. </myTag>"""

Source Edit

  1. proc escape(s: string): string {....raises: [], tags: [], forbids: [].}

Escapes s for inclusion into an XML document.

Escapes these characters:

charis converted to
<&lt;
>&gt;
&&amp;
&quot;
&apos;

You can also use addEscaped proc.

Source Edit

  1. proc findAll(n: XmlNode; tag: string; caseInsensitive = false): seq[XmlNode] {.
  2. ...raises: [], tags: [], forbids: [].}

A shortcut version to assign in let blocks.

Example:

  1. var
  2. b = newElement("good")
  3. c = newElement("bad")
  4. d = newElement("BAD")
  5. e = newElement("GOOD")
  6. b.add newText("b text")
  7. c.add newText("c text")
  8. d.add newText("d text")
  9. e.add newText("e text")
  10. let a = newXmlTree("father", [b, c, d, e])
  11. assert $(a.findAll("good")) == "@[<good>b text</good>]"
  12. assert $(a.findAll("BAD")) == "@[<BAD>d text</BAD>]"
  13. assert $(a.findAll("good", caseInsensitive = true)) == "@[<good>b text</good>, <GOOD>e text</GOOD>]"
  14. assert $(a.findAll("BAD", caseInsensitive = true)) == "@[<bad>c text</bad>, <BAD>d text</BAD>]"

Source Edit

  1. proc findAll(n: XmlNode; tag: string; result: var seq[XmlNode];
  2. caseInsensitive = false) {....raises: [], tags: [], forbids: [].}

Iterates over all the children of n returning those matching tag.

Found nodes satisfying the condition will be appended to the result sequence.

Example:

  1. var
  2. b = newElement("good")
  3. c = newElement("bad")
  4. d = newElement("BAD")
  5. e = newElement("GOOD")
  6. b.add newText("b text")
  7. c.add newText("c text")
  8. d.add newText("d text")
  9. e.add newText("e text")
  10. let a = newXmlTree("father", [b, c, d, e])
  11. var s = newSeq[XmlNode]()
  12. a.findAll("good", s)
  13. assert $s == "@[<good>b text</good>]"
  14. s.setLen(0)
  15. a.findAll("good", s, caseInsensitive = true)
  16. assert $s == "@[<good>b text</good>, <GOOD>e text</GOOD>]"
  17. s.setLen(0)
  18. a.findAll("BAD", s)
  19. assert $s == "@[<BAD>d text</BAD>]"
  20. s.setLen(0)
  21. a.findAll("BAD", s, caseInsensitive = true)
  22. assert $s == "@[<bad>c text</bad>, <BAD>d text</BAD>]"

Source Edit

  1. proc innerText(n: XmlNode): string {....raises: [], tags: [], forbids: [].}

Gets the inner text of n:

  • If n is xnText or xnEntity, returns its content.
  • If n is xnElement, runs recursively on each child node and concatenates the results.
  • Otherwise returns an empty string.

See also:

Example:

  1. var f = newElement("myTag")
  2. f.add newText("my text")
  3. f.add newComment("my comment")
  4. f.add newEntity("my entity")
  5. assert $f == "<myTag>my text<!-- my comment -->&my entity;</myTag>"
  6. assert innerText(f) == "my textmy entity"

Source Edit

  1. proc insert(father, son: XmlNode; index: int) {.inline, ...raises: [], tags: [],
  2. forbids: [].}

Inserts the child son to a given position in father.

father must be of xnElement kind.

See also:

Example:

  1. var f = newElement("myTag")
  2. f.add newElement("first")
  3. f.insert(newElement("second"), 0)
  4. assert $f == """<myTag>
  5. <second />
  6. <first />
  7. </myTag>"""

Source Edit

  1. proc insert(father: XmlNode; sons: openArray[XmlNode]; index: int) {.inline,
  2. ...raises: [], tags: [], forbids: [].}

Inserts the children openArray`sons` to a given position in father.

father must be of xnElement kind.

See also:

Example:

  1. var f = newElement("myTag")
  2. f.add newElement("first")
  3. f.insert([newElement("second"), newElement("third")], 0)
  4. assert $f == """<myTag>
  5. <second />
  6. <third />
  7. <first />
  8. </myTag>"""

Source Edit

  1. proc kind(n: XmlNode): XmlNodeKind {.inline, ...raises: [], tags: [], forbids: [].}

Returns n’s kind.

Example:

  1. var a = newElement("firstTag")
  2. assert a.kind == xnElement
  3. var b = newText("my text")
  4. assert b.kind == xnText

Source Edit

  1. proc len(n: XmlNode): int {.inline, ...raises: [], tags: [], forbids: [].}

Returns the number of n’s children.

Example:

  1. var f = newElement("myTag")
  2. f.add newElement("first")
  3. f.insert(newElement("second"), 0)
  4. assert len(f) == 2

Source Edit

  1. proc newCData(cdata: sink string): XmlNode {....raises: [], tags: [], forbids: [].}

Creates a new XmlNode of kind xnCData with the text cdata.

Example:

  1. var d = newCData("my cdata")
  2. assert d.kind == xnCData
  3. assert $d == "<![CDATA[my cdata]]>"

Source Edit

  1. proc newComment(comment: sink string): XmlNode {....raises: [], tags: [],
  2. forbids: [].}

Creates a new XmlNode of kind xnComment with the text comment.

Example:

  1. var c = newComment("my comment")
  2. assert c.kind == xnComment
  3. assert $c == "<!-- my comment -->"

Source Edit

  1. proc newElement(tag: sink string): XmlNode {....raises: [], tags: [], forbids: [].}

Creates a new XmlNode of kind xnElement with the given tag.

See also:

Example:

  1. var a = newElement("firstTag")
  2. a.add newElement("childTag")
  3. assert a.kind == xnElement
  4. assert $a == """<firstTag>
  5. <childTag />
  6. </firstTag>"""

Source Edit

  1. proc newEntity(entity: string): XmlNode {....raises: [], tags: [], forbids: [].}

Creates a new XmlNode of kind xnEntity with the text entity.

Example:

  1. var e = newEntity("my entity")
  2. assert e.kind == xnEntity
  3. assert $e == "&my entity;"

Source Edit

  1. proc newText(text: sink string): XmlNode {....raises: [], tags: [], forbids: [].}

Creates a new XmlNode of kind xnText with the text text.

Example:

  1. var b = newText("my text")
  2. assert b.kind == xnText
  3. assert $b == "my text"

Source Edit

  1. proc newVerbatimText(text: sink string): XmlNode {....raises: [], tags: [],
  2. forbids: [].}

Creates a new XmlNode of kind xnVerbatimText with the text text. Since: Version 1.3. Source Edit

  1. proc newXmlTree(tag: sink string; children: openArray[XmlNode];
  2. attributes: XmlAttributes = nil): XmlNode {....raises: [],
  3. tags: [], forbids: [].}

Creates a new XML tree with tag, children and attributes.

See also:

Example:

  1. var g = newElement("myTag")
  2. g.add newText("some text")
  3. g.add newComment("this is comment")
  4. var h = newElement("secondTag")
  5. h.add newEntity("some entity")
  6. let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes
  7. let k = newXmlTree("treeTag", [g, h], att)
  8. doAssert $k == """<treeTag key1="first value" key2="second value">
  9. <myTag>some text<!-- this is comment --></myTag>
  10. <secondTag>&some entity;</secondTag>
  11. </treeTag>"""

Source Edit

  1. proc rawTag(n: XmlNode): string {.inline, ...raises: [], tags: [], forbids: [].}

Returns the underlying ‘tag’ string by reference.

This is only used for speed hacks.

Source Edit

  1. proc rawText(n: XmlNode): string {.inline, ...raises: [], tags: [], forbids: [].}

Returns the underlying ‘text’ string by reference.

This is only used for speed hacks.

Source Edit

  1. proc replace(n: XmlNode; i: Natural; replacement: openArray[XmlNode]) {.
  2. ...raises: [], tags: [], forbids: [].}

Replaces the i’th child of n with replacement openArray.

n must be of xnElement kind.

See also:

Example:

  1. var f = newElement("myTag")
  2. f.add newElement("first")
  3. f.insert(newElement("second"), 0)
  4. f.replace(0, @[newElement("third"), newElement("fourth")])
  5. assert $f == """<myTag>
  6. <third />
  7. <fourth />
  8. <first />
  9. </myTag>"""

Source Edit

  1. proc replace(n: XmlNode; slice: Slice[int]; replacement: openArray[XmlNode]) {.
  2. ...raises: [], tags: [], forbids: [].}

Deletes the items n[slice] of n.

n must be of xnElement kind.

See also:

Example:

  1. var f = newElement("myTag")
  2. f.add newElement("first")
  3. f.insert([newElement("second"), newElement("fifth")], 0)
  4. f.replace(0..1, @[newElement("third"), newElement("fourth")])
  5. assert $f == """<myTag>
  6. <third />
  7. <fourth />
  8. <first />
  9. </myTag>"""

Source Edit

  1. proc tag(n: XmlNode): lent string {.inline, ...raises: [], tags: [], forbids: [].}

Gets the tag name of n.

n has to be an xnElement node.

See also:

Example:

  1. var a = newElement("firstTag")
  2. a.add newElement("childTag")
  3. assert $a == """<firstTag>
  4. <childTag />
  5. </firstTag>"""
  6. assert a.tag == "firstTag"

Source Edit

  1. proc tag=(n: XmlNode; tag: sink string) {.inline, ...raises: [], tags: [],
  2. forbids: [].}

Sets the tag name of n.

n has to be an xnElement node.

See also:

Example:

  1. var a = newElement("firstTag")
  2. a.add newElement("childTag")
  3. assert $a == """<firstTag>
  4. <childTag />
  5. </firstTag>"""
  6. a.tag = "newTag"
  7. assert $a == """<newTag>
  8. <childTag />
  9. </newTag>"""

Source Edit

  1. proc text(n: XmlNode): lent string {.inline, ...raises: [], tags: [], forbids: [].}

Gets the associated text with the node n.

n can be a CDATA, Text, comment, or entity node.

See also:

Example:

  1. var c = newComment("my comment")
  2. assert $c == "<!-- my comment -->"
  3. assert c.text == "my comment"

Source Edit

  1. proc text=(n: XmlNode; text: sink string) {.inline, ...raises: [], tags: [],
  2. forbids: [].}

Sets the associated text with the node n.

n can be a CDATA, Text, comment, or entity node.

See also:

Example:

  1. var e = newEntity("my entity")
  2. assert $e == "&my entity;"
  3. e.text = "a new entity text"
  4. assert $e == "&a new entity text;"

Source Edit

  1. proc toXmlAttributes(keyValuePairs: varargs[tuple[key, val: string]]): XmlAttributes {.
  2. ...raises: [], tags: [], forbids: [].}

Converts {key: value} pairs into XmlAttributes.

Example:

  1. let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes
  2. var j = newElement("myTag")
  3. j.attrs = att
  4. doAssert $j == """<myTag key1="first value" key2="second value" />"""

Source Edit

Iterators

  1. iterator items(n: XmlNode): XmlNode {.inline, ...raises: [], tags: [], forbids: [].}

Iterates over all direct children of n.

Example:

  1. var g = newElement("myTag")
  2. g.add newText("some text")
  3. g.add newComment("this is comment")
  4. var h = newElement("secondTag")
  5. h.add newEntity("some entity")
  6. g.add h
  7. assert $g == "<myTag>some text<!-- this is comment --><secondTag>&some entity;</secondTag></myTag>"
  8. # for x in g: # the same as `for x in items(g):`
  9. # echo x
  10. # some text
  11. # <!-- this is comment -->
  12. # <secondTag>&some entity;<![CDATA[some cdata]]></secondTag>

Source Edit

  1. iterator mitems(n: var XmlNode): var XmlNode {.inline, ...raises: [], tags: [],
  2. forbids: [].}

Iterates over all direct children of n so that they can be modified. Source Edit

Macros

  1. macro `<>`(x: untyped): untyped

Constructor macro for XML. Example usage:

  1. <>a(href="http://nim-lang.org", newText("Nim rules."))

Produces an XML tree for:

  1. <a href="http://nim-lang.org">Nim rules.</a>

Source Edit