1

I am trying to read the content of the XML file. Probably this is basic JS stuff, but I seem can't make it work.

I am using Chrome's experimental Native File System API to read folders in folder:

const opts = {type: 'open-directory'};
handle = await window.chooseFileSystemEntries(opts);
const entries = await handle.getEntries();
...

Then, later on in the code I am entering one of the folders from the main directory and trying to read the file in it. The file system strucure is like this:

Directory > subdirectory > file

and the second part of the code looks like this:

var subdirHandle = await handle.getDirectory(oneOfTheFolders);
var xmlFile = await subdirHandle.getFile('subject.xml');
xmlDoc = domParser.parseFromString(xmlFile, "text/xml");    
parsedNumber = document.evaluate(myXpathFce('nodeInXML'), xmlDoc, null, XPathResult.ANY_TYPE, null).iterateNext();
if(parsedNumber.childNodes.length >0){
...

I believe the issue is here var xmlFile = await subdirHandle.getFile('subject.xml'); with the file reading. If I loaded the file straight from the Input and used FileReader(), I was able to get the content and parse it, but with the 'directory' approach I am getting null (for the evaluated document) like this Uncaught (in promise) TypeError: Cannot read property 'childNodes' of null

Edit here is what I get in console for the xmlFile variable. I just need to get the content (XML in text format) from this

console log for xmlFile variable

koubin
  • 579
  • 5
  • 9
  • 30
  • Can you post the contents of the subject.xml file so we can see why the xml has an invalid structure? – Wezelkrozum May 30 '20 at 22:23
  • Just to get you in the right direction in the mean time. The myXpathFce('nodeInXML') function returns a XPath that cannot be found in the XML document. – Wezelkrozum May 30 '20 at 22:31
  • The xpath was tested and works well (if the xml is loaded standard way through input). The xpath goes like this (namespaces there): `//*[local-name()='name'][contains(., 'Comments')]/following-sibling::*[local-name()='data']` and the xml part: `Comments123` – koubin May 31 '20 at 06:54

2 Answers2

2

I noticed you're saving the File object in the xmlFile variable and passing it directly into the parseFromString method.

You cannot parse a document object from a File object directly. You should first read the string from the File object using a FileReader. You can read the string from a File object with the await keyword using the readFileAsync function below:

function readFileAsync(file) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    reader.onload = () => {
      resolve(reader.result);
    };
    reader.onerror = reject;
    reader.readAsText(file);
  })
}

var file = await handle.getFile();
var text = await readFileAsync(file);
var xmlDoc = domParser.parseFromString(text, "text/xml");
Wezelkrozum
  • 831
  • 5
  • 15
  • thanks for answer. As mentioned, I was testing FileReader with no luck. Seems like the file has different format than when loaded straight from input. Your code returns this: `Uncaught (in promise) TypeError: Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'.` – koubin May 31 '20 at 11:52
  • That's strange, I can read my xml file using the following code: https://cdpn.io/wesselkroos/debug/rNOXKNe Do you still get the same error there? – Wezelkrozum May 31 '20 at 11:56
  • Tried your code and I get just the name of the folders or file. In my code that works too, what I am not able to do is to read the content of that file which is in subirectory in this case. Please see the Edited question - at the end. – koubin May 31 '20 at 14:10
  • @koubin Ah, there are click event listeners on the name of the file/folder that are displayed. You should be able to click on the file that you want to open, then it will read the file and log the parsedNumber to the console. – Wezelkrozum May 31 '20 at 14:16
  • Thanks, I realized it when I took a look at your code :-) It works well in that case, but still when I try subfolder and specific file inside, it throws mentioned error. Could you try to modifiy your example so when user cliks "read directory" button, it will go for example to the first found subdirectory and there it will take specific file "subject.xml". I mean this part of my code which may cause the issue: `var subdirHandle = await handle.getDirectory(adresar); var xmlSoubor = await subdirHandle.getFile('subject.xml');` – koubin May 31 '20 at 14:46
  • if I use `const entries = await subdirHandle.getEntries();`, then go through all and find file name `subject.xml` and then I use `var xmlFile = await entry.getFile();` it works. So I assume the entry (handle) has to be the file, not parenting directory. I would still like to find some shortcut like `subdirHandle.getFile('subject.xml');` – koubin May 31 '20 at 20:20
1

For obtaining the contents of a FileSystemFileHandle, call getFile(), which returns a File object, which contains a blob. To get the data from the blob, call one of its methods (slice(), stream(), text(), arrayBuffer()).

DenverCoder9
  • 2,024
  • 11
  • 32