How to manipulate a xml file and save it to disk? - node.js

I have two xml files with exactly same structure. The only difference is the inner text of the tags.
I want to replace the value in the first file with the corresponding value in the second file.
I have tried using the xml2json but the problem is it removed all the comments which I need in the final output.
So currently I am using xmldom.
I am able to manipulate the text but the changes are lost when I try to save the file to the disk.
var DOMParser = require("xmldom").DOMParser;
var serializer = new (require('xmldom')).XMLSerializer;
var fs = require('fs');
let firstXML = `<root>
<!--This is just a comment-->
<string name="one">SOMETHING</string>
</root>`
let secondXML = `<root>
<string name="one">ELSE</string>
</root>`
var firstDoc = new DOMParser().parseFromString(firstXML, "text/xml");
var secondDoc = new DOMParser().parseFromString(secondXML, "text/xml");
let elementsFirst = firstDoc.getElementsByTagName("string");
let elementsSecond = secondDoc.getElementsByTagName("string");
for(let i = 0; i < elementsFirst.length; ++i) {
let el = elementsFirst[i];
let name = el.getAttribute("name");
for(let j = 0; j < elementsSecond.length; ++j) {
if(name = elementsSecond[j].getAttribute("name")) {
el.firstChild.nodeValue = elementsSecond[j].firstChild.nodeValue;
break;
}
}
}
fs.writeFileSync("output.xml", serializer.serializeToString(firstDocs));
//Required output
`<root>
<!--This is just a comment-->
<string name="one">ELSE</string>
</root>`

Please don't ask me why, but if you replace this line
el.firstChild.nodeValue = elementsSecond[j].firstChild.nodeValue;
with this one
el.firstChild.data = elementsSecond[j].firstChild.nodeValue;
it will work as expected.
P.S. You have a typo in your if statement, you need ===, a single = will usually return true
Update: after finding the solution - I found out that it is duplicate of this one

Related

NodeJS TypeError: Cannot read properties of undefined (reading '0')

I get the enemyCards from the frontend and it is an array, with 990 x 7 poker cards.
The sortCardOrder function just take the cards in order so i can search in my datas.
This is my NodeJS code:
import fs from 'fs';
import G from 'generatorics';
export default function findEnemyStrongest(enemyCards) {
let eCombination = enemyCards.enemyCards;
let result = [];
for(const comb of eCombination){
result.push(findStrongest(comb));
}
console.log(result);
}
function createCombinations(enemyC){
let combine = enemyC;
let onlyName = [];
let allCombinations = [];
for (let card of combine){
onlyName.push(card.name);
}
for (let comb of G.combination(onlyName, 5)){
allCombinations.push(comb.slice());
}
return allCombinations;
}
function findStrongest(combi){
let rawdata = fs.readFileSync('data.json');
let strenghtOrder = JSON.parse(rawdata);
let combinations = createCombinations(combi);
let combinationsName = [];
let ordered = "";
let result = [];
for(let combination of combinations){
let nameString = "";
let colors = {'C': 0, 'S': 0, 'H':0, 'D':0};
for(let card of combination){
nameString += card[0];
colors[card[1]]+=1
}
ordered = sortCardOrder(nameString, colors);
combinationsName.push(ordered);
console.log(combinationsName)
result.push(strenghtOrder.cardStrenght[ordered]);
}
return Math.min(...result);
}
function sortCardOrder(string, colors){
}
Can anyone know what is the problem?
We can infer this line is causing the error:
nameString += card[0];
It is requesting the 0 property of the card variable, but card is undefined. Card gets its value from combination. Print out combination to see if it has undefined values.
...
for(let combination of combinations){
console.log(combination)
...
Combination gets it value from combinations, which comes from comb. Print out the values of comb.
...
for (let comb of G.combination(onlyName, 5)){
console.log(comb)
...
Keep going backwards until you find the source of the 'undefined' value. Without seeing the original source data (from G), stepping through the code is the only way to find the error source.

What is the right way to use xpath on nodejs + xpath-Module if you search in subnodes?

I use XMLDOM + XPath to find XMLs nodes in this script:
var DOMParser = require("xmldom").DOMParser;
var xpath = require("xpath");
let data = `<start>
<b1 id="111"><c1 id="333">ccc</c1></b1>
<b1 id="222">bbb</b1>
</start>`;
let doc = new DOMParser().parseFromString(data);
let nodes = xpath.select("//b1", doc);
// let doc2 = new DOMParser().parseFromString(nodes[0].toString());
let doc2 = nodes[0];
console.log("doc2.toString: ", doc2.toString());
let nodes2 = xpath.select("b1", doc2);
console.log("nodes found by xpath 'b1': ", nodes2.toString());
if (nodes2.length > 0) {
console.log("id = " + nodes2[0].getAttribute("id"));
}
nodes2 = xpath.select("b1/c1", doc2);
console.log("nodes found by xpath 'b1/c1': ", nodes2.toString());
if (nodes2.length > 0) {
console.log("id = " + nodes2[0].getAttribute("id"));
}
nodes2 = xpath.select("c1", doc2);
console.log("nodes found by xpath 'c1': ", nodes2.toString());
if (nodes2.length > 0) {
console.log("id = " + nodes2[0].getAttribute("id"));
}
I want make a list of <b1> nodes and then get the id-value of the node.
The XPath pattern b1/c1 don't work but the c1 does.
If I change from search in a subnode
let doc2 = nodes[0];
to search in complete XML Document
let doc2 = new DOMParser().parseFromString(nodes[0].toString());
the b1/c1 pattern work!
Why b1/c1 don't work in case one?
Try:
echo "<b1 id=\"111\"><c1 id=\"333\">ccc</c1></b1>" | xmllint --xpath b1/c1 -
find:
<c1 id="333">ccc</c1>
On a plain XML the xpath pattern work fine, why not on subnodes from XMLDOM?
Or try in:
https://www.freeformatter.com/xpath-tester.html#ad-output
I want make a list of nodes and then get the id-value of the node.
So, that is to say, you want to make a list of the id attribute values?
var DOMParser = require("xmldom").DOMParser;
var xpath = require("xpath");
let data = `<start>
<b1 id="111"><c1 id="333">ccc</c1></b1>
<b1 id="222">bbb</b1>
</start>`
let doc = new DOMParser().parseFromString(data);
let ids = xpath.select("//b1/#id", doc).map(attr => attr.value);
// -> ["333", "222"]
An alternative to the last line is this:
let ids = xpath.select("//b1", doc).map(node => node.getAttribute('id'));
// -> ["333", "222"]

Define the first line of file as a header to use in the rest of the file NODEJS

I'v to read a file into a array multidimensional, so I can manipulate it. I'm doing this with readline, but how could I get the first line and define it as the header and skip it from the rest. Follows mycode:
const fields = []
const fileData = []
rl.on('line', (line)=>{
const rowData = line.split(delimiter)
for (let index = 0; index < header.length; index++) {
fields[header[index]] = rowData[index]
}
fileData.push(fields)
})
The array header is what I need, but I can't think how. I tried something inside the event "on", like:
const header = []
if(!header){
header = line.split(delimiter)
}
But, didn't work :S
Some help, please?
I get it!
I had justo to change const header to let header.
Thanks!

Write to json file in increments of 50

I am currently looping through a json object with the purpose of writing certain key value pairs to a new json file. I can write all the elements in the newVideos array to a new file. However, I need to get the first 50 and write it to a file, then the next 50 and so on... Can anyone point me in the right direction?
async function GetVideos(videoData) {
var videos = videoData.videos;
var newVideos = [];
for (var i = 0; i < videos.length; i++) {
var o = videos[i];
newVideos[i] = {
ID: o.ID,
Videos: o.Videos
};
}
}

XPages - using POI 4 XPages and it errors on $ symbol exporting to Word/PDF

I am using the splendid POI4Xpages add-on for my Xpage. It does very well mapping the web page to the Word or PDF, but I have noticed it bombs when there is a dollar sign ($) within any of the fields on the Xpage/Notes document.
Right now, my workaround for users is to substitute USD in place of the $ symbol, but my users and I would like it to handle the $.
I enclosed the error dump below.
Suggestions for where to begin (and end) are much appreciated. Thank you in advance.
POI 4 XPages -> ERROR
--------------------------------------------------------------
Error : Error during Documentgeneration
POI LIB : 1.2.6.201312211419
StackTrace:
java.lang.IllegalArgumentException: Illegal group reference
at java.util.regex.Matcher.appendReplacement(Matcher.java:724)
at java.util.regex.Matcher.replaceAll(Matcher.java:824)
at java.lang.String.replaceAll(String.java:1591)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processBookmarks2Run(DocumentProcessor.java:129)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processBookmarks 2Paragraph(DocumentProcessor.java:118)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processBookmarks 2Table(DocumentProcessor.java:110)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processBookmarks 2Document(DocumentProcessor.java:84)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.processDocument( DocumentProcessor.java:193)
at biz.webgate.dominoext.poi.component.kernel.DocumentProcessor.generateNewFile( DocumentProcessor.java:143)
at biz.webgate.dominoext.poi.component.containers.UIDocument.processAjaxRequest( UIDocument.java:208)
at biz.webgate.dominoext.poi.component.actions.DocumentGenerationServerAction.in voke(DocumentGenerationServerAction.java:48)
at com.ibm.xsp.application.ActionListenerImpl.processAction(ActionListenerImpl.j ava:60)
at javax.faces.component.UICommand.broadcast(UICommand.java:324)
at com.ibm.xsp.component.UIEventHandler.broadcast(UIEventHandler.java:366)
at com.ibm.xsp.component.UIDataPanelBase.broadcast(UIDataPanelBase.java:400)
at com.ibm.xsp.extlib.component.layout.UIVarPublisherBase.broadcast(UIVarPublish erBase.java:185)
at com.ibm.xsp.component.UIViewRootEx.broadcast(UIViewRootEx.java:1535)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:307)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:428)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase .java:94)
at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:210)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:96)
at com.ibm.xsp.controller.FacesControllerImpl.execute(FacesControllerImpl.java:2 56)
at com.ibm.xsp.webapp.FacesServlet.serviceView(FacesServlet.java:228)
at com.ibm.xsp.webapp.FacesServletEx.serviceView(FacesServletEx.java:157)
at com.ibm.xsp.webapp.FacesServlet.service(FacesServlet.java:160)
at com.ibm.xsp.webapp.FacesServletEx.service(FacesServletEx.java:138)
at com.ibm.xsp.webapp.DesignerFacesServlet.service(DesignerFacesServlet.java:103 )
at com.ibm.designer.runtime.domino.adapter.ComponentModule.invokeServlet(Compone ntModule.java:576)
at com.ibm.domino.xsp.module.nsf.NSFComponentModule.invokeServlet(NSFComponentMo dule.java:1335)
at com.ibm.designer.runtime.domino.adapter.ComponentModule$AdapterInvoker.invoke Servlet(ComponentModule.java:853)
at com.ibm.designer.runtime.domino.adapter.ComponentModule$ServletInvoker.doServ ice(ComponentModule.java:796)
at com.ibm.designer.runtime.domino.adapter.ComponentModule.doService(ComponentMo dule.java:565)
at com.ibm.domino.xsp.module.nsf.NSFComponentModule.doService(NSFComponentModule .java:1319)
at com.ibm.domino.xsp.module.nsf.NSFService.doServiceInternal(NSFService.java:66 2)
at com.ibm.domino.xsp.module.nsf.NSFService.doService(NSFService.java:482)
at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.doService(LCDEnvironme nt.java:357)
at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.service(LCDEnvironment .java:313)
at com.ibm.domino.xsp.bridge.http.engine.XspCmdManager.service(XspCmdManager.jav a:272)
We had this same issue and basically did a hack like below to prefix a $ if we found a decimal. Hope this helps out.
function process(xwpfdocument){
try{
// Get POI Document
var x = xwpfdocument;
var tables:java.util.Iterator = x.getTablesIterator();
while(tables.hasNext()){
var t = tables.next();
var numRows = t.getNumberOfRows();
// Loop Through All Rows
if(numRows>0){
for(var row=0; row<numRows; row++){
var cellList:java.util.List = t.getRow(row).getTableCells();
var numCells = cellList.size();
// Loop through all Cells
for(var cell=0; cell<numCells; cell++){
var c = cellList.get(cell);
var paragraphs:java.util.List = c.getParagraphs();
// Loop through all Paragraphs
for(var para=0; para<paragraphs.size();para++){
var p = paragraphs.get(para);
var runs:java.util.List = p.getRuns();
// Loop through all Runs
for(var r=0;r<runs.size();r++){
var run = runs.get(r);
var txt=run.getText(0);
if(txt.indexOf("<NL>")>-1){
var newRun = p.createRun();
var newTxt = txt.split("<NL>");
for(var n=0; n<newTxt.length; n++){
// Add New Runs with Breaks
var prefix = "";
if(newTxt[n].indexOf(".")>-1){
prefix = "$";
}
newRun.setText(#Text(prefix+newTxt[n]));
newRun.addBreak();
}
//Delete old run
//p.removeRun(0);
} else { //added for cases with only one account
var newRun = p.createRun();
var prefix = "";
if(txt.indexOf("%")>-1) { //added so SS002, SS003, and SS004 keep the %, added from the Letter.getBookmarkAPR function, rather than prepending a $
//nothing required
} else if(txt.indexOf(".")>-1){
prefix = "$";
}
newRun.setText(#Text(prefix+txt));
}
//Delete old run
p.removeRun(0);
}
}
}
}
}
}
} catch(e){
// Write to Log
system.out.println(e.getLocalizedMessage());
}
//Done
return;
}
Christian Güdemann posted a new build that addressed the $ character in the middle of a text field issue.
http://www.webgate.biz/ftp/openntf/POI4XPages/snapshot/biz.webgate.dominoext.poi-1.3.0-SNAPSHOT.zip
Btw there is a mailinglist in place to be informed about development builds:
http://mm.wgcdev.ch/mailman/listinfo
Thank you for your help, Dwain and Christian!

Resources