Looking for assistance with an error I'm getting when attempting to get a nested node value in an XML file using XmlService and Google's AppScript. The node name is "asciiformat" and its position in the XML file is according to below (this is a simplified version; find full XML structure below AppScript code):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<entry>
<tes:ftpjob xmlns:tes="http://www.software.com">
<tes:asciiformat>N</tes:asciiformat>
Here's the error from AppScript:
TypeError: ftpJobInfo.getChildren is not a function
doGet @ Code.gs:17
Here's the code:
function doGet(e) {
let fileID = '1qHbA97eVaJtPWU3g_f9dEtwg-rlvkpc2';
url = DriveApp.getFileById(fileID).getBlob().getDataAsString();
let document = XmlService.parse(url);
let root = document.getRootElement();
let ns = root.getNamespace();
let entries = root.getChildren("entry", ns);
let entry, ftpJobInfo, ftpJobInfoDetails;
let id, title, asciiFormat;
for (let counter = 0; counter < entries.length; counter++) {
entry = entries[counter];
ftpJobInfo = entry.getContent(8);
ftpJobInfoDetails = ftpJobInfo.getChildren('tes:ftpjob');
asciiFormat = ftpJobInfoDetails.getContent(0).getValue();
Logger.log("prayer hands");
}
}
Here's the full XML file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<title>tes-6.5/tes:FTPJob.getList</title>
<category term="0" scheme="row" label=""/>
<category term="0" scheme="level" label=""/>
<category term="111111111111111111111111" scheme="securitypolicy" label=""/>
<category term="000000000000000000000000" scheme="customsecuritypolicy" label=""/>
<generator uri="http://www.software.com">TES</generator>
<modified>2022-08-04T15:41:11.027-06:00</modified>
<entry>
<id>9966</id>
<title>01 PMI SFTP</title>
<category term="0" scheme="row" label=""/>
<category term="0" scheme="level" label=""/>
<category term="111111111111111111111111" scheme="securitypolicy" label=""/>
<category term="000000000000000000000000" scheme="customsecuritypolicy" label=""/>
<source>com.software.FTPJobView</source>
<tes:ftpjob xmlns:tes="http://www.software.com">
<tes:asciiformat>N</tes:asciiformat>
<tes:ftphost>1.1.1.1:722</tes:ftphost>
<tes:filename>*.txt</tes:filename>
<tes:ftpoperation>2</tes:ftpoperation>
<tes:ftpprotocol>sftp</tes:ftpprotocol>
<tes:ftpuserid>25</tes:ftpuserid>
<tes:localpath>\\localpath</tes:localpath>
<tes:newfilename/>
<tes:replacefiles>N</tes:replacefiles>
<tes:userpasswordauthentication>Y</tes:userpasswordauthentication>
<tes:id>9966</tes:id><tes:typename>FTPJOB</tes:typename>
<tes:name>01 PMI SFTP</tes:name><tes:parentname>\location\location\location</tes:parentname>
<tes:active>Y</tes:active>
<tes:ownerid>16</tes:ownerid>
<tes:agentid>65</tes:agentid>
<tes:command>\\location</tes:command>
<tes:createtime>2012-08-08T11:05:27-0600</tes:createtime>
<tes:dependencylogic>1</tes:dependencylogic>
<tes:fullpath>\location\location\location</tes:fullpath>
<tes:lastchangetime>2019-07-19T17:27:42-0600</tes:lastchangetime>
<tes:runuserid>25</tes:runuserid>
</tes:ftpjob>
</entry>
</feed>
In your situation, the structure of XML data has already been known. When this situation is used, how about the following modification?
let document = XmlService.parse(url);
let root = document.getRootElement();
let ns = root.getNamespace();
let entries = root.getChildren("entry", ns);
let entry, ftpJobInfo, ftpJobInfoDetails;
let id, title, asciiFormat;
for (let counter = 0; counter < entries.length; counter++) {
entry = entries[counter];
ftpJobInfo = entry.getContent(8);
ftpJobInfoDetails = ftpJobInfo.getChildren('tes:ftpjob');
asciiFormat = ftpJobInfoDetails.getContent(0).getValue();
Logger.log("prayer hands");
}
const search = "asciiformat"; // This is from your question.
const root = XmlService.parse(url).getRootElement();
const ns = XmlService.getNamespace("tes", "http://www.software.com");
const value = root.getChild("entry", root.getNamespace()).getChild("ftpjob", ns).getChild(search, ns).getValue();
console.log(value) // N is returned.
url
is your showing XML data, when you run this modified script, you can see the value of N
in the log.In your showing script, I think that ftpJobInfo = entry.getContent(8);
has no value. By this, I think that this might be the reason for your issue. And, from your showing XML data, the tag of entry
is only one. So, in this case, I thought that getChildren
is not required to be used. And, from your XML data, it seems that the namespace of ftpjob
is tes
. This can be used for retrieving the tag of asciiformat
. So, I proposed the above modification.
As another direction, when this benchmark is considered, I thought that the following sample script might be able to be also used.
const res = url.match(/<tes:asciiformat>(.+)<\/tes:asciiformat>/);
console.log(res && res[1]); // N is returned.