xrust

repository·main·Indexed 41 days ago

https://github.com/ballsteve/xrust

A Rust implementation of the XML technology stack targeting XPath 3.1, XQuery 3.1, and XSLT 3.0. It provides a robust XDM 3.1 data model, a navigable and mutable tree structure via the smite library, and a secure-by-default model for external resource access. Version 2.2.0 provides functional equivalence to XPath 1.0 and XSLT 1.0 while utilizing the v3.0 data model.

Tokens
25K
Snippets
48
Records
77
Agent score
100%

What's inside xrust

  1. Overview of χrust

    main

    χrust (pronounced "crust") is a Rust library providing implementations for XPath, XQuery, and XSLT. It includes an XML parser based on a parser combinator approach.

    Current Capabilities:

    • Functional equivalent of XPath 1.0 and XSLT 1.0.
    • Implements the XQuery and XPath Data Model (XDM) 3.1.
    • Supports advanced features like FLWR expressions, grouping (xsl:for-each-group), and user-defined functions.

    Note on Compliance: While it implements the core elements of v1.0, it is not strictly compliant with v1.0 standards because it uses the v3.0 data model.

  2. Understanding the Smite Tree model

    main

    The "Tree" is the fundamental data object used for transformations in χrust. It is implemented via a library called smite.

    Key Characteristics:

    • Fully Navigable: From any given node, you can access its children, parent, siblings, or attributes.
    • Mutable: It achieves mutability through the interior mutability pattern (the name "smite" is an anagram of "tuple struct enum interior mutability").
  3. How χrust parsing and evaluation works

    main

    The library follows a design that separates parsing from evaluation.

    1. Compilation Phase: XPath expressions or XSLT stylesheets are parsed (compiled) into an internal representation called a "transformation".
    2. Evaluation Phase: The resulting transformation is then evaluated against data.

    This design ensures that different syntaxes that represent the same logic result in the same internal transformation format. For example, an XPath if $a then "a is true" else "" will compile to the same internal form as an XSLT <xsl:if test="$a">a is true</xsl:if>.

  4. How XML Namespaces are handled

    main

    Namespace support in χrust is implemented across three layers:

    1. Parsing: The XML parser uses a NamespaceMap (a flat mapping of prefix to URI) to track in-scope namespaces during construction.
    2. Tree Representation: The smite tree implementation includes a Namespace type node to represent XML Namespace declarations. NamespaceNode objects are Rc-shared for efficiency.
    3. Transformations: Transformations can store a NamespaceMap to use during the transformation process.

    A convenience routine is provided to build a NamespaceMap from Namespace node declarations.

  5. Securing XML and XSLT transformations

    main

    Because XML documents and XSLT stylesheets can access external resources, χrust implements a "secure by default" security model. By default, access to external resources is restricted (often completely).

    Security Components:

    • Security Feature: A module defines a feature that determines if resource access is permitted and may impose limits (e.g., limiting the size of an external entity).
    • Security Policy: An application creates a policy containing multiple features. When a module attempts to access a resource, it looks up the required feature in the current policy to decide if the action is allowed.
  6. Copy items using shallow or deep copy

    main

    The module provides two ways to copy items:

    1. copy (Shallow Copy): Selects items using a Transform s, performs a shallow copy, and then constructs new content for each copied item using a second Transform c.
    2. deep_copy: Selects items using a Transform s and returns a sequence of fully independent deep copies of those items.
  7. Set evaluation depth limits for security

    main

    To prevent infinite loops during transformation, you can limit the maximum evaluation depth. This is controlled via the max_depth field in Context or by setting a security policy.

    In XSLT, this can be controlled via the feature URI: Q{http://gitlab.gnome.org/World/Rust/markup-rs/xrust/transform}maximum-depth

    Security results for this feature:

    • NotPermitted: Uses the default value.
    • Permitted (no value): No limit.
    • Permitted (with value): The provided number is the maximum depth.
  8. Configure security policies to prevent exfiltration and DoS

    main

    The security module allows you to define and enforce restrictions to prevent data exfiltration or denial-of-service attacks.

    Security is managed through three layers:

    1. Feature: A specific capability or access type defined by a module.
    2. Policy: A combination of Features that defines what is allowed.
    3. Restriction: A policy can permit a feature but further restrict it with specific limits.
  9. Construct XML elements and nodes during transformation

    main
    The src/transform/construct.rs module provides internal functions used during XSLT-like transformations to build new XML nodes (elements, attributes, text, comments, etc.) for the result document. These functions interact with a Context<N> which holds the Result Document (rd) and a StaticContext for dispatching transformations.
  10. Configure node matching with NodeMatch and NodeTest

    main

    To select or filter nodes, use NodeMatch, which combines an Axis with a NodeTest.

    NodeTest Types

    • Kind(KindTest): Matches based on the node type (e.g., Element, Attribute, Text, Comment, PI, Document).
    • Name(NameTest): Matches based on the node's name, supporting:
      • Exact QName matches.
      • Wildcards for namespaces or local names (e.g., *:local-name or prefix:*).

    Axis Types

    Axis defines the direction of navigation in the tree. Common axes include:

    • Child, Descendant, DescendantOrSelf.
    • Parent, Ancestor, AncestorOrSelf.
    • Following, FollowingSibling, Preceding, PrecedingSibling.
    • Attribute, SelfAxis, SelfDocument, SelfNamespace.
  11. Define grouping logic with the Grouping enum

    main

    The Grouping<N> enum determines how a collection is divided into groups during operations like ForEach.

    Supported grouping methods:

    • By(Vec<Transform<N>>): Groups items based on the result of a transformation.
    • StartingWith(Box<Pattern<N>>): Groups items based on a pattern match at the start.
    • EndingWith(Box<Pattern<N>>): Groups items based on a pattern match at the end.
    • Adjacent(Vec<Transform<N>>): Groups adjacent items based on a transformation.