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.
worker_threads
pool (Node >= 12).300 KB XML file 100 KB XML file
XML file is an actual XML response from Expedia API. I just delete some nodes to change its size for benchmarking.
For complete benchmark, see benchmark/index.md.
rapidx2j
or xml2json
no longer works on Node 14 so I remove them from the benchmark.yarn add camaro
## npm install camaro
You can use our custom template format powered by XPath.
We also introduce some custom syntax such as:
#
, that means it’s a constant. E.g: #1234
will return 1234
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 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.
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>
#json #xml #camaro #programming #developer