Problem in printing angle brackets using the xml-builder node module - javascript

I am creating an xml file using "xml-builder" node module. But when I tried to write angle brackets ("<" or ">"), I got characters like "<" and ">". The code is as follows:
let builder = require('xmlbuilder', { encoding: 'utf-8' });
let name = "ABC";
let xml = builder.create('Slides');
xml.ele('props',"Hello").up();
xml.ele('name',"<Hello> "+name+" </Hello>").up();
xml.end({ pretty: true });
console.log(xml.toString())
The output is as follows:
<Slides>
<props>Hello</props>
<name><Hello> ABC </Hello></name>
</Slides>
What should I do to get < or > printed instead of < or > ?

There is an npm module decode-html that will handle the same use case as your.
var decode = require('decode-html');
console.log(decode('<div class="hidden">NON&SENSE&apos;s</div>'));
// -> '<div class="hidden">NON&SENSE\'s</div>'

The problem is that is you are attempting to create a child element in an incorrect way, by passing some xml in the value field of xml.ele. The module is correctly escaping your angle brackets.
What you need to do is create another element named Hello and append it to the name element. You can do this by either chaining your .ele calls or using their return values.
Here is the correct code:
let builder = require('xmlbuilder', { encoding: 'utf-8' });
let name = "ABC";
let xml = builder.create('Slides');
xml.ele('props',"Hello");
xml.ele('name')
.ele("Hello", name);
xml.end({ pretty: true });
console.log(xml.toString())
Output:
<Slides>
<props>Hello</props>
<name>
<Hello>ABC</Hello>
</name>
</Slides>

Related

How to apply regular expression for Javascript

I am trying to get message log from Azure application Insight like this
az monitor app-insights --app [app id] --analystics-query [condition like specific message id]
Then I got a message like this
"message": [
"Receiving message: {"type":"CTL","traceId":"f0d11b3dbf27b8fc57ac0e40c4ed9e48","spanId":"a5508acb0926fb1a","id":{"global":"GLkELDUjcRpP4srUt9yngY","caller":null,"local":"GLkELDUisjnGrSK5wKybht"},"eventVersion":"format version","timeStamp":"2021-10-01T14:55:59.8168722+07:00","eventMetadata":{"deleteTimeStamp":null,"ttlSeconds":null,"isFcra":null,"isDppa":true,"isCCPA":true,"globalProductId":null,"globalSubProductId":null,"mbsiProductId":null},"eventBody":{"sys":"otel","msg":"Testing Centralized Event Publisher with App1 (using logback)","app":{"name":"otel","service":"postHouse","status":"status name","method":"POST","protocol":"HTTP","resp_time_ms":"250","status_code":"4"},}}"
] }
So that I would like to apply Regular Expression for this message to get only the message from {"type.....to "status_code":"4"},}} and also convert it to JSON format
I have code like this in my .js file
Then('extract json from {string}', function(message){
message = getVal(message, this);
const getmess = message.match(/{(.*)}/g);
const messJson = JSON.parse(getmess);
console.log(messJson);
})
But it doesn't work for me
SyntaxError: Unexpected token \ in JSON at position 1
How can I apply this in my code on Javascript? Thank you so much for your help
Try this. But keep in mind, that current regex is binded with provided program output syntax. If output will be different in wrapper structure, this regex might not work any more.
// Text from app
const STDOUT = `
"message": [ "Receiving message: {"type":"CTL","traceId":"f0d11b3dbf27b8fc57ac0e40c4ed9e48","spanId":"a5508acb0926fb1a","id":{"global":"GLkELDUjcRpP4srUt9yngY","caller":null,"local":"GLkELDUisjnGrSK5wKybht"},"eventVersion":"format version","timeStamp":"2021-10-01T14:55:59.8168722+07:00","eventMetadata":{"deleteTimeStamp":null,"ttlSeconds":null,"isFcra":null,"isDppa":true,"isCCPA":true,"globalProductId":null,"globalSubProductId":null,"mbsiProductId":null},"eventBody":{"sys":"otel","msg":"Testing Centralized Event Publisher with App1 (using logback)","app":{"name":"otel","service":"postHouse","status":"status name","method":"POST","protocol":"HTTP","resp_time_ms":"250","status_code":"4"},}}"
] }
`;
// Match JSON part string
let JSONstr = /.*\[\s*\"Receiving message:\s*(.*?)\s*\"\s*]\s*}\s*$/.exec(STDOUT)[1];
// Remove trailing comma(s)
JSONstr = JSONstr.replace(/^(.*\")([^\"]+)$/, (s, m1, m2) => `${m1}${m2.replace(/\,/, "")}`);
// Convert to object
const JSONobj = JSON.parse(JSONstr);
// Result
console.log(JSONobj);
Try this one:
/.*?({"type":.*?,"status_code":"\d+"\})/
When used in Javascript, the part covered by the parentheses counts as Group 1, i.e.,:
const messJson = JSON.parse(message.match(/.*?({"type":.*?,"status_code":"\d+"\})/)[1]);
Reference here: https://regexr.com/66mf2

Node file parsing by empty line not working

I have some data in a txt file in this format:
byr:1985
eyr:2021 iyr:2011 hgt:175cm pid:163069444 hcl:#18171d
eyr:2023
hcl:#cfa07d ecl:blu hgt:169cm pid:494407412 byr:1936
ecl:zzz
eyr:2036 hgt:109 hcl:#623a2f iyr:1997 byr:2029
cid:169 pid:170290956
hcl:#18171d ecl:oth
pid:266824158 hgt:168cm byr:1992 eyr:2021
I already have a function that parses the txt file line by line:
function parse_file_by_line(folder, file_name) {
// Read the input file line by line, creating an array of inputs.
const input_file = path.join(__dirname, folder, file_name);
return (input_array = fs.readFileSync(input_file).toString().split("\r\n"));
}
However, i want to parse on the blank lines. ( the empty spaces in the text file ). Someone suggested to split on "\n\n" Which i have tried but it ends up putting all the data into one big array element." I want to split it on the empty lines and the data between into one array element. For example, the first index would be "byr:1985 eyr:2021 iyr:2011 hgt:175cm pid:163069444 hcl:#18171d".
I want to provide a way to check file string. You could use JSON.stringify to check what kind of string your file have. By this way, you will find out what is your line ending.
const fs = require('fs')
const data = fs.readFileSync("./file.txt")
console.log(JSON.stringify(data.toString()));
In my mac, this is output.
"byr:1985\neyr:2021 iyr:2011 hgt:175cm pid:163069444 hcl:#18171d\n\neyr:2023\nhcl:#cfa07d ecl:blu hgt:169cm pid:494407412 byr:1936\n\necl:zzz\neyr:2036 hgt:109 hcl:#623a2f iyr:1997 byr:2029\ncid:169 pid:170290956\n\nhcl:#18171d ecl:oth\npid:266824158 hgt:168cm byr:1992 eyr:2021"
Use split("\r\n\r\n"). Windows has \r\n on each line ending and linux uses just \n.
You can use a stream approach which mean not reading all the file into memory. This is useful when working with large files. Following handles CRLF too:
const fs = require('fs');
const readline = require('readline');
async function processLineByLine() {
const fileStream = fs.createReadStream('input.txt');
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
// Note: we use the crlfDelay option to recognize all instances of CR LF
// ('\r\n') in input.txt as a single line break.
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
console.log(`Line from file: ${line}`);
}
}
processLineByLine();
For more info see this.
Now, you can customize the for-loop to detect empty line like this:
var lines = []
for await (const line of rl) {
// Each line in input.txt will be successively available here as `line`.
if (line === ''){
if (lines.length > 0)
process_chunk(lines);
lines = [] //empty the array and make it ready for next iteration
}
else
lines.push(line)
}
function process_chunk(lines) {
//now, you have an array of consequtive non empty lines here
}

Removing the last character from file stream in node.js (fs module)

Using node.js, I am trying to build an array of objects and write them to a file. To do this, I'm using the built in fs library.
After calling
var file = fs.createWriteStream('arrayOfObjects.json'); and file.write('[') I run several asynchronous functions to eventually append objects like this:
file.write(JSON.stringify(objectToAppend) + ',\n')
I can determine when all of the objects have stopped appending, and this is where I run file.write(']') and file.end(). My problem is that adding the last comma to the end of the last object causes the JSON to be invalid.
It is very difficult to determine where and when the last object is being created due to the asynchronous nature of the script, so I was wondering if there is a way to strip or remove characters from a file-stream. If so, I could do this before adding the last ']' character.
I could do this manually, but I was hoping to pipe this to another application. The only solution I've thought about is using the fs.truncate() function, however this doesn't seem to work for file streams, and neither file.length or file.length() will give me the length of the contents because it is not a string so it's difficult to determine how or where to truncate the file.
For now I have just been adding '{}]' to the end of the array to make it valid JSON, but this empty object may cause some problems later.
Also note: the array of objects I am writing in this stream is VERY large, so I would rather not end the stream and re-open the file.
I'd recommend to prepend the separator instead, so that you dynamically can adjust it after the first call:
file.write('[\n')
var sep = "";
forEach(function(objectToAppen) {
file.write(sep + JSON.stringify(objectToAppend))
if (!sep)
sep = ",\n";
});
Example using JSONStream:
var JSONStream = require('JSONStream');
var fs = require('fs');
var jsonwriter = JSONStream.stringify();
var file = fs.createWriteStream('arrayOfObjects.json');
// Pipe the JSON data to the file.
jsonwriter.pipe(file);
// Write your objects to the JSON stream.
jsonwriter.write({ foo : 'bar#1' });
jsonwriter.write({ foo : 'bar#2' });
jsonwriter.write({ foo : 'bar#3' });
jsonwriter.write({ foo : 'bar#4' });
// When you're done, end it.
jsonwriter.end();
Here's a snippet incorporating robertklep's answer. This converts from a pipe-separated file to json:
var fs = require('fs');
var readline = require('readline');
var JSONStream = require('JSONStream');
// Make sure we got a filename on the command line.
if (process.argv.length < 3) {
console.log('Usage: node ' + process.argv[1] + ' FILENAME');
process.exit(1);
}
var filename = process.argv[2];
var outputFilename = filename + '.json';
console.log("Converting psv to json. Please wait.");
var jsonwriter = JSONStream.stringify();
var outputFile = fs.createWriteStream(outputFilename);
jsonwriter.pipe(outputFile);
var rl = readline.createInterface({
input: fs.createReadStream(filename),
terminal: false
}).on('line', function(line) {
console.log('Line: ' + line);
if(!/ADDRESS_DETAIL_PID/.test(line))
{
var split = line.split('|');
var line_as_json = { "address_detail_pid": split[0], "flat_type": split[1], "flat_number": split[2], "level_type": split[3], "level_number": split[4], "number_first": split[5], "street_name": split[6], "street_type_code": split[7], "locality_name": split[8], "state_abbreviation": split[9], "postcode": split[10], "longitude": split[11], "latitude": split[12] };
jsonwriter.write(line_as_json);
}
}).on('close', () => {
jsonwriter.end();
});;
console.log('psv2json complete.');
The accepted answer is interesting (prepending the separator) but in my case I have found it easier to append the separator and remove the last character of the file, just as suggested in the question.
This is how you remove the last character of a file with Node.js :
import fs from 'fs'
async function removeLastCharacter(filename) {
const stat = await fs.promises.stat(filename)
const fileSize = stat.size
await fs.promises.truncate(filename, fileSize - 1)
}
explanation :
fs.promises.stat gives us some information about the file, we will use its size.
fs.promises.truncate remove from the file what is after a certain position
We use the position fileSize - 1 which is the last character.
Note :
Yes I know that we need to wait until the stream is closed, but this is ok because truncate and stat functions are very fast and doesn't depend on the file size, it doesn't have to read its content.

Grunt Task - Get Filename from path without extension

Is it possible to get the filename without the extension from the src filepath.
As an example, let's say the src file is my-file.png - located at images/my-file.png.
In my task I have this at the moment:
var processName = options.processName || function (name) { return name; };
var filename = processName(filepath);
When I reference filename for output it returns:
images/my-file.png
I want to only return the actual filename, without the path and without the extension:
my-file.png
How can I achieve this?
Might be pretty old but if someone else finds this SO., in reply for #user3143218 's comment :
slice(0, -4) will remove the last 4 characters from the name, so for the example my-file.png we will get my-file but for script.js we will get scrip. I suggest using a regex removing everything from the last dot.
You could use a regex like this:
var theFile = filename.match(/\/([^/]*)$/)[1];
var onlyName = theFile.substr(0, theFile.lastIndexOf('.')) || theFile;
That should give you my-file. The regex gives you the string after the last forward slash, and the next line removes everything after the last dot (and the dot).
Thanks to Andeersg's answer below I was able to pull this off. It might not be the best solution but it works. Final code is:
var processName = options.processName || function (name) { return name; };
var filename = processName(filepath);
var theFile = filename.match(/\/([^/]*)$/)[1];
var onlyName = theFile.slice(0, -4);
Now onlyName will return:
my-file

UltraEdit find and replace regular expression

I have the code bellow to find the regular expression after %hostname and it replaces all the text correrctly for #hostname.
How do I replicate this for %Location and #Location. I can't seem to get the replication working for more than one variable.
Thanks
var host= "%hostname =(.*)"; // Perl regular expression to find title string
UltraEdit.activeDocument.top();
// Turn on regular expressions
UltraEdit.activeDocument.findReplace.regExp = true;
// Find it
UltraEdit.activeDocument.findReplace.find(host);
// Load it into a selection
var host2= UltraEdit.activeDocument.selection;
// Javascript function 'match' will match the regex within the javascript engine
// so we can extract the actual title via array
t = host2.match(host);
savehost = t[1];
UltraEdit.activeDocument.top();
UltraEdit.activeDocument.findReplace.replaceAll=true;
UltraEdit.activeDocument.findReplace.matchCase=true;
UltraEdit.activeDocument.findReplace.replace("#hostname", savehost);
Here is the UltraEdit script for this task.
The array asVariables contains the names of the variables which can be extended by you with additional strings.
if (UltraEdit.document.length > 0) // Is any file opened?
{
// Define environment for this script.
UltraEdit.insertMode();
UltraEdit.columnModeOff();
// Define a constant array of variable names which can be extended
// or modified in script code at any time to support more variables.
var asVariables = [ "hostname" , "Location" ];
// Define once all find and replace options to make the
// script independent on internal defaults of UltraEdit.
UltraEdit.perlReOn();
UltraEdit.activeDocument.findReplace.mode=0;
UltraEdit.activeDocument.findReplace.matchCase=true;
UltraEdit.activeDocument.findReplace.matchWord=false;
UltraEdit.activeDocument.findReplace.searchDown=true;
if (typeof(UltraEdit.activeDocument.findReplace.searchInColumn) == "boolean")
{
UltraEdit.activeDocument.findReplace.searchInColumn=false;
}
UltraEdit.activeDocument.findReplace.preserveCase=false;
UltraEdit.activeDocument.findReplace.replaceAll=true;
UltraEdit.activeDocument.findReplace.replaceInAllOpen=false;
// Run the code in the loop on all variables defined in the array.
for (var nVariable = 0; nVariable < asVariables.length; nVariable++)
{
// Move caret to top of the active file.
UltraEdit.activeDocument.top();
// Perl regular expression to find %variable string and assigned data.
var sSearch = "%" + asVariables[nVariable] + " *?=.*$";
UltraEdit.activeDocument.findReplace.regExp=true;
// If the variable is not found in active file,
// continue immediately with next variable.
if(!UltraEdit.activeDocument.findReplace.find(sSearch)) continue;
// Get just the string after the first equal sign from selected string.
// The replace method of JavaScript String object never modifies the
// string value itself. It creates always a new string derived from
// the current string value with the replace applied.
var sData = UltraEdit.activeDocument.selection.replace(/^.*?=(.*)$/,"$1");
// Replace all occurrences of #variable by the found data in entire file.
UltraEdit.activeDocument.top();
UltraEdit.activeDocument.findReplace.regExp=false;
sSearch = "#" + asVariables[nVariable];
UltraEdit.activeDocument.findReplace.replace(sSearch,sData);
}
}

Categories