geotiff.js icon indicating copy to clipboard operation
geotiff.js copied to clipboard

getGDALMetadata error

Open mvtm-dn opened this issue 8 years ago • 3 comments
trafficstars

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

mvtm-dn avatar Feb 20 '17 08:02 mvtm-dn

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.

constantinius avatar Feb 20 '17 09:02 constantinius

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

mvtm-dn avatar Feb 20 '17 11:02 mvtm-dn

@constantinius , I believe this issue can be closed as fixed.

DanielJDufour avatar Oct 08 '22 15:10 DanielJDufour