KDL Document Language

repository·main·Indexed 23 days ago

https://github.com/kdl-org/kdl

A small document language with XML-like node semantics designed for serialization and configuration. KDL aims to be as readable as CLI commands while providing structured data capabilities. It supports nodes with arguments, properties, and child nodes, and is available in versions 1.0.0 and 2.0.0 with implementations across multiple languages including Rust, JavaScript, Go, Python, C/C++, and Java.

Tokens
9.2K
Snippets
24
Records
54
Agent score
82%

What's inside KDL

  1. What is KDL?

    main

    KDL is a document language with XML-like node semantics designed to look like CLI command invocations. It serves as both a serialization format and a configuration language, similar to JSON, YAML, or XML. It supports nodes with standalone values, key/value pairs, multi-line strings (including raw and dedented versions), and comments.

    package {
      name my-pkg
      version "1.2.3"
    
      dependencies {
        lodash "^3.2.1" optional=#true alias=underscore
      }
    
      scripts {
        message """
          hello
          world
          """
        build #"""
          echo "foo"
          node -c "console.log('hello, world!');"
          echo "foo" > some-file.txt
          """#
      }
    
      the-matrix 1 2 3 \
                 4 5 6 \
                 7 8 9
    
      /-this-is-commented {
        this entire node {
          is gone
        }
      }
    }
  2. Introduction to KDL

    main

    KDL is a node-oriented document language designed to be easy to read and easy to implement. It is suitable for use as both a configuration language and a data exchange or storage format, similar to XML.

    In the specification, references to "left" and "right" refer to the direction of the data stream (towards the beginning or end of the text, respectively).

  3. What is KDL Schema and how is it used?

    main

    KDL Schema is a schema language written in KDL itself, designed to describe and constrain the allowed semantics of a KDL document. It allows developers to define rules for what a KDL document can contain, which can be used for:

    • Documentation: Providing clear rules for users on how to structure their KDL files.
    • Automated Verification: Validating KDL documents against a defined schema to ensure they are semantically correct.
    • Automated Generation: Using the schema to automatically generate language bindings.

    This specification refers to KDL Schema version 1.0.0 (released September 11, 2021).

  4. KDL Versions and Migration

    main

    KDL has two major versions: KDL 1.0.0 (legacy) and KDL 2.0.0 (current).

    Users are encouraged to migrate to KDL 2.0.0. Migration is forward-and-backward-compatible and safe, and can be automated. There is no data ambiguity between v1 and v2 documents, though different library implementations may support different versions or offer a hybrid mode.

  5. Use Comments in KDL

    main

    KDL supports three types of comments:

    1. Single-line comments: Start with // and continue until the next newline.
    2. Multi-line comments: Start with /* and end with */. These can be nested.
    3. Slashdash comments: Denoted by /-. These are used to logically comment out entire components (Nodes, Arguments, Property keys, or Children Blocks) so they are not included in the parsed data. A slashdash can be followed by whitespace or other comments before the target element.
  6. KDL Node Syntax and Structure

    main

    A KDL node consists of a node name (string), zero or more arguments (values), and optional child nodes. Nodes can also have properties (key=value pairs).

    Key structural rules:

    • Nodes without children can be terminated by a newline, a semicolon, or the end of the file.
    • Properties and values can be interspersed (e.g., node key=val 1 2 3).
    • Node names and property keys are strings and can be unquoted identifiers or quoted/raw strings.
    • For lists of arbitrary values, a common convention is to name the nodes -.
  7. Use Quoted and Raw Strings

    main

    KDL supports two types of strings:

    1. Quoted Strings: Delimited by ". They support escape sequences like \n, \r, \t, \\, \/, \", \b, \f, and \u{hex}.
    2. Raw Strings: Delimited by r followed by zero or more # characters and a ". They do not support escapes. The string ends with a matching number of # characters and a ". This allows the string to contain literal quotes or hashes.
    just-escapes r"\n will be literal"
    quotes-and-escapes r#"hello\n\r\asd"world"#
  8. Understand the KDL Document structure

    main

    A KDL Document is the top-level container, composed of zero or more Nodes separated by whitespace and newlines. All documents must be UTF-8 encoded.

    Nodes can be organized into a hierarchy using Children Blocks (enclosed in { and }).

    foo {
        bar
    }
    baz
  9. Use Raw Strings for literal text

    main

    Raw Strings are variants of Quoted and Multi-Line strings that do not support \-escapes (including line-continuation escapes). They are useful when you want the string to contain literal backslashes and escape sequences without processing them.

    To create a Raw String, precede the opening quotes with one or more # characters. The string must then be closed by the normal closing quotes followed by a matching number of # characters. This allows the string to contain any combination of " and # as long as it doesn't match the specific closing delimiter sequence.

    Note: Raw Strings cannot contain disallowed literal code-points (like certain control characters) because they do not support Unicode escapes.

    just-escapes #"\n will be literal"#
    
    quotes-and-escapes ##"hello\n\r\asd"#world"##
    
    raw-multi-line #"""
        Here's a """
            multiline string
            """
        without escapes.
        """#
  10. Use KQL matchers to filter nodes by attributes

    main

    Matchers are used inside [] (or as part of a selector) to filter nodes by their values, properties, names, or type annotations.

    Common Matchers

    • top(): Returns all top-level children of the current document. Note: top() can only be the first matcher in a selector (e.g., top() > [] is valid, but a > top() is not).
    • (foo): Selects elements with type annotation foo.
    • (): Selects any element with any type annotation.
    • [val()]: Selects any element with a value.
    • [val(n)]: Selects any element with the $n^{th}$ value.
    • [prop(foo)] or [foo]: Selects any element with a property named foo.

    Comparison Operators

    Matchers support various operators for filtering:

    • Equality/Inequality: [val() = 1], [val() != 1], [prop(name) = 1].
    • Node Identity: [name() = hi] (node name is "hi") or [tag() = hi] (tag is "hi").
    • Numeric Comparison: [val() > 1], [val() >= 1], [val() < 1], [val() <= 1].
    • String Pattern Matching (works only on strings):
      • [val() ^= foo]: Starts with "foo".
      • [val() $= foo]: Ends with "foo".
      • [val() *= foo]: Contains "foo".
    • Type Matching: [val() = (foo)] (value's type annotation is foo).