read-excel-file
Version:
Read `.xlsx` files in a web browser or in Node.js
88 lines (87 loc) • 4.01 kB
JavaScript
/**
* Returns sheet file paths.
* Seems that the correct place to look for the `sheetId` -> `filename` mapping
* is `xl/_rels/workbook.xml.rels` file.
* https://github.com/tidyverse/readxl/issues/104
* @param {string} content — `xl/_rels/workbook.xml.rels` file contents.
* @param {function} parseXml — SAX XML parser.
* @return {object} — An object of shape `{ sheets: Record<string, string>, sharedStrings: string?, styles: string? }`
*/
export default function parseFilePaths(content, parseXml) {
// There're two standards of `.xlsx` files:
// * So-called "transitional", that emerged originally in 2006 and debuted widely with Microsoft Office 2007.
// * So-called "strict", that emerged in 2008 with the publication of the ISO/IEC 29500 specification.
//
// "Transitional" standard was released in 2007 and includes legacy elements, old namespaces,
// and compatibility features to support conversions from 1990s binary format `.xls`.
// This remains Excel's default save format.
//
// "Strict" standard was introduced conceptually in 2008, but fully realized with modern namespaces
// and no legacy tags (like VML or old drawing quirks) later on. Microsoft added reading support
// in Excel 2010 and the ability to save Strict files starting in Excel 2013.
//
var RELATIONSHIPS_BASE_URL_TRANSITIONAL_STANDARD = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/';
var RELATIONSHIPS_BASE_URL_STRICT_STANDARD = 'http://purl.oclc.org/ooxml/officeDocument/relationships/';
// Example:
// <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
// ...
// <Relationship
// Id="rId3"
// Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
// Target="worksheets/sheet1.xml"/>
// </Relationships>
var state = createInitialState();
return parseXml(content, state, onOpenTag, null, null).then(function () {
return getResultFromState(state);
});
function createInitialState() {
return {
sheets: {},
sharedStrings: undefined,
styles: undefined
};
}
function getResultFromState(state) {
return state;
}
function onOpenTag(tagName, attributes, state) {
if (tagName === 'Relationship') {
addFilePathForRelation(state, attributes.Id, attributes.Type, attributes.Target);
}
}
function addFilePathForRelation(state, id, type, target) {
switch (type) {
case RELATIONSHIPS_BASE_URL_TRANSITIONAL_STANDARD + 'styles':
case RELATIONSHIPS_BASE_URL_STRICT_STANDARD + 'styles':
state.styles = getFilePathFromRelationTarget(target);
break;
case RELATIONSHIPS_BASE_URL_TRANSITIONAL_STANDARD + 'sharedStrings':
case RELATIONSHIPS_BASE_URL_STRICT_STANDARD + 'sharedStrings':
state.sharedStrings = getFilePathFromRelationTarget(target);
break;
case RELATIONSHIPS_BASE_URL_TRANSITIONAL_STANDARD + 'worksheet':
case RELATIONSHIPS_BASE_URL_STRICT_STANDARD + 'worksheet':
state.sheets[id] = getFilePathFromRelationTarget(target);
break;
}
}
function getFilePathFromRelationTarget(path) {
// Normally, `path` is a relative path inside the ZIP archive,
// like "worksheets/sheet1.xml", or "sharedStrings.xml", or "styles.xml".
// There has been one weird case when file path was an absolute path,
// like "/xl/worksheets/sheet1.xml" (specifically for sheets):
// https://github.com/catamphetamine/read-excel-file/pull/95
// Other libraries (like `xlsx`) and software (like Google Docs)
// seem to support such absolute file paths, so this library does too.
if (path[0] === '/') {
return path.slice('/'.length);
}
// // Seems like a path could also be a URL.
// // http://officeopenxml.com/anatomyofOOXML-xlsx.php
// if (/^[a-z]+\:\/\//.test(path)) {
// return path
// }
return 'xl/' + path;
}
}
//# sourceMappingURL=parseFilePaths.js.map