A Rust decoder and encoder for Microsoft's Binary XML (MS-BINXML) format, used by SQL Server Analysis Services (SSAS) and the XMLA protocol.
XMLA responses from Analysis Services are often transmitted as compact binary XML rather than text XML. This crate converts between the two representations:
- Decode — parse a raw MS-BINXML byte payload into an indented XML string
- Encode — serialize a UTF-8 XML string into a MS-BINXML v1 byte payload
The implementation follows the MS-BINXML v9.0 specification.
[dependencies]
ms-binxml = "0.1"use ms_binxml::{is_bxml, decode};
let data: &[u8] = /* bytes from an XMLA response */;
if is_bxml(data) {
let xml = decode(data)?;
println!("{xml}");
}use ms_binxml::encode;
let xml = r#"<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body />
</soap:Envelope>"#;
let bxml: Vec<u8> = encode(xml)?;use ms_binxml::{decode, encode};
let original = decode(bxml_bytes)?;
let re_encoded = encode(&original)?;
let recovered = decode(&re_encoded)?;
assert_eq!(original, recovered);| Function | Description |
|---|---|
is_bxml(data: &[u8]) -> bool |
Returns true if data starts with the MS-BINXML signature bytes DF FF |
decode(data: &[u8]) -> Result<String, Error> |
Decodes a MS-BINXML payload to an indented XML string |
encode(xml: &str) -> Result<Vec<u8>, Error> |
Encodes a UTF-8 XML string to a MS-BINXML v1 payload |
The decoder has an implementation path for every token type defined in the codebase, covering all SQL and XSD scalar types (integers, floats, decimals, UUIDs, date/time variants, binary blobs, strings), structural tokens (elements, attributes, namespaces, CDATA, comments, processing instructions, nested documents), and name/qname dictionary tokens. The token list is based on the MS-BINXML v9.0 specification, though most scalar type paths are not yet covered by the test suite.
The encoder produces valid v1 payloads with string values encoded as T_SQL_NVARCHAR (UTF-16LE), which is what Analysis Services expects for XMLA requests.
In practice, Analysis Services often compresses MS-BINXML payloads with LZXpress before transmission. You will typically need to decompress the response body before passing it to decode. The rust-lzxpress crate (v0.7.1+) handles this decompression.
MIT — see LICENSE.