Crate ogrim

source ·
Expand description

XML builder macro letting you write XML inside Rust code (similar to serde_json::json!).

This library only builds a string, not some kind of tree representing the XML document. Thus, you cannot introspect it after building. So this is just a better format! for building XML.

There are no memory allocations in this library except by the String that is being built. Not even temporarily, not even for escaping values. This should make it quite speedy and at least as fast as hand written string building.

Mini example

use ogrim::xml;

let cat_name = "Tony";
let doc = xml!(
    <?xml version="1.0" ?>
    <zoo name="Lorem Ipsum" openingYear={2000 + 13}>
        <cat>{cat_name}</cat>
        <dog>"Barbara"</>   // omit name of closing tab for convenience
    </zoo>
);

println!("{}", doc.as_str()); // Print XML

As you can see, the name of the closing tab can be omitted. This should help a little bit with XML’s verbosity. For more information and examples, see xml.

Of course, values are escaped:

let doc = ogrim::xml!(
    <?xml version="1.0" ?>
    <foo name=r#"a"b<c&d"#>
        "Little Bobby </foo> Tables"
    </foo>
);

assert_eq!(doc.as_str(), concat!(
    r#"<?xml version="1.0" encoding="UTF-8"?>"#,
    r#"<foo name="a&quot;b&lt;c&amp;d">Little Bobby &lt;/foo&gt; Tables</foo>"#,
));

Limitations and notes

  • This crate only lets you build UTF-8 encoded XML documents.

  • Text content of nodes has to be quoted (e.g. <foo>"hello"</foo> instead of <foo>hello</foo>).

  • Writing names (i.e. tag and attribute names) has some special cases. In short: if you only use valid ASCII Rust identifiers with : in the middle of the name (e.g. atom:link), you are fine. In other cases, see below or just use a string literal: <"weird3.14exml-name:" />.

    The gory details

    First, talking about characters beyond ASCII, XML names allow some chars that Rust identifiers do not allow. Those are just not part of the Rust lexicographical grammar and hence, using a string literal is necessary in that case. But you likely won’t run into this. For completeness, here are all characters you could legally write in XML names, but not in Rust identifiers.

    Further, - : . are all not part of Rust identifier, but instead treated by Rust as “puncuation”. And Rust macros have no information about whitespace at all, so these three inputs are the same:

    • <foo:bar: baz="3">
    • <foo:bar :baz="3">
    • <foo: bar:baz="3">

    This library uses some best effort guesses to disambiguate this. If you don’t use - : . at the end of an XML name it should work fine. Finally, due to these characters being treated as punctuation, digits after these puncuations are parsed as numeric literals, which brings a whole new bag of weird behavior. For example, foo:27eels fails to parse as 27e is parsed as a floating point literal with exponent… but the actual exponent is missing.

    Again: for most normal names, everything should just work. For everything else, know these rules or just use a string literal instead.

Macros

  • Builds or appends to an XML Document by writing XML in your Rust code.

Structs

  • A document, potentially still under construction.

Enums

  • Specifies how the XML should be formatted.