Git Product home page Git Product logo

camaro's Introduction

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

camaro's People

Contributors

amilajack avatar anhthang avatar axelpale avatar cdm6a avatar davidspiess avatar dependabot[bot] avatar dsifford avatar eyolas avatar greenkeeper[bot] avatar tpberntsen avatar tuananh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

camaro's Issues

Provide sync API

Since it's a straightforward change (as far as I can tell), I'd like to work on providing an alternative synchronous API for this lib.

This would mean keeping the async API as-is:

  • transform
  • toJson
  • prettyPrint

The new API would provide the new sync functions:

  • transformSync
  • toJsonSync
  • prettyPrintSync

My proposal will most probably involve refactoring the async calls so that they return a Promise that wraps up a call to their corresponding sync alternative (since that's what's done currently). This change should be backwards compatible.

npm ERR! extraneous: for camaro packages

Hi everyone

I noticed npm ERR! extraneous: errors when execute npm list command in my project. Output;

npm ERR! extraneous: [email protected] /Users/orhan/projects/rx-soap-client/node_modules/camaro/node_modules/detect-libc
npm ERR! extraneous: [email protected] /Users/orhan/projects/rx-soap-client/node_modules/camaro/node_modules/needle
npm ERR! extraneous: [email protected] /Users/orhan/projects/rx-soap-client/node_modules/camaro/node_modules/nopt
npm ERR! extraneous: [email protected] /Users/orhan/projects/rx-soap-client/node_modules/camaro/node_modules/npm-packlist
npm ERR! extraneous: [email protected] /Users/orhan/projects/rx-soap-client/node_modules/camaro/node_modules/npmlog
npm ERR! extraneous: [email protected] /Users/orhan/projects/rx-soap-client/node_modules/camaro/node_modules/rc
npm ERR! extraneous: [email protected] /Users/orhan/projects/rx-soap-client/node_modules/camaro/node_modules/rimraf
npm ERR! extraneous: [email protected] /Users/orhan/projects/rx-soap-client/node_modules/camaro/node_modules/semver
npm ERR! extraneous: [email protected] /Users/orhan/projects/rx-soap-client/node_modules/camaro/node_modules/tar

is there anything we should concern?

Issue with whitespace

I'm having an issue with whitespace and I'm wondering if Camaro is handling it as-designed, or if I should look to another package to help with this.

Given this chunk of XML (truncated, but you get the idea)

<body>
 … 
he conducted research in immunology and rheumatology.</p>
</sec>
</sec>
<sec disp-level="1">
<title>Eye on 45</title>
<sec disp-level="2">
<title>Protests take shape</title>
<p>As U.S. President …

Using this to construct my template…

body: "article/body",

I get this result…

he conducted research in immunology and rheumatology.Eye on 45Protests take shapeAs U.S. President 

I do want to take the entire text of the body as just text, without any tags preserved. Should I expect to see a space character between where tags were stripped, or should it be concatenated like this?

`transform` in parallel does not work and messes with process

Describe the bug

If you call transform before it's previous invocation has returned, it seems to drop the previous promise somehow

eg:

const { transform } = require('camaro')

const doit = () => transform('<foo>bar</foo>', { foo: 'foo' })

doit().then(_ => console.log('done 1'), console.error)
doit().then(_ => console.log('done 2'), console.error)

output

done 2

Even weirder, if you force Promise.all([doit(), doit()]) it seems to mess up with the whole process!

const { transform } = require('camaro')

const sleep = t => new Promise(resolve => setTimeout(resolve, t))

const doit = () => transform('<foo>bar</foo>', { foo: 'foo' })

const main = async () => {
  const sleeper = sleep(3000).then(_ => console.log('done sleeping')) // enqueu before, do run after 3 seconds

  try {
    const r = await Promise.all([doit(), doit()])
  } finally {
    console.log('finally block') // never runs
  }

  await sleeper
  console.log('after awaiting sleeper') // never runs
}

main()

This scripts waits 3 seconds to exit but only outputs 'done sleeping'

  • camaro version: 4.0.8, 4.1.2
  • Node version: v8.16.0, v10.16.0, v12.14.0, v13.5.0
  • Operating system: Linux Mint 19.1 Tessa

In camaro 3.0.19 it does work fine

Transforming into array without object inside

I want to transform an area of an XML document formatted like this:
<people> <item>Joseph</item> <item>Frederick</item> <item>Kennedy</item> </people>
into JSON like so:
... people: ["Joseph", "Frederick", "Kennedy"], ...
But the only samples I have found only format the template string so it produces an array with an object inside. Is there any way to get a flat array such as the one above?

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because we are using your CI build statuses to figure out when to notify you about breaking changes.

Since we did not receive a CI status on the greenkeeper/initial branch, we assume that you still need to configure it.

If you have already set up a CI for this repository, you might need to check your configuration. Make sure it will run on all new branches. If you don’t want it to run on every branch, you can whitelist branches starting with greenkeeper/.

We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

Camaro in v8.10.0 Lambda intermittent crashes

Hi,

I have a Lambda executing Node v8.10.0 code which is processing XML responses in near realtime from an API (millions per day). It has been executing perfectly until this past week when the Lambda function has suddenly started intermittently crashing with Process exited before completing request. I doubt the Lambda function is running out of memory: Memory Size: 192 MB Max Memory Used: 75 MB

I have managed to pinpoint this crashing to the Camaro call, which is this in isolation:

const parseXML = require('camaro');
const xmlTemplate = {
	title: '//JD/NeutralForm',
	disciplines: [
		'//JD/Discipline[@language="en"]', '.'
	],
	subDisciplines: [
		'//JD/SubDiscipline[@language="en"]', '.'
	]
};

let result;
try {
	result = parseXML(xml, xmlTemplate);
} catch (err) {
	console.log(err);
}
console.log(result.title, result.disciplines, result.subDisciplines);

Sample of the typical XML when it has failed:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<NormalisationResult>
    <Source><![CDATA[FP&A Accountant]]></Source>
    <NormalisationJDs>
        <JD idGlobalStrikt="1000193383" idnorm="393530" language="en" normbyderivat="0" nosuggest="0" ortho="0" type="JD">
            <NeutralForm><![CDATA[FP&A Accountant]]></NeutralForm>
            <GenderForm gender="M"><![CDATA[FP&A Accountant]]></GenderForm>
            <UsedSource><![CDATA[FP&A Accountant]]></UsedSource>
            <Discipline discipline="Accountancy" id="251169" language="en" subDiscipline="Accountancy"><![CDATA[Accountancy]]></Discipline>
            <SubDiscipline discipline="Accountancy" id="251169" language="en" subDiscipline="Accountancy"><![CDATA[Accountancy]]></SubDiscipline>
            <SynonymJDs>
                <idGlobalStrikt>1000193383</idGlobalStrikt>
            </SynonymJDs>
            <Hypernyms>
                <idGlobalStrikt>1000185261</idGlobalStrikt>
            </Hypernyms>
            <AllHypernyms>
                <idGlobalStrikt>1000185261</idGlobalStrikt>
                <idGlobalStrikt>1000198579</idGlobalStrikt>
                <idGlobalStrikt>170502</idGlobalStrikt>
                <idGlobalStrikt>182350</idGlobalStrikt>
                <idGlobalStrikt>196669</idGlobalStrikt>
            </AllHypernyms>
        </JD>
    </NormalisationJDs>
    <RemainingSource/>
</NormalisationResult>

I cannot see an obvious reason nor why any errors are not being caught by the catch. I have tried switching to manual install as part of Jenkins build instead of using the pre-built binary in Releases, and it has made no difference. Not all requests fail. Any ideas?

ARM support

Hello
Do you have any plan to suppoert ARM CPU support?

I have an ARM chipset box and running Armbian Ubuntu on it but I can't run my camaro dependent project on it.

Here is the docker-compose build logs

Step 6/8 : RUN npm install &&     npm cache clean --force
 ---> Running in b296051d19b0

> [email protected] install /usr/app/node_modules/camaro
> node-pre-gyp install --fallback-to-build

node-pre-gyp WARN Using needle for node-pre-gyp https download
node-pre-gyp WARN Tried to download(404): https://github.com/tuananh/camaro/releases/download/3.0.14/camaro-v3.0.14-node-v64-linux-arm64.tar.gz
node-pre-gyp WARN Pre-built binaries not found for [email protected] and [email protected] (node-v64 ABI, musl) (falling back to source compile with node-gyp)
gyp WARN install got an error, rolling back install
gyp ERR! configure error
gyp ERR! stack Error: read ECONNRESET
gyp ERR! stack     at TLSWrap.onStreamRead (internal/stream_base_commons.js:111:27)
gyp ERR! System Linux 4.20.2-aml-s905
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "configure" "--fallback-to-build" "--module=/usr/app/node_modules/camaro/lib/binding/camaro.node" "--module_name=camaro" "--module_path=/usr/app/node_modules/camaro/lib/binding" "--napi_version=3" "--node_abi_napi=napi" "--napi_build_version=0" "--node_napi_label=node-v64"
gyp ERR! cwd /usr/app/node_modules/camaro
gyp ERR! node -v v10.15.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
node-pre-gyp ERR! build error
node-pre-gyp ERR! stack Error: Failed to execute '/usr/local/bin/node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js configure --fallback-to-build --module=/usr/app/node_modules/camaro/lib/binding/camaro.node --module_name=camaro --module_path=/usr/app/node_modules/camaro/lib/binding --napi_version=3 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=node-v64' (1)
node-pre-gyp ERR! stack     at ChildProcess.<anonymous> (/usr/app/node_modules/node-pre-gyp/lib/util/compile.js:83:29)
node-pre-gyp ERR! stack     at ChildProcess.emit (events.js:182:13)
node-pre-gyp ERR! stack     at maybeClose (internal/child_process.js:962:16)
node-pre-gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:251:5)
node-pre-gyp ERR! System Linux 4.20.2-aml-s905
node-pre-gyp ERR! command "/usr/local/bin/node" "/usr/app/node_modules/.bin/node-pre-gyp" "install" "--fallback-to-build"
node-pre-gyp ERR! cwd /usr/app/node_modules/camaro
node-pre-gyp ERR! node -v v10.15.0
node-pre-gyp ERR! node-pre-gyp -v v0.12.0
node-pre-gyp ERR! not ok
Failed to execute '/usr/local/bin/node /usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js configure --fallback-to-build --module=/usr/app/node_modules/camaro/lib/binding/camaro.node --module_name=camaro --module_path=/usr/app/node_modules/camaro/lib/binding --napi_version=3 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=node-v64' (1)
npm WARN [email protected] had bundled packages that do not match the required version(s). They have been replaced with non-bundled versions.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"arm64"})

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: `node-pre-gyp install --fallback-to-build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2019-02-03T20_31_28_227Z-debug.log

How to define namespaces?

If my XML document contains identical local tag names but in different namespaces, how to tell camaro to select only the other? For example consider the following:

<?xml version="1.0" encoding="UTF-8"?>
<bookings>
  <restaurant xmlns="http://mycustom/namespace">
    <table>
      <reserved>1</reserved>
    </table>
  </restaurant>
  <restaurant xmlns="http://official/namespace/1.2">
    <name>Pizzeria Piccolo</name>
    <table>
      <forPersons>4</forPersons>
      <reserved>
        <from>2017-12-12T16:40</from>
        <to>2017-12-12T18:40</to>
      </reserved>
    </table>
  </restaurant>
</bookings>

How to select only the tables in the namespace http://official/namespace/1.2?

With XPath, one typically defines which prefix maps to which namespace, for example:

{
  c: 'http://mycustom/namespace',
  o: 'http://official/namespace/1.2'
}

And then the template to match the official tables becomes:

var template = {
  tables: ['//o:table', {
    reserved: 'o:reserved'
  }]
};

The example is of course made up and lacking but still, is it possible to do this in camaro?

Issue in Loading camaro on AWS Lambda

I am trying to load Camaro module on my app, it works fine locally (Node v8). But when deploying on AWS Lambda (Node v6.10 runtime) it breaks. Is this library limited to later version of Node. If yes, can you please share how to build this for a lower Node version.

Thanks.

ENOENT error on run since 4.1.1

Describe the bug
After updating to camaro 4.1.1, program does not run and instead crashes with an ENOENT error. Deleting node_modules and package-lock.json does not help, but downgrade to 4.1.0 and running npm install again resolves the issue.

Error:

{ Error: ENOENT: no such file or directory, open '<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.wasm'
    at Object.openSync (fs.js:438:3)
    at Object.readFileSync (fs.js:343:35)
    at w (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:9:121)
    at x (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:9:178)
    at Ea (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:17:305)
    at Fa.u.function.fetch.credentials (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:18:85)
    at new Promise (<anonymous>)
    at Fa (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:18:59)
    at d (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:19:220)
    at <<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:20:193
    at Ga (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:20:412)
    at Object.e.asm (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:21:152)
    at <<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:36:10
    at Object.<anonymous> (<<PROJECT LOCATION>>\node_modules\camaro\index.js:12:18)
    at Module._compile (internal/modules/cjs/loader.js:701:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
  errno: -4058,
  syscall: 'open',
  code: 'ENOENT',
  path:
   '<<PROJECT LOCATION>>\\node_modules\\camaro\\dist\\camaro.wasm' }
{ Error: ENOENT: no such file or directory, open '<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.wasm'
    at Object.openSync (fs.js:438:3)
    at Object.readFileSync (fs.js:343:35)
    at w (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:9:121)
    at x (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:9:178)
    at Ea (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:17:305)
    at Fa.u.function.fetch.credentials (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:18:85)
    at new Promise (<anonymous>)
    at Fa (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:18:59)
    at d (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:19:220)
    at <<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:20:193
    at Ga (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:20:412)
    at Object.e.asm (<<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:21:152)
    at <<PROJECT LOCATION>>\node_modules\camaro\dist\camaro.js:36:10
    at Object.<anonymous> (<<PROJECT LOCATION>>\node_modules\camaro\index.js:12:18)
    at Module._compile (internal/modules/cjs/loader.js:701:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
  errno: -4058,
  syscall: 'open',
  code: 'ENOENT',
  path:
   '<<PROJECT LOCATION>>\\node_modules\\camaro\\dist\\camaro.wasm' }
  • camaro version: 4.1.1
  • Node version: 10.15.3
  • Operating system: Windows 10

Is it possible to keep the order of the keys in the template?

Hi,
First of all, thank you so much for this great package.

I have been using it for a while and I have found that all the result JSON structures are returned with the keys ordered alphabetically, ignoring completely the order specified in the template.

Is there a way to control this?

Thanks!

npm installation failed

When I try to install your module using npm install camaro I get this error

[email protected] install c:....\node_modules\camaro
node-pre-gyp install --fallback-to-build

node-pre-gyp WARN Using needle for node-pre-gyp https download
node-pre-gyp WARN Tried to download(404): https://github.com/tuananh/camaro/releases/download/3.0.15/camaro-v3.0.15-node-v57-win32-x64.tar.gz
node-pre-gyp WARN Pre-built binaries not found for [email protected] and [email protected] (node-v57 ABI, unknown) (falling back to source compile with node-gyp)
gyp ERR! configure error
gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.
gyp ERR! stack at PythonFinder.failNoPython (C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\configure.js:483:19)
gyp ERR! stack at PythonFinder. (C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\lib\configure.js:508:16)
gyp ERR! stack at C:\Program Files\nodejs\node_modules\npm\node_modules\graceful-fs\polyfills.js:284:29
gyp ERR! stack at FSReqWrap.oncomplete (fs.js:152:21)
gyp ERR! System Windows_NT 10.0.17763
gyp ERR! command "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js" "configure" "--fallback-to-build" "--module=c:\...\node_modules\camaro\lib\binding\camaro.node" "--module_name=camaro" "--module_path=c:\...\node_modules\camaro\lib\binding" "--napi_version=1" "--node_abi_napi=napi" "--napi_build_version=0" "--node_napi_label=node-v57"
gyp ERR! cwd c:...\node_modules\camaro
gyp ERR! node -v v8.11.1
gyp ERR! node-gyp -v v3.6.2
gyp ERR! not ok
node-pre-gyp ERR! build error
node-pre-gyp ERR! stack Error: Failed to execute 'C:\Program Files\nodejs\node.exe C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js configure --fallback-to-build --module=c:...\node_modules\camaro\lib\binding\camaro.node --module_name=camaro --module_path=c:...\node_modules\camaro\lib\binding --napi_version=1 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=node-v57' (1)
node-pre-gyp ERR! stack at ChildProcess. (c:...\node_modules\node-pre-gyp\lib\util\compile.js:83:29)
node-pre-gyp ERR! stack at emitTwo (events.js:126:13)
node-pre-gyp ERR! stack at ChildProcess.emit (events.js:214:7)
node-pre-gyp ERR! stack at maybeClose (internal/child_process.js:925:16)
node-pre-gyp ERR! stack at Process.ChildProcess._handle.onexit (internal/child_process.js:209:5)
node-pre-gyp ERR! System Windows_NT 10.0.17763
node-pre-gyp ERR! command "C:\Program Files\nodejs\node.exe" "c:\...\node_modules\node-pre-gyp\bin\node-pre-gyp" "install" "--fallback-to-build"
node-pre-gyp ERR! cwd c:...\node_modules\camaro
node-pre-gyp ERR! node -v v8.11.1
node-pre-gyp ERR! node-pre-gyp -v v0.12.0
node-pre-gyp ERR! not ok
Failed to execute 'C:\Program Files\nodejs\node.exe C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js configure --fallback-to-build --module=c:\…\node_modules\camaro\lib\binding\camaro.node --module_name=camaro --module_path=c:...\node_modules\camaro\lib\binding --napi_version=1 --node_abi_napi=napi --napi_build_version=0 --node_napi_label=node-v57' (1)
npm WARN sip No description
npm WARN sip No repository field.
npm WARN sip No license field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: node-pre-gyp install --fallback-to-build
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! C:...\AppData\Roaming\npm-cache_logs\2019-02-22T12_21_50_074Z-debug.log

I will attach the log file

2019-02-22T12_21_50_074Z-debug.log

Publish 3.0.18 to npm and build 3.0.17 win32x64

Describe the bug
Due to the performance decrease in going to webasm I wish to stay at v3 of the package, there are some issues though with the builds of 3.0.17 and 3.0.18,
first is that 3.0.18 has not been sent to the npmjs.org registry (having instead 3.0.17)
second is that 3.0.17 does download and install correctly on win32-x64 devices

node-pre-gyp WARN Tried to download(404): https://github.com/tuananh/camaro/releases/download/3.0.17/camaro-v3.0.17-node-v72-win32-x64.tar.gz

than later camaro\src\transform.cpp(5): fatal error C1083: Cannot open include file: 'pugixml/src/pugixml.hpp': No such file or directory (compiling source file
..\src\camaro.cpp) [[...]\camaro\build\camaro.vcxproj] as it seems the dependencies don't get loaded in the build script.

Travis CI Error: CXXABI_1.3.8 not found

I am trying to run a test suite using Travis CI. The build fails because Camaro build throws the following error:

Error: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by /home/travis/build/axelpale/tresdb/node_modules/camaro/lib/binding/camaro.node)
    at Object.Module._extensions..node (module.js:682:18)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/home/travis/build/axelpale/tresdb/node_modules/camaro/index.js:4:16)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/home/travis/build/axelpale/tresdb/server/api/locations/importer/parsekml.js:2:20)

I have tried both Camaro v3.0.14 and v3.0.16 with the same result.

My travis.yml is rather minimal and basic, see below. The default OS of Travis build is Ubuntu Trusty 14.04.

language: node_js
node_js:
  - "8"
branches:
  only:
  - master

Any tips? I will try to post a solution if I manage to find one.

Use with Angular 5 Project

Hi guys,

I am trying to get this working with an Angular 5 Project using Angular-Cli & Typescript.

Once i have added package with npm or yarn, when i try to use it in a component i am getting the following error:

ERROR
src/app/shared/components/xml-reader/xml-reader.ts(5,19): error TS2304: Cannot find name 'require'.

CODE

import { Component, EventEmitter, Output } from '@angular/core';

const transform = require('camaro')

@Component({
    selector: 'mi-xml-reader',
    templateUrl: './xml-reader.html',
    styleUrls: ['./xml-reader.scss']
})

export class XmlReaderComponent {

    loadXmlFile($event: any) {
        
        const file: File = $event.target.files[0];
        
        const template = {
            cache_key: '/HotelListResponse/cacheKey',
            hotels: ['//HotelSummary', {
                hotel_id: 'hotelId',
                name: 'name',
                rooms: ['RoomRateDetailsList/RoomRateDetails', {
                    rates: ['RateInfos/RateInfo', {
                        currency: 'ChargeableRateInfo/@currencyCode',
                        non_refundable: 'boolean(nonRefundable = "true")',
                        price: 'number(ChargeableRateInfo/@total)'
                    }],
                    room_name: 'roomDescription',
                    room_type_id: 'roomTypeCode'
                }]
            }],
            session_id: '/HotelListResponse/customerSessionId'
        }
        const result = transform(file.name, template)
    }  
}

REVISED CODE
I also tried to revise the code to something like so i.e. did an import instead of require:

import { Component, EventEmitter, Output } from '@angular/core';

import * as transform from 'camaro';

@Component({
    selector: 'mi-xml-reader',
    templateUrl: './xml-reader.html',
    styleUrls: ['./xml-reader.scss']
})

export class XmlReaderComponent {

    loadXmlFile($event: any) {
        
        const file: File = $event.target.files[0];
        
        const template = {
            cache_key: '/HotelListResponse/cacheKey',
            hotels: ['//HotelSummary', {
                hotel_id: 'hotelId',
                name: 'name',
                rooms: ['RoomRateDetailsList/RoomRateDetails', {
                    rates: ['RateInfos/RateInfo', {
                        currency: 'ChargeableRateInfo/@currencyCode',
                        non_refundable: 'boolean(nonRefundable = "true")',
                        price: 'number(ChargeableRateInfo/@total)'
                    }],
                    room_name: 'roomDescription',
                    room_type_id: 'roomTypeCode'
                }]
            }],
            session_id: '/HotelListResponse/customerSessionId'
        }
        const result = transform(file.name, template)
    }    
}

REVISED ERROR

ERROR in node_modules/camaro/index.d.ts(2,1):
error TS1046: A 'declare' modifier is required for a top level declaration in a .d.ts file.

Array in an Array

Describe the bug
I'm trying to template a file that could have an array of tags inside and array of tags. When I try parsing it the return is returned as [Array]

Minimal Script To Reproduce
This is the XML I'm using. It may have more than one ContactPostals each with AddressLine's within.

<ContactPostals xmlns="">
            <AddressID>1013923</AddressID>
            <AddressNumber>8</AddressNumber>
            <AddressLine>Any Close</AddressLine>
            <AddressLine>Anytown</AddressLine>
            <AddressLine>Anyshire</AddressLine>
            <AddressLine xsi:nil="true"/>
            <AddressLine xsi:nil="true"/>
            <AddressLine xsi:nil="true"/>
            <Postcode>LE44 4AA</Postcode>
</ContactPostals>

This is the template I'm using:

            contactPostals: [ '//ContactPostals', {
                addressNumber: AddressNumber',
                addressLine: [ 'AddressLine', '.' ],
                postcode: 'Postcode',
                uPRN: 'UPRN'
            },

Which yields

contactPostals: 
   [ { addressNumber: '8',
       addressLine: [Array],
       postcode: 'LE44 4AA',
       uPRN: '' } ],

Expected Results

addressLine: [
  '8', 'Any Close', 'Anytown', 'Anyshire', '', ''
]
  • camaro version: 4.0.5
  • Node version: 8.16.0
  • Operating system: Debian Buster

Conditional template

How do I create a template for the following use case:

Assuming we have the following variations:

<!-- first variation -->
....
<content>
  <morning> morning text </morning>
  <evening> evening text </evening>
</content>
....
<!-- second variation -->
...
<content> some text </content>
...

I want to be able to extract the content and obtain the variation of content as follows:
content: ['some text'] or content: { morning: 'morning text', evening: 'evening text'}.

How do i write the template for such a use case?

[question] how to set default value if a path value is empty

Is there a straight forward way of returning a specified value if a path defined in the template is empty? I am using the package in an AWS Lambda function to parse XML docs to JSON, then upload that into DynamoDB. The issue I am having with camaro returning blank if a path is empty is DynamoDB doesn't allow an attribute value to contain an empty string. Currently I am looping through the object returned by transform to check for empty strings, but hoping there is a better way I may be missing. I am admittedly not well versed in XPath, but since 'if a path is empty, return blank' is listed as custom syntax I figured it best to ask here first.

Thanks in advance and thanks for a great package.

transform function return undefined (5318992)

Hello,
I'm trying to use camaro in my project and I encounter a problem that I'm not sure where it is coming from.
this is my code:

    const {transform} = require('camaro');
    const fs = require('fs');
     ....
module.myModule= function () {
       try {
           var xml= fs.readFileSync('c:\myPath\file.xml', 'utf-8');
       } catch (err) {
           console.error(err);
       };

       const sampleTemplet = {
         first: "first element",
         second: "second element"
       };
       (async function() {
          try {
              var result = await transform(xml, sampleTemplet);
          } catch (err) {
              console.error(err);
          };
          console.log(result);
        })();

     };

the result is that transform return undefined error (with number 5318992)
and I can't figure out why because there is no err.message or err.stack - both return undefined as well.

  • camaro version: 4.0.7
  • Node version: 8.14.0
  • Operating system: WIN10

Could it be it doesn't work on Wíndows?

Hi,
I am already trying for hours to parse something on windows but the results are not consistent.
It always worked before when I am only extracting one value from an xml, but when I am trying more complex stuff things seem not to work so well,

const transform = require('camaro')

const xml = `
<?xml version="1.0" encoding="UTF-8"?>
<bookings>
    <restaurant>
        <name>Pizzeria Piccolo</name>
        <table>
            <forPersons>4</forPersons>
            <reserved>
                <from>2017-12-12T16:40</from>
                <to>2017-12-12T18:40</to>
            </reserved>
        </table>
        <table>
            <forPersons>2</forPersons>
            <reserved>
                <from>2018-12-12T16:40</from>
                <to>2018-12-12T18:40</to>
            </reserved>
        </table>
    </restaurant>
</bookings>
`
const result = transform(xml, {
    nodes: [
        '//restaurant/table',
        {
            forPersons: 'forPersons',
            from: 'reserved/from',
            to: 'reserved/to'
        }
    ]
})

console.log(JSON.stringify(result, null, 4))

I get

{ "nodes": [] }

What am I doing wrong?

Windows 7
camaro 2.26
node 8.7.0

Best,
P

select all // should only select all nodes from current context

example

const template = {
    outerArr: ['//outer', {
    	innerArr: ['//inner', {
    		item: 'item'
    	}]
    }]
}

the select all selector of innerArr should only select all inner nodes inside the current node of the outer nodes only.

currently, it will return all inner nodes of the document.

Add better typing to `transform`

It is possible to statically type the parsed type based on the template argument, I was meaning to do a PR but have no idea how to test it, plus, the definition of 'Template' is possibly incomplete, since I couldn't find doc on it.

I'm using these helpers:

import { transform } from 'camaro'

export type Template<P extends Props> = P
export type Props = { [key: string]: Mixed }
export type Mixed = string | Props | [string, Props]
export type OutputOf<T extends Props> = OutputOfMixed<T>
export type OutputOfMixed<T extends Mixed> = T extends string
  ? string
  : T extends Props
  ? { [P in keyof T]: OutputOfMixed<T[P]> }
  : T extends [string, Props]
  ? Array<OutputOf<T[1]>>
  : never

export const template = <P extends Props>(props: P): Template<P> => props
export const parse = <P extends Props>(template: Template<P>, xml: string): Promise<OutputOf<P>> => transform(xml, template)

With those, the example in README can be refactored to:

const Rate = template({
  currency: 'ChargeableRateInfo/@currencyCode',
  non_refundable: 'boolean(nonRefundable = "true")',
  price: 'number(ChargeableRateInfo/@total)'
})

const Room = template({
  room_name: 'roomDescription',
  room_type_id: 'roomTypeCode',
  rates: ['RatesInfos/RateInfo', Rate]
})

const Hotel = template({
  hotel_id: 'hotelId',
  name: 'name',
  rooms: ['RoomRateDetailsList/RoomRateDetails', Room]
})

const Doc = template({
  cache_key: '/HotelListResponse/cacheKey',
  session_id: '/HotelListResponse/customerSessionId',
  hotels: ['//HotelSummary', Hotel]
})

And TS can infer the parsed type:

const result = parse(Doc, '')
// Revealed:
// const result: Promise<{
//   cache_key: string;
//   session_id: string;
//   hotels: {
//       hotel_id: string;
//       name: string;
//       rooms: {
//           room_name: string;
//           room_type_id: string;
//           rates: {
//               currency: string;
//               non_refundable: string;
//               price: string;
//           }[];
//       }[];
//   }[];
// }>

Or it can be extracted:

type DocType = OutputOf<typeof Doc>
// Revealed:
// type DocType = {
//   cache_key: string;
//   session_id: string;
//   hotels: {
//       hotel_id: string;
//       name: string;
//       rooms: {
//           room_name: string;
//           room_type_id: string;
//           rates: {
//               currency: string;
//               non_refundable: string;
//               price: string;
//           }[];
//       }[];
//   }[];
// }

Thanks for this awesome project btw

Module not found: Can't resolve xxxx

Describe the bug
using serverless framework and trying to transform the xml using template. getting error Module not found for asm2wasm, env, global, along with below error -
WebAssembly module is included in initial chunk.
This is not allowed, because WebAssembly download and compilation must happen asynchronous.
Add an async splitpoint (i. e. import()) somewhere between your entrypoint and the WebAssembly module:

Minimal Script To Reproduce
running sls offline in serverless project

const { transform } = require('camaro')
// your code
  let result = await transform(data, {
     data : ['xxx,xxx', {
          processDate: 'xxx',
          effectiveDate: 'xxx',
          tranSubCode: 'xxxx',
}]
[camaro-issue.txt](https://github.com/tuananh/camaro/files/4531879/camaro-issue.txt)




**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

- camaro version: 4.1 , 4.2 
- Node version:  10.x , 12.x
- Operating system: win10

camaro.transform is not a function

I've been trying to upgrade camaro on an old app. It's currently using v1.2.0 and working fine. However, there are quite a lot of vulnerabilities reported by npm, so I'd like to update it.

I've already updated some related apps which run on AWS Lambda. I hit issues with v3.0.8 on Lambda, but 3.0.7 is working fine. So I am trying to use the same version for an app that will run on an AWS EC2 linux instance. Locally, it runs on node 8.2.1 on OSX.

When I do a normal install (Locally on OSX): npm i --save [email protected] it installs without error, but when it runs, I get this:

(node:97402) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3874): TypeError: camaro.transform is not a function
Error saving fare flow data TypeError: camaro.transform is not a function
at transform (/Users/ianbale/Source Code/data-manager-ftp/node_modules/camaro/index.js:34:25)

I've also tried rebuilding camaro as I had to do for v1.2.0:

npm i [email protected] --build-from-source --update-binary

But this fails:

285 warn [email protected] had bundled packages that do not match the required version(s). They have been replaced with non-bundled versions.
286 verbose stack Error: [email protected] install: `node-pre-gyp install --fallback-to-build`
286 verbose stack Exit status 1
286 verbose stack     at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:304:16)
286 verbose stack     at emitTwo (events.js:125:13)
286 verbose stack     at EventEmitter.emit (events.js:213:7)
286 verbose stack     at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
286 verbose stack     at emitTwo (events.js:125:13)
286 verbose stack     at ChildProcess.emit (events.js:213:7)
286 verbose stack     at maybeClose (internal/child_process.js:921:16)
286 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5)
287 verbose pkgid [email protected]
288 verbose cwd /Users/ianbale/Source Code/data-manager-ftp
289 verbose Darwin 17.6.0
290 verbose argv "/usr/local/bin/node" "/usr/local/bin/npm" "i" "[email protected]" "--build-from-source" "--update-binary"
291 verbose node v8.2.1
292 verbose npm  v6.2.0
293 error code ELIFECYCLE
294 error errno 1
295 error [email protected] install: `node-pre-gyp install --fallback-to-build`

I've also tried simply installing 3.0.7 then overwriting camaro.node with the prebuilt binary camaro-v3.0.7-node-v57-darwin-x64.tar.gz

I get the same runtime error:

(node:97402) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3874): TypeError: camaro.transform is not a function
Error saving fare flow data TypeError: camaro.transform is not a function
at transform (/Users/ianbale/Source Code/data-manager-ftp/node_modules/camaro/index.js:34:25)

Can you offer any insight into why I am having so much difficulty with this version of Camaro?

Module worker.js not found when using Typescript

Hi There!

This project looks so great! I love the template idea and haven't seen anything as user friendly. Bravo.

I'm not sure if Camaro is supposed to work with Typescript, it feels like it should, but perhaps, there's an issue with .wasm?

I'm getting the following error about worker.js not being found when I try and run a simple test with Jest.

I'm going to keep playing around and see if it's something to do with my Typescript workflow, but I thought I'd pop this up in case anyone else had come across and fixed this issue :)

Thanks again, all the best

J

(node:2138) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:2138) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

events.js:170
      throw er; // Unhandled 'error' event
      ^
Error: Cannot find module '/Users/redacted-user/redacted/project/node_modules/camaro/worker.js'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:668:15)
    at Function.Module._load (internal/modules/cjs/loader.js:591:27)
    at Module.require (internal/modules/cjs/loader.js:723:19)
    at require (internal/modules/cjs/helpers.js:14:16)
    at Promise.resolve.then (/Users/redacted-user/redacted/project/node_modules/piscina/dist/src/worker.js:39:67)
Emitted 'error' event at:
    at EventEmitterReferencingAsyncResource.runInAsyncScope (async_hooks.js:188:21)
    at Piscina.emit (/Users/redacted-user/redacted/project/node_modules/eventemitter-asyncresource/src/index.ts:50:31)
    at Worker.worker.on (/Users/redacted-user/redacted/project/node_modules/piscina/src/index.ts:596:30)
    at Worker.emit (events.js:193:13)
    at Worker.[kOnErrorMessage] (internal/worker.js:170:10)
    at Worker.[kOnMessage] (internal/worker.js:180:37)
    at MessagePort.Worker.(anonymous function).on (internal/worker.js:113:57)
    at MessagePort.emit (events.js:193:13)
    at MessagePort.onmessage (internal/worker/io.js:73:8)
node[2138]: ../src/env.cc:963:virtual node::AsyncRequest::~AsyncRequest(): Assertion `(async_) == nullptr' failed.
 1: 0x100069fdc node::Abort() [/Users/redacted-user/.nvm/versions/node/v11.15.0/bin/node]
 2: 0x100069903 node::GetErrorSource(v8::Isolate*, v8::Local<v8::Context>, v8::Local<v8::Message>, bool*) [/Users/redacted-user/.nvm/versions/node/v11.15.0/bin/node]
 3: 0x10002c4c6 node::Environment::~Environment() [/Users/redacted-user/.nvm/versions/node/v11.15.0/bin/node]
 4: 0x1000d85d9 node::worker::Worker::~Worker() [/Users/redacted-user/.nvm/versions/node/v11.15.0/bin/node]
 5: 0x1000d86c2 node::worker::Worker::~Worker() [/Users/redacted-user/.nvm/versions/node/v11.15.0/bin/node]
 6: 0x100240917 v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo*) [/Users/redacted-user/.nvm/versions/node/v11.15.0/bin/node]
 7: 0x10023fee6 v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) [/Users/redacted-user/.nvm/versions/node/v11.15.0/bin/node]
 8: 0x10023f5e0 v8::internal::Builtin_Impl_HandleApi
const { transform } = require('camaro')

const template = [
  "newsMessage/itemSet/packageItem/newsItem",
  {
    name: "catalogRef",
  },
];

export default async (xmlString: string) => {
  try {
    const result = await transform(xmlString, template);
    return result;
  } catch (e) {
    throw new Error("Transform didn't work");
  }
};

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

  • camaro version: 6.0.0
  • Node version: 11.15
  • Operating system: MacOS

Cleanup JSON result

Hi,
How can I clean up the resulting white space and \n characters please?

{"sku":"\n                        0135363004\n                    ","barCode":"\n                        60000000425\n                    ","cost":"\n                        1250.0000\n                    ","description":"\n                        725 HUNTER 12G 28\" M/C\n                    ","price":"\n                        1250.0000\n                    "},{"sku":"\n                        00100\n                    ","barCode":"\n                        60000000000\n                    ","cost":"\n                        0.1600\n                    ","description":"\n                        ELEY 22 TENEX\n                    ","price":"\n                        0.0000\n                    "},{"sku":"\n                        001-V2250-L\n                    ","barCode":"\n                        60000000548\n                    ","cost":"\n                        65.0000\n                    ","description":"\n                        SKEET JACKET LEATHER LRG\n                    ","price":"\n                        65.0000\n                    "},{"sku":"\n                        01100\n                    ","barCode":"\n                        60000000022\n                    ","cost":"\n                        0.1230\n                    ","description":"\n                        ELEY 22 MATCH\n                    ","price":"\n                        0.1200\n                    "},{"sku":"\n                        011605204\n                    ","barCode":"\n                        60000000346\n                    ","cost":"\n                        740.0000\n                    ","description":"\n                        MAXUS COMPOSITE 3.5\" 28\"\n                    ","price":"\n                        0.0000\n                    "},{"sku":"\n                        011607304\n                    ","barCode":"\n                        60000000347\n                    ","cost":"\n                        956.0000\n                    ","description":"\n                        BROWNING MAXUS G3 28\"\n                    ","price":"\n                        0.0000\n                    "},{"sku":"\n                        011684304\n                    ","barCode":"\n                        60000000348\n                    ","cost":"\n                        852.0000\n                    ","description":"\n                        MAXUS BLACK CARBON SPORT 28\"\n                    ","price":"\n                        831.0000\n                    "},

I am using the follwing in my code:

const xml = fs.readFileSync("./temp/itemMasters.xml", "utf-8");

  const template = {
    products: [
      "//a:ItemMaster",
      {
        sku: "a:Sku",
        barCode: "a:BarcodeNumber",
        cost: "a:Cost",
        description: "a:Description",
        price: "a:Price"
      }
    ]
  };

  (async function() {
    const result = await transform(xml, template);
    let json = JSON.stringify(result.products);
    fs.writeFileSync("./temp/ItemMasters.json", json);
  })();

Problem running under docker?

Hi,

I have a small app which is using camaro. All works fine locally (OSX - i5 CPU). I recently tried out docker and have moved it into a docker file. I had to remove and reinstall camaro for it to run, but having done that it works perfectly.

Now I've moved my docker image onto a Centos 7 VM (Xeon CPU). Now I'm getting "Illegal instruction (core dumped)" when the app attempts to decode some XML with camaro.

I'm using the official node.js docker image with node v6.11.0

Wondering if this is a known issue and whether there is anything I can do to correct it?

Question: Template extraction

Hi There!

Thanks again for Camaro. It's so lovely, but unfortunately I have to work in a Node 10 environment.

I wonder if in your travels you've come across any libraries that use a similar XPath template API. that Camaro uses, or is it uniquely your design?

Thank you for being so generous with your time!

Get all text nodes (PCDATA)

Describe the issue
I have a long XML with a lot of children and I need all text nodes, not just a first.

Minimal Script To Reproduce

const { transform } = require('camaro')
const xml = `<root>
                    <string>test</string>
                    <arr>
                        <item>1</item>
                        <item>2</item>
                        <item>3</item>
                    </arr>
                </root>
                `
const template = {
    data: '/root'
}

Expected behavior
I want below as response

<string>test</string>
                    <arr>
                        <item>1</item>
                        <item>2</item>
                        <item>3</item>
                    </arr>

Purpose
We can consider to use some template below

  • /root/pcdata() - probably, it's new indicator
  • /root/nodes()

Reference: https://stackoverflow.com/questions/21794767/pugixml-get-all-text-nodes-pcdata-not-just-the-first

Environment

  • camaro version: 3.0.17
  • Node version: LTS
  • Operating system: macOS

Issue Camaro and Lambda AWS / Serverless

Hello, I'm new to using camaro and Lambda function from AWS. When I want to deploy the lambda function with serverless I'm getting the following error in the cloudwatch:
module initialization error: Error at Error (native) at Object.Module._extensions..node (module.js:597:18) at Module.load (module.js:487:32) at tryModuleLoad (module.js:446:12) at Function.Module._load (module.js:438:3) at Module.require (module.js:497:17) at require (internal/module.js:20:19) at Object.<anonymous> (/var/task/node_modules/camaro/index.js:4:16) at Module._compile (module.js:570:32) at Object.Module._extensions..js (module.js:579:10)

My package.json
{ "name": "lambda-dashboardcb", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "start": "nodemon ./bin/www" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "axios": "^0.17.1", "body-parser": "^1.18.2", "camaro": "^2.2.2", "cookie-parser": "^1.4.3", "debug": "~2.6.9", "express": "^4.15.5", "google-oauth-jwt": "^0.2.0", "googleapis": "^23.0.0", "morgan": "^1.9.0", "pug": "^2.0.0-beta11", "serve-favicon": "^2.4.5", "serverless-http": "^1.5.2" }, "devDependencies": { "nodemon": "^1.13.3", "serverless-offline": "^3.16.0" } }

My serverless.yml
service: lambda-dashboardcb

provider:
name: aws
runtime: nodejs6.10
stage: dev
region: eu-west-1

functions:
app:
handler: index.handler
events:
- http: ANY /
- http: 'ANY {proxy+}'
plugins:

  • serverless-offline

Suggestion: Add `engines` field to package.json

Describe the bug
Camaro requires Node >= 12 to run, installs quietly into <12 projects and creates phantom bugs.

by adding:

"engines": {
  "node": ">=12.0.0"
}

A compatible node version will be verified at install time, triggering a failure if necessary.

x86_64 binaries are compiled for a specific arch?

Hello,

When our developers are trying to install camaro via NPM the binaries being downloaded give an "Illegal Instruction" on Westmere generation chips.

Are you compiling with a specific -march flag? Considering there are many generations of Xeons in production everywhere is it possible to get a less processor-specific build included in npm to make it easier to install?

I get the need to tweak for speed, and if we need to we can compile this for a particular generation of processors using specific versions of GCC/Clang we can, but it may be a good idea to make it 'just work' for older x86_64 builds?

Warning: (node:23080) ExperimentalWarning: The ESM module loader is experimental.

Camaro started giving this warning recently, it still works, though.

Running on node.js 12.18.0 and camaro is v6.0.2.

Is this something a new version of node introduced or a new version of camaro?

(node:23080) ExperimentalWarning: The ESM module loader is experimental.
(node:23080) ExperimentalWarning: The ESM module loader is experimental.
(node:23080) ExperimentalWarning: The ESM module loader is experimental.
(node:23080) ExperimentalWarning: The ESM module loader is experimental.

How can i access attributes values in xml tag ??

  • How can i access attributes values in xml tag ??
-<City Id="1" JPDCode="JPD000003">
- <Name>Can Pastilla</Name>
- <Country Id="118" JPDCode="JPD034804">
- <Name>Spain</Name>
- </Country>
- <Region Id="1953" JPDCode="JPD036705">
- <Name>Majorca</Name>
- </Region>
- </City>

How can u get JPDCode ??

Node throw error

having error in below line (node_modules\camaro\dist\camaro.js:9) in windows 10 (64bit)

if(aa){v=__dirname+"/";var da,ea;w=function(a,b){da||(da=require("fs"));ea||(ea=require("path"));a=ea.normalize(a);a=da.readFileSync(a);return b?a:a.toString()};x=function(a){a=w(a,!0);a.buffer||(a=new Uint8Array(a));a.buffer||z("Assertion failed: undefined");return a};1<process.argv.length&&process.argv[1].replace(/\/g,"/");process.argv.slice(2);process.on("uncaughtException",function(a){throw a;});process.on("unhandledRejection",z);e.inspect=function(){return"[Emscripten Module object]"}}else if(ca)"undefined"!=

camaro version: 4.1.2
Node version: 12.16.2
OS: Windows 10 (64 bit)

what could be the solution to this error ?

Undefined or missing elements parse as empty strings

When parsing some XML which has optional elements, the values get returned as an empty string.

Included are the example output that is received and the desired output, plus the code used to generate.

It would be greatly appreciated for some pointers on how to produce the desired output and in any case thanks for the work on the library.

Example Output

[
  {
    "optional": "has a value"
  },
  {
    "optional": ""
  },
  {
    "optional": ""
  }
]

Desired Output

[
  {
    "optional": "has a value"
  },
  {
    "optional": null
  },
  {
    "optional": null
  }
]

Code

const xml = `
  <example>
    <entry>
      <optional>has a value</optional>
    </entry>

    <entry>
      <optional/>
    </entry>

    <entry/>
  </example>
`;

const result = await camaro.transform(xml, [
  '//entry',
  {
    optional: 'optional',
  },
]);

console.log(JSON.stringify(result, null, 2));

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.