geotiff.js
geotiff.js copied to clipboard
getGDALMetadata error
Node.js 4.2.6. Got
/path/to/test/node_modules/geotiff/src/geotiffimage.js:628
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null
^
ReferenceError: XPathResult is not defined
at Object.GeoTIFFImage.getGDALMetadata (/path/to/test/node_modules/geotiff/src/geotiffimage.js:628:7)
at /home/mvtm/projects/radar/server/src/testgt.js:15:21
Right now, geotiff.js relies on the Browsers DOM capabilities to parse the GDAL metadata (which is included as XML). I'm hesitant to include a third-party library, as I want to keep the size of geotiff.js as small as possible.
A workaround is to use the xmldom and xpath libraries:
var xpath = require('xpath')
, dom = require('xmldom').DOMParser
function getGDALMetadata(image) {
var metadata = {};
if (!image.fileDirectory.GDAL_METADATA) {
return null;
}
var string = image.fileDirectory.GDAL_METADATA;
var doc = new dom().parseFromString(image.fileDirectory.GDAL_METADATA)
var nodes = xpath.select("//GDALMetadata/Item", doc)
for (var i=0; i < nodes.length; ++i) {
var node = nodes(i);
metadata[node.getAttribute("name")] = node.textContent;
}
return metadata;
}
I'll keep this issue open, as I'm still deciding on how to proceed.
Yep. But I used a different approach:
--- src/geotiffimage.js 2017-02-20 18:14:35.000000000 +0800
+++ new/geotiffimage.js 2017-02-20 19:26:52.000000000 +0800
@@ -793,11 +793,22 @@
var xmlDom = globals.parseXml(string.substring(0, string.length-1));
var result = xmlDom.evaluate(
"GDALMetadata/Item", xmlDom, null,
- XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null
+ globals.XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null
);
for (var i=0; i < result.snapshotLength; ++i) {
- var node = result.snapshotItem(i);
- metadata[node.getAttribute("name")] = node.textContent;
+ var node = result.snapshotItem(i),name=node.getAttribute("name"),sample=node.getAttribute("sample");
+ if (sample) {
+ sample=Number.parseInt(sample);
+ var data=metadata[name];
+ if (!data || !Array.isArray(data)) {
+ data=[];
+ metadata[name]=data;
+ }
+ data[sample]=node.textContent;
+ }
+ else {
+ metadata[name] = node.textContent;
+ }
}
return metadata;
},
diff -Naur src/globals.js new/globals.js
--- src/globals.js 2017-02-20 18:14:35.000000000 +0800
+++ new/globals.js 2017-02-20 19:15:55.000000000 +0800
@@ -230,13 +230,20 @@
}
var parseXml;
+var _xpathResult;
// node.js version
if (typeof window === "undefined") {
+ // requires xmldom and xpath module
+ var DOMParser = require('xmldom').DOMParser,
+ xpath = require('xpath');
parseXml = function(xmlStr) {
- // requires xmldom module
- var DOMParser = require('xmldom').DOMParser;
- return ( new DOMParser() ).parseFromString(xmlStr, "text/xml");
+ var ret=(new DOMParser()).parseFromString(xmlStr, "text/xml");
+ ret.evaluate=function(expr,context,resolver,type,result) {
+ return xpath.evaluate(expr,context,resolver,type,result);
+ };
+ return ret;
};
+ _xpathResult=xpath.XPathResult;
}
else if (typeof window.DOMParser !== "undefined") {
parseXml = function(xmlStr) {
@@ -252,6 +259,7 @@
};
}
+
module.exports = {
fieldTags: fieldTags,
fieldTagNames: fieldTagNames,
@@ -261,5 +269,6 @@
photometricInterpretations: photometricInterpretations,
geoKeys: geoKeys,
geoKeyNames: geoKeyNames,
- parseXml: parseXml
+ parseXml: parseXml,
+ XPathResult: typeof XPathResult==='undefined'?_xpathResult:XPathResult
};
Also this patch changes GDALMetadData. From my best knowledge in GeoTIFF GDALMetadat all Items bounded not only to item name, but also can be bound to certain sample. So I modified getGDALMetadata in that way that it return string value for Items without sample bounding and array of strings in other case
@constantinius , I believe this issue can be closed as fixed.