---
title: "期待意想不到的惊喜——Altova MissionKit 解决了格式转换难题"
date: "2013-01-10"
tags: 
  - "data-mapping"
  - "mapforce"
  - "missionkit"
  - "xmlspy"
description: 了解如何使用 Altova MissionKit，特别是 MapForce 和 XMLSpy，来诊断和解决数据映射问题，包括处理 GPS 坐标中的科学计数法。
---
Status: #blog

Tags:  #data-mapping #mapforce #missionkit #xmlspy

Categories: [Altova](/blog/zh/category/altova.md) 
# 期待意想不到的惊喜——Altova MissionKit 解决了格式转换难题

每次从外部来源接收数据时，都存在一种可能性，即数据可能不会以您期望的格式到达。这可能需要特殊的处理方式，但为了构建一个在实际应用中稳定可靠的数据映射和转换解决方案，即使是罕见的情况也需要考虑。

我们处理了大量的 .gpx 文件，每个文件包含数百个坐标。我们使用了在博客文章《[将 Web 服务作为查找表来优化 GPS 数据](https://www.altova.com/blog/2012/06/web-service-as-look-up-table-to-refine.html)》中介绍的 MapForce 映射工具。然后有一天，我们处理了一个新的文件时，遇到了以下错误，导致映射失败：

![在映射 Web 服务数据时出现的错误信息](https://lh6.ggpht.com/-8eeq0Sre-5o/UO2IztvOjdI/AAAAAAAAA6k/LhnY21vwyK8/clip_image001%25255B3%25255D.png?imgmax=800 "Error message during mapping of Web services data")

我们利用 [Altova MissionKit](https://www.altova.com/zh/missionkit.html) 提供的功能，结合了 [MapForce](https://www.altova.com/zh/mapforce.html) 和 [XMLSpy](https://www.altova.com/zh/xmlspy.html) 的特性，迅速诊断出了问题，并开发出一种解决方案，该方案也可以在未来的数据映射项目中重复使用。

<!--more-->

我们首先怀疑是输入数据有问题，所以我们用XMLSpy打开了该文件，结果该文件通过了格式正确性检查 [XML 验证](https://www.altova.com/zh/xmlspy/xml-validator.html) 测试。 幸运的是，每个数据点都有一个唯一的时戳，所以我们搜索了23:06:22这个时间戳，这是最后一次成功处理的GPS坐标的时间。 这个时间戳在输入文件的第1772行出现了一次。

在后续的数据中，我们没有发现任何明显错误。我们只是注释掉了下一个数据点，然后保存文件，以便重新处理数据映射

![注释 XML 文件中的一部分内容](https://lh3.ggpht.com/-UeqIOKWBDp8/UO2I0JP9HII/AAAAAAAAA6s/3GC5RMqRXAA/clip_image002%25255B3%25255D.png?imgmax=800 "Commenting out a portion of an XML file")

这次的映射过程成功完成了：

![Altova MapForce 消息窗口](https://lh5.ggpht.com/-K0ySupBx4ZM/UO2I1KQnttI/AAAAAAAAA60/BpfcM6B9RY0/clip_image003%25255B3%25255D.png?imgmax=800 "Altova MapForce Messages window")

现在，我们对该Web服务返回的数据产生了怀疑。 即使是美国地质调查局的国家地理空间项目运行了这个Web服务，但也许其底层数据库中包含无效的数据。

我们插入了一个简单的.csv文件作为备用输出，并将每个坐标集合的标高结果映射到该文件，以便检查Web服务的输出结果。

![使用一个简单的文本文件来收集来自网络服务的数据](https://lh6.ggpht.com/-KAc2wKzVjes/UO2I1myy8oI/AAAAAAAAA68/aSoxAnJ7Zh8/clip_image004%25255B3%25255D.png?imgmax=800 "Using a simple text file to capture data from a Web service")

在输出文件 "diagnostic.csv" 的某一行中，包含与之前错误消息中提到的相同值，该值被引号括起来

![Web 服务的示例输出](https://lh3.ggpht.com/-_8RAIySmcXg/UO2I2ssrbNI/AAAAAAAAA7E/qtT4BbsKONo/clip_image005%25255B3%25255D.png?imgmax=800 "Sample output from the Web service")

这是科学计数法！Web服务返回了一个以[科学计数法](http://en.wikipedia.org/wiki/Scientific_notation)格式表示的数字！我们数据映射中的一个功能，用于处理Web服务的结果，需要十进制输入。

**数据类型转换**

一种策略可能是编写一个函数，该函数能够识别 Web 服务返回的结果为科学计数法，并显式地计算其数值。MapForce 的错误消息“将 '-1.24202767892712E-06' 转换为 **十进制** 失败”表明可能存在一个更简单的解决方案。

现在是思考数据类型的好时机。我们在映射中使用的Web服务组件明确表明它返回的是文本字符串。当映射将一个字符串作为输入连接到数学公式时，MapForce会自动执行从字符串到十进制数的类型转换。在大多数情况下，这让开发人员无需过多考虑显式的类型转换，因为数据在不同格式之间传输时会自动处理。在我们的映射中，MapForce成功地将字符串转换为十进制数178次，直到遇到以科学计数法表示的数值。

科学计数法通常用于表示那些过大或过小的数字，以方便记录，而无法直接用十进制形式表示。在MapForce中，十进制数据类型并不指定数字的大小或值。相反，它识别的是XML中的十进制类型，即由数字序列组成，并以点号作为小数点分隔符的字符序列。

在XML中，以及在MapForce中，双精度数据类型支持科学计数法。我们可以将科学计数法表示的数据显式地转换为双精度数据类型，然后再对结果进行四舍五入。

这个解决方案易于测试，只需使用简单的映射关系，输入和输出都使用文本文件。我们在四舍五入函数之前插入了一个简单的变量，并将它的数据类型设置为双精度浮点数。在我们的第一个测试中，我们使用了从美国地质调查局（USGS）网站获取的数据作为输入，这样就可以在不重复调用网站服务的情况下，对相同的数据进行处理。这个映射关系也让我们能够轻松地使用新的输入数据来构建更多的测试用例。

![在 MapForce 中为变量指定数据类型](https://lh5.ggpht.com/-hosv1fkHlMw/UO2I2yvIsVI/AAAAAAAAA7M/-jMNaESV_rA/clip_image006%25255B3%25255D.png?imgmax=800 "Assigning the datatype of a variable in MapForce")

映射处理已成功完成，生成以下结果：

![以下是经过修改后的数据映射的示例输出](https://lh4.ggpht.com/-4jeljPRsVcU/UO2I3iKQtZI/AAAAAAAAA7U/sH3Wn2YS05I/clip_image007%25255B3%25255D.png?imgmax=800 "Example output from the mdified data mapping")

**创建用户函数**

[用户函数](https://www.altova.com/zh/mapforce/visual-function-builder.html) 在 MapForce 中定义于一个映射文件中，并且可以添加到函数库中，供其他映射文件使用，甚至可以被多个用户使用。用户函数还可以封装复杂的操作，从而使大型映射设计中的整体数据流程更加易于追踪。

我们已经对简单的Web服务调用进行了修改，根据经度选择用于美国东部或西部大陆的数据库。现在，如果我们在结果中添加明确的数据类型定义，将会使调用 `getElevation` 函数变得更加复杂。我们选择将所有内容都定义在一个用户自定义函数中。

![MapForce 中的用户函数，用于封装复杂的操作](https://lh6.ggpht.com/-EgfsEE1molQ/UO2I4X0fxbI/AAAAAAAAA7c/lgbGUeDDmIU/clip_image008%25255B3%25255D.png?imgmax=800 "A user function in MapForce to encapsulate a complex operation")

**应用用户函数**

在下面的代码示例中，我们插入了新的 `getElevationUS` 函数。

![MapForce 数据映射功能，通过用户自定义函数得到增强](https://lh5.ggpht.com/-1WM_YloAs9Q/UO2I5OcvIQI/AAAAAAAAA7k/0rKkFhfhmKY/clip_image009%25255B3%25255D.png?imgmax=800 "MapForce data mapping enhanced with a User Function") 

现在，回顾一下我们最初为什么要对Web服务返回的海拔值进行四舍五入。Web服务返回的值以米为单位，而小数点后两位，也就是每一厘米，都小于半英寸。

我们可以将四舍五入操作包含在 `getElevationUS` 函数中，但如果该函数不进行四舍五入，直接使用原始海拔数据，那么它在未来的数据映射中会更有用。

以下是经过修改后的地图生成结果，使用了与最初出现问题时相同的 .gpx 文件作为输入。我们在输出文件中搜索了时间戳 "23:06:22"，这是我们在出现错误之前找到的最后一个有效坐标的时间戳。从第 902 行开始的以下点，就是导致错误的点。

![来自 MapForce 数据映射工具的示例数据](https://lh5.ggpht.com/-k6NYBvSghlA/UO2I52w8KQI/AAAAAAAAA7s/0-s7KfpJdpE/clip_image010%25255B3%25255D.png?imgmax=800 "Sample data from a MapForce data mapping")

最初，我们感到有些失望，因为所有的努力似乎都只是为了提升到0。然后，我们在谷歌地图上标记了那些可疑的坐标：

![通过纬度和经度确定一个点的地理位置](https://lh6.ggpht.com/-0v5cW6dbhms/UO2I6ssKn6I/AAAAAAAAA7w/6Kq-1XDWz5Q/clip_image011%25255B3%25255D.png?imgmax=800 "Locating a point by latitude and longitude")

路线的一部分沿着一座桥梁，横跨一个潮汐河口。即使我们将来在数据地图中不再使用 `getElevationUS` 函数，但很可能其他旅行的 .gpx 文件也会经过其他潮汐河口，并且在这些地方可能会产生更多非常小的海拔数值。

**如果您想使用以下工具，请** [Altova MissionKit 套件](https://www.altova.com/zh/missionkit/software-development-tools.html) **用于创建用户自定义函数，以便对您的数据进行个性化映射** [点击此处下载免费试用版](https://www.altova.com/zh/download-trial/)**.**
