Search

Dark theme | Light theme

September 12, 2026

Nushell Niceties: Writing XML

In Nushell almost everything is a data structure. This mind set is also applied to XML structures in Nushell. A XML tag can be described as a record with the attributes tag, attributes and content. The tag attribute has a string value that is the tag name. Attributes are defined with a record structure. The key is the attribute name and the value is the attribute value. Finally the content attribute is a list containing a string value for text content or new record structures for nested XML tags. With this basic record structure you can describe XML content. To actually transform it to a XML string value you can use the command to xml. This command will use the data in the record structure and will output XML.

The next example shows the record structure books to describe a XML tag books with child XML tags book. Each book tag has an attribute isbn and an other child tag title. The title tag contains a string value.

use std/assert

# Record structure with tag, attributes and content
# fields to reflect Nushell's XML structure.
# Following the same structure makes it easy to
# convert this record to XML using the to xml command.
let books = {
  tag: books
  content: [
    {
      tag: book
      attributes: {
        isbn: '9781784396114'
      }
      content: [
        {
          tag: author
          content: ['mrhaki']
        }
        {
          tag: title
          content: ['Gradle Effective Implement Guide']
        }
      ]
    }
    {
      tag: book
      attributes: {
        isbn: '9781784392673'
      }
      content: [
        {
          tag: author
          content: ['mrhaki']
        }
        {
          tag: title
          content: ['Gradle Dependency Management']
        }
      ]
    }
  ]
}

# Use to xml to convert record to XML text.
assert equal ($books | to xml) '<books><book isbn="9781784396114"><author>mrhaki</author><title>Gradle Effective Implement Guide</title></book><book isbn="9781784392673"><author>mrhaki</author><title>Gradle Dependency Management</title></book></books>'

In order to indent the XML content you can use the option --indent or the short-option -i followed by the number of spaces to indent the result.

In the following example the same record books is transformed to XML with indentation of 2 spaces:

use std/assert

# Record structure with tag, attributes and content
# fields to reflect Nushell's XML structure.
# Following the same structure makes it easy to
# convert this record to XML using the to xml command.
let books = {
  tag: books
  content: [
    {
      tag: book
      attributes: {
        isbn: '9781784396114'
      }
      content: [
        {
          tag: author
          content: ['mrhaki']
        }
        {
          tag: title
          content: ['Gradle Effective Implement Guide']
        }
      ]
    }
    {
      tag: book
      attributes: {
        isbn: '9781784392673'
      }
      content: [
        {
          tag: author
          content: ['mrhaki']
        }
        {
          tag: title
          content: ['Gradle Dependency Management']
        }
      ]
    }
  ]
}

# Using --indent option (or short -i) to indent XML result.
assert equal ($books | to xml --indent 2) '<books>
  <book isbn="9781784396114">
    <author>mrhaki</author>
    <title>Gradle Effective Implement Guide</title>
  </book>
  <book isbn="9781784392673">
    <author>mrhaki</author>
    <title>Gradle Dependency Management</title>
  </book>
</books>'

Instead of creating the record structure from scratch you can use Nushell commands to transform any data structure into the record structure with XML data. As you can see in the following example a table of items is transformed to a XML record structure and then transformed to XML text:

use std/assert

# Simple table with three columns title, author, isbn.
let items = [
  [title author isbn];
  [
    'Gradle Effective Implementation Guide'
    'mrhaki'
    '9781784396114'
  ]
  [
    'Gradle Dependency Management'
    'mrhaki'
    '9781784392673'
  ]
]

# Convert table to XML record structure
# with tag, attributes and content fields.
let content = $items | each {|book|
  {
    tag: book
    attributes: {
      isbn: $book.isbn
    }
    content: [
      {
        tag: title
        content: [$book.title]
      }
    ]
  }
}

# Use $content to create final XML with
# books root element.
assert equal ({tag: books content: $content} | to xml -i 2) '<books>
  <book isbn="9781784396114">
    <title>Gradle Effective Implementation Guide</title>
  </book>
  <book isbn="9781784392673">
    <title>Gradle Dependency Management</title>
  </book>
</books>'

To create XML text with XML namespaces is simply using the correct names for the attributes key:

use std/assert

# Namespaces are simply attributes in the record structure.
(assert equal
  ({tag: 'bk:books' attributes: {'xmlns:bk': 'urn:sample:book'}} | to xml)
  '<bk:books xmlns:bk="urn:sample:book"></bk:books>')

The to xml command supports the option --self-closed or short -s to change how empty tags are transformed to XML text. With this option an empty tag will be self-closed in the result. Without the option a start and end tag are created in the resulting XML text without content. The following sample shows the different results by using this option or not:

use std/assert

# Option --self-closed (or short -s) can be used to simplify
# empty XML tags to a self closing tag, instead of a
# start and end tag without content.
assert equal ({tag: books} | to xml --self-closed) '<books/>'
assert equal ({tag: books} | to xml -s) '<books/>'
assert equal ({tag: books} | to xml) '<books></books>'

Written with Nushell 0.115.1