• Stars
    star
    491
  • Rank 89,025 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

camaro is an utility to transform XML to JSON, using Node.js binding to native XML parser pugixml, one of the fastest XML parser around.

camaro

camaro is a utility to transform XML to JSON, using Node.js bindings to a native XML parser pugixml - one of the fastest XML parsers around.

npm Build status npm license

🤘 Features

  • Transform XML to JSON.

    • Only take properties that you're interested in.
    • Output is ready to use JS object.
    • For those that need a complete document parser, checkout my other project @tuananh/sax-parser - a pretty fast native module, XML-compliant SAX parser for Node.js.
  • Written in C++ and compiled down to WebAssembly, so no re-compilation needed.

    • No need to build a binary whenever a new Node version is released.
    • Works on all major platforms (OS X, Linux and Windows). See Travis CI and AppVeyor build status for details.
    • AWS Lambda friendly (or serverless in general).
  • It's pretty fast on large XML strings.

    • We're using pugixml under the hood. It's one of the fastest XML parsers around.
    • Scales well with multi-core processors by use of a worker_threads pool (Node >= 12).
  • Pretty print XML.

🔥 Benchmark

300 KB XML file 100 KB XML file
60 KB XML file 7 KB XML file

The XML file is an actual XML response from the Expedia API. I just deleted some nodes to change its size for benchmarking.

For complete benchmark, see benchmark/README.md.

  • Please note that this is an unfair game for camaro because it only transforms the fields specified in the template. The whole reason for me creating this is because most of the time, I'm just interested in some of the data in the whole XML mess.
  • I may expose another method to transform the whole XML tree so that the benchmark will better reflect the real performance.
  • 🚧 Performance on small XML strings will probably be worse than pure JavaScript implementations. If your use cases consists of small XML strings only, you probably don't need this.
  • Some other libraries that I used to use for benchmarks, like rapidx2j and xml2json, no longer work on Node 14, so I removed them from the benchmark.

intro

Installation

yarn add camaro
# npm install camaro

Usage

You can use our custom template format powered by XPath.

We also introduce some custom syntax such as:

  • if a path starts with #, that means it's a constant. E.g, #1234 will return 1234
  • if a path is empty, return blank
  • Some string manipulation functions which are not availble in XPath 1.0, such as lower-case, upper-case, title-case, camel-case, snake-case, string-join or raw. Eventually, I'm hoping to add all XPath 2.0 functions but these are all that I need for now. PRs are welcome.

The rest are pretty much vanilla XPath 1.0.

For complete API documentation, please see API.md

Additional examples can be found in the examples folder at https://github.com/tuananh/camaro/tree/develop/examples or this comprehensive blog post by Ming Di Leom.

const { transform, prettyPrint } = require('camaro')

const xml = `
    <players>
        <player jerseyNumber="10">
            <name>wayne rooney</name>
            <isRetired>false</isRetired>
            <yearOfBirth>1985</yearOfBirth>
        </player>
        <player jerseyNumber="7">
            <name>cristiano ronaldo</name>
            <isRetired>false</isRetired>
            <yearOfBirth>1985</yearOfBirth>
        </player>
        <player jerseyNumber="7">
            <name>eric cantona</name>
            <isRetired>true</isRetired>
            <yearOfBirth>1966</yearOfBirth>
        </player>
    </players>
`

/**
 * the template can be an object or an array depends on what output you want the XML to be transformed to.
 * 
 * ['players/player', {name, ...}] means that: Get all the nodes with this XPath expression `players/player`.
 *      - the first param is the XPath path to get all the XML nodes.
 *      - the second param is a string or an object that describe the shape of the array element and how to get it.
 * 
 * For each of those XML node
 *      - call the XPath function `title-case` on field `name` and assign it to `name` field of the output.
 *      - get the attribute `jerseyNumber` from XML node player
 *      - get the `yearOfBirth` attribute from `yearOfBirth` and cast it to number.
 *      - cast `isRetired` to true if its string value equals to "true", and false otherwise.
 */

const template = ['players/player', {
    name: 'title-case(name)',
    jerseyNumber: '@jerseyNumber',
    yearOfBirth: 'number(yearOfBirth)',
    isRetired: 'boolean(isRetired = "true")'
}]

;(async function () {
    const result = await transform(xml, template)
    console.log(result)

    const prettyStr = await prettyPrint(xml, { indentSize: 4})
    console.log(prettyStr)
})()

Output of transform()

[
    {
        name: 'Wayne Rooney',
        jerseyNumber: 10,
        yearOfBirth: 1985,
        isRetired: false,
    },
    {
        name: 'Cristiano Ronaldo',
        jerseyNumber: 7,
        yearOfBirth: 1985,
        isRetired: false,
    },
    {
        name: 'Eric Cantona',
        jerseyNumber: 7,
        yearOfBirth: 1966,
        isRetired: true,
    }
]

And output of prettyPrint()

<players>
    <player jerseyNumber="10">
        <name>Wayne Rooney</name>
        <isRetired>false</isRetired>
        <yearOfBirth>1985</yearOfBirth>
    </player>
    <player jerseyNumber="7">
        <name>Cristiano Ronaldo</name>
        <isRetired>false</isRetired>
        <yearOfBirth>1985</yearOfBirth>
    </player>
    <player jerseyNumber="7">
        <name>Eric Cantona</name>
        <isRetired>true</isRetired>
        <yearOfBirth>1966</yearOfBirth>
    </player>
</players>

Similar projects

  • cruftless: I personally find this project very fascinating. Its template engine is more powerful than camaro's XPath-based perhaps. You should check it out.

Used by

...

Stargazers over time

Stargazers over time

Licence

The MIT License

More Repositories

1

aws-the-yaml-way

AWS - The YAML way
49
star
2

node-prune

Easily pruning unneeded files from node_modules folder
Shell
47
star
3

BetterTube

A better Youtube embed tag for jekyll: thumbnail on initial load and replace with iframe on click.
CSS
30
star
4

reader

get a reader mode sharable url for any url - built with cloudflare workers https://reader.tuananh.net
JavaScript
26
star
5

reader2

Get a reader mode, sharable URL for any webpage.
JavaScript
21
star
6

kubernetes-twemproxy

🚀 Running twemproxy on Kubernetes
19
star
7

how-small-can-it-be

How small can a Java application container image be
Makefile
15
star
8

argocd-template

WIP: A boilerplate to bootstrap ArgoCD
Makefile
9
star
9

redis-operator-without-writing-any-code

8
star
10

jekyll-pure

✈️ A simple, no bullshit jekyll theme http://tuananh.github.io/jekyll-pure/
CSS
8
star
11

apko-helm-image-demo

Example of using apko/melange to have a fully reproducible, multi-arch, SBOM support container image
8
star
12

kompression

This is a fork of koa-compress with support for brotli compression
JavaScript
8
star
13

sax-parser

An extremely fast SAX parser for Node.js written in C++
JavaScript
6
star
14

webadge.dev

Badges - built with Cloudflare Workers
JavaScript
6
star
15

gitlab-repo-sync

Python
6
star
16

lambda-cdk-template

A simple CDK template to quickly test a Lambda function with CDK.
Python
6
star
17

ArchiveGenerator

Monthly/yearly post archive generator plugin for jekyll
Ruby
6
star
18

fetch

python script to download files via direct HTTP/FTP links using axel/wget
Python
6
star
19

vault-operator

Vault Operator for Kubernetes
Go
5
star
20

netshoot

A port of https://github.com/nicolaka/netshoot Docker + Kubernetes network trouble-shooting swiss-army container
5
star
21

multiarch-docker-example

An example using Docker's new docker buildx bake to build multi-arch container images
Dockerfile
4
star
22

COVID-19

COVID-19 stats - Built with Cloudflare Workers https://covid19.tuananh.net
JavaScript
4
star
23

apko-image-template

Template repo for new apko image.
4
star
24

easy-exif

tiny EXIF reader for Node.js in WebAssembly
C++
4
star
25

common-container-exit-codes

3
star
26

chart-repo-template

A Helm chart repo template that publish to both OCI registry and GitHub Pages
Smarty
3
star
27

github-followers-watch

A simple tool to watch my GitHub account's followers & following list.
Go
3
star
28

feed-furious

a fast XML feed parser
JavaScript
3
star
29

node-module-rust-example

Just an example repo how to write Node module with Rust.
Rust
3
star
30

melange-example

Just an example building container image with melange & apko
Makefile
3
star
31

send-to-kindle

A Lambda function transform webpage into a clean text format and send it over to your Kindle.
JavaScript
3
star
32

distroless-argocd

This is a POC to build Argo CD container image with melange & apko.
3
star
33

starspace

StarSpace native bindings for ⬡.js
Python
3
star
34

backstage-techdocs-example

2
star
35

opentravel

✈ A collection of travel related data
JavaScript
2
star
36

bun

A minimal and secure container image for bun, available in both amd64 and arm64.
2
star
37

netcat

Docker image for Debian port of OpenBSD's netcat, available in both amd64 and arm64
C
2
star
38

data-mesh-and-cloud

data mesh and cloud
2
star
39

svg2pdf

svg2pdf
C
2
star
40

fasttext-native

fastText native bindings for ⬡.js
C++
2
star
41

aws-cdk-k0s-cluster

Create a k0s cluster for testing purpose with Graviton spot instances.
TypeScript
2
star
42

tuananh

2
star
43

aws-cli

A tiny & secure Wolfi-based aws-cli v2 container image.
2
star
44

actions

My commonly used GitHub Actions.
Dockerfile
2
star
45

a-k8s-world-without-helm

A Kubernetes world without Helm
2
star
46

package-json-editor

npm package editor that preserve newline and indentation
JavaScript
2
star
47

ignore.rs

Generate .gitignore file
Rust
1
star
48

csv2xls

csv to xls
JavaScript
1
star
49

bazel-monorepo-template

Bazel monorepo template. Still very much WIP.
Starlark
1
star
50

backstage-model-example

1
star
51

fuso

transforming json to json using JSONPath
C++
1
star
52

keycloak

Keycloak image based on Wolfi
1
star
53

ksec

kubectl create secret utility
JavaScript
1
star
54

pihole-vietnam-ads-filter

pihole vietnam ads filter
1
star
55

jenkins-shared-libraries-tips

Tips and tricks working with Jenkins shared libraries
1
star
56

terragrunt

1
star
57

winston-gcloud

Google Cloud Logging transport for winston
JavaScript
1
star
58

grafana-agent

Wolfi OS-based Grafana Agent container image
1
star
59

jenkins-inbound-agent

1
star
60

atom-xpath

xpath query for atom
JavaScript
1
star
61

talks

https://tuananh.org/talks/
1
star
62

termplot

Tracks expvar-like (JSON) metrics and plot their evolution over time right in the terminal
JavaScript
1
star
63

validate-spdx-license

Go
1
star
64

fast-osm-xml

a fast OSM to JSON parser
JavaScript
1
star
65

py-event-ruler

Test EventBridge pattern locally with Python
Go
1
star
66

deny

Generate .gitignore file using gitingore.io API
JavaScript
1
star
67

IonicTinderCards

IonicTinderCards
JavaScript
1
star
68

cached-execute

redis, lock and load
JavaScript
1
star
69

hacker-news-redesigned

A redesigned Hacker News clone written with React and GraphQL.
JavaScript
1
star
70

azcopy

TEST TEST!!!
1
star
71

containerize

Generate a Dockerfile for your Node.js app
JavaScript
1
star
72

emsdk-docker

Docker image for emsdk
1
star
73

rdd.me

rdd.me url shorterner
1
star
74

smaz.js

⚡️ A Node.js module to compress small string using antirez's smaz.
1
star
75

himitsu

ひみつ - "secret" - STILL VERY MUCH WIP
Go
1
star
76

go-nix

Nix
1
star
77

memcached-exporter

A drop-in replacement for bitnami/memcached-exporter
1
star
78

xpath-object-transform

Transform an object literal using xpath.
JavaScript
1
star
79

redis-autocomplete

Proof of concept to use redis for autocomplete
JavaScript
1
star
80

whatday

find day of week from date
JavaScript
1
star
81

semver

A simple CLI to test a version string whether it satisfies the condition or not.
Go
1
star