使用xml2js解析XML转JSON后存入MongoDB遭遇‘key $ must not start with $’错误的问题咨询
Ah, I've run into this exact issue before! The problem is that xml2js defaults to using $ as the key for XML element attributes, but MongoDB blocks any field names that start with $—that's why you're hitting that error. Here are two straightforward fixes:
Solution 1: Configure xml2js to Use a Valid Attribute Key
The easiest fix is to tweak the xml2js parser settings to use a MongoDB-friendly key (like attributes) instead of $ for storing XML attributes. This avoids the problem entirely during parsing.
Update your parser initialization line to include the attrkey option:
const parser = new xml2js.Parser({ attrkey: 'attributes' }); // Replace default $ with 'attributes'
With this change, your parsed result will look like this (no more $ keys):
{ PFA: { Entity: [ { attributes: { id: '123', action: 'add', date: '31-Jul-2009' }, ActiveStatus: [ 'Inactive' ] } ] } }
You can now insert the result object directly into MongoDB without any errors.
Solution 2: Post-Process the Parsed JSON to Rename $ Keys
If you can't modify the parser configuration (for example, if you need to keep the original structure elsewhere), you can recursively traverse the parsed object and rename all $ keys to something valid.
Add this helper function to your code:
function renameDollarKeys(obj) { if (Array.isArray(obj)) { return obj.map(item => renameDollarKeys(item)); } else if (typeof obj === 'object' && obj !== null) { const cleanedObj = {}; for (const key in obj) { // Replace $ with 'attributes' or any valid key name const newKey = key === '$' ? 'attributes' : key; cleanedObj[newKey] = renameDollarKeys(obj[key]); } return cleanedObj; } return obj; // Return primitive values as-is }
Then apply this function to your parsed result before inserting into MongoDB:
parser.parseString(data, (err, result) => { const cleanedResult = renameDollarKeys(result); // Fix all $ keys // Proceed with MongoDB insertion using cleanedResult MongoClient.connect(url, function(err, db) { if (err) throw err; var dbo = db.db("db"); dbo.collection("entity").insertOne(cleanedResult, function(err, res) { if (err) throw err; console.log("1 document inserted"); db.close(); }); }); });
Quick Note: Remove Unnecessary util.inspect Call
I noticed your code uses util.inspect to convert the result to a string, but you don't actually use this string for the MongoDB insertion. You can safely delete that line—result is already a JavaScript object ready for insertion once the $ keys are fixed.
Content of the question来源于stack exchange,提问作者Steve

