-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds function that inserts missing namespace into KML #5860
Conversation
Welcome to the Cesium community @nrivera-Novetta! Can you please send in a Contributor License Agreement (CLA) so that we can review and merge this pull request? I noticed that CHANGES.md has not been updated. If this change updates the public API in any way, fixes a bug, or makes any non-trivial update, please add a bullet point to I am a bot who helps you make Cesium awesome! Thanks again. |
Thanks for the pull request, @nrivera-Novetta! Do you work for Novetta and did you write this code for them? If so, we already have a CLA from Novetta that covers you. |
@nrivera-Novetta please add yourself to CONTRIBUTORS.md. |
@nrivera-Novetta please update CHANGES.md. |
@tfili can you review this? |
@@ -255,6 +255,23 @@ define([ | |||
return deferred.promise; | |||
} | |||
|
|||
function insertNamespaces(text) { | |||
var namespaceMap = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be cleaner to have the following then build the search strings in the loop.
var namespaceMap = {
xsi : 'http://www.w3.org/2001/XMLSchema-instance'
};
Source/DataSources/KmlDataSource.js
Outdated
var firstPart; | ||
var lastPart; | ||
|
||
for (var key in namespaceMap){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
XML doesn't allow for whitespace between <
and the tag name, so you could check for <xsi:
, so you don't inadvertantly match soemthing like <exsi:name>
. In the loop you could check for a bad file like this
var prefix = '<' + key + ':';
var declaration = 'xmlns:' + key + '=';
if(text.indexOf(prefix) !== -1 && text.indexOf(declaration) === -1) {
Source/DataSources/KmlDataSource.js
Outdated
|
||
for (var key in namespaceMap){ | ||
if(text.indexOf(key) !== -1 && text.indexOf(namespaceMap[key][0]) === -1) { | ||
firstPart = text.substr(0, text.indexOf('<kml') + 4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can find the index of <kml
once before the loop, then you can just append to the firstPart
as you iterate, then combine firstPart
and lastPart
after the loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You still only want to find <kml
once, but you may want to do it in the loop after we found a problem, so we don't search a potentially long string if we don't need to. So something like this
var firstPart;
var lastPart;
for (var key in namespaceMap){
...
if(text.indexOf(prefix) !== -1 && text.indexOf(declaration) === -1) {
if (!defined(firstPart)) {
// Search for <kml and set firstPart/lastPart
}
...
}
}
if (defined(firstPart)) {
text = firstPart + lastPart;
}
return text;
@tfili with regard to what you said about xml not allowing for a space between a < and a tag, there is a special case that is identical to the one in my test kml in which the 'xsi:' is an attribute rather than a tag. It seems that there are a bunch of kml's floating around with this same xsi attribute and without any xsi tags in the document. I'm going to change the code to account for this and for what you mentioned and put the PR back up. |
CHANGES.md
Outdated
@@ -18,6 +18,7 @@ Change Log | |||
* Fixed a 3D Tiles point cloud bug causing a stray point to appear at the center of the screen on certain hardware. [#5599](https://github.com/AnalyticalGraphicsInc/cesium/issues/5599) | |||
* Fixed removing multiple event listeners within event callbacks. [#5827](https://github.com/AnalyticalGraphicsInc/cesium/issues/5827) | |||
* Running `buildApps` now creates a built version of Sandcastle which uses the built version of Cesium for better performance. | |||
* Added function that inserts missing namespace declarations into KML files. [#5860](https://github.com/AnalyticalGraphicsInc/cesium/pull/5860) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1.38 Came out already. Needs to be updated for 1.39 which will be released Nov 1.
Source/DataSources/KmlDataSource.js
Outdated
|
||
for (var key in namespaceMap) { | ||
if (namespaceMap.hasOwnProperty(key)) { | ||
reg = RegExp('[<| ]' + key + ':'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[ ]
specifies a character group where it represents any of the characters in it. This one will match <xsi:
, xsi:
or |xsi:
. I think you were trying to use the OR syntax that you need in capture group (represented with ( )
). So it can either be [< ]
or (<| )
. I think just removing the |
from your code and going with the character group is the way to go as it doesn't have the overhead of capturing.
@tfili hey just wondering if you could take another look at this |
I'll take a look. @nrivera-Novetta, you need to add a comment when it is ready for another look or I won't be notified. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides the few small tweaks, this looks good.
Also, you don't have to close a PR to work on it. We won't merge it till all the tests pass and the comments have been addressed. Just comment when its ready.
Thanks again @nrivera-Novetta
Source/DataSources/KmlDataSource.js
Outdated
reg = RegExp('[< ]' + key + ':'); | ||
declaration = 'xmlns:' + key + '='; | ||
if (reg.test(text) && text.indexOf(declaration) === -1) { | ||
if (!firstPart) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be
if (!defined(firstPart)) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tfili do you mean this line should actually use 'defined'? or just check if it's defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
defined
is a function in Cesium. It does some extra checking to make sure a value is actually undefined
or null
. This should be used in cases like this.
The magic of javascript's implicit type conversion would cause !firstpart
to be true in other cases.
Source/DataSources/KmlDataSource.js
Outdated
} | ||
} | ||
|
||
if (firstPart) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use defined
here as well.
Thanks again @nrivera-Novetta! @tfili is this ready to merge? If so, please go ahead. |
This is based on an issue with some KML files having a 'xsi:schemaLocation' attribute in the Document tag without declaring the xsi namespace, causing the load to fail. The fix, so far, has been to edit the actual file manually, but many users/customers do not know how to. This function has a map with the key as the namespace as it would be used in the file ('xsi:') and a value as a 2 element array: element 0 contains the beginning of the namespace declaration ('xmlns:xsi=') and element 1 contains the urls for the declaration. This map can be updated with other namespaces that commonly cause the same issue. The new file - undeclaredNamespaces.kml includes this same issue and is used for the test.