免费视频|新人指南|投诉删帖|广告合作|地信网APP下载

查看: 935|回复: 6
收起左侧

FME相邻要素属性:读取结构化文本文件的示例

[复制链接]

665

主题

2万

铜板

34

好友

传奇会员

Rank: 30Rank: 30Rank: 30Rank: 30Rank: 30Rank: 30Rank: 30Rank: 30

积分
20649

精华勋章爱心勋章地信专家组贡献勋章冰雪节勋章

发表于 2021-10-28 15:17 | 显示全部楼层 |阅读模式

本文转载来自CSDN作者:fmechina    版权归作者所有

原文链接:https://www.safe.com/blog/2017/08/adjacentfeatureattributes-evangelist166/

嗨FME'ers,

我确实没有太多留意FME中的相邻要素属性功能(Adjacent Feature Attributes),很可惜,这是一个非常棒的数据处理工具。

最近的培训课程中的一个问题就是一个很好的例子……

相邻要素属性的定义:

首先让我解释一下这个工具,查看AttributeManager转换器的参数,你会在对话框的顶部看到几个高级选项:

显然,关键参数是启用相邻要素属性,但如下图所示替换参数对我们也很重要。

它有什么用呢?请记住,FME中的每个要素通常都是单独处理的(基于要素)。在整个数据流里面每个要素都有自己的属性。这个选项的作用是让我们联系流中的相邻要素并访问它们的属性!

例如,在Advanced FME Desktop课程的基本练习中,我设置了AttributeManager转换器以访问前面的要素属性:


我们在处理累计气候降雨数据(2月的总数是1月+ 2月,3月是1月+ 2月+ 3月)。我要获得每个月的降雨数据需用以下内容:

即当前月份(当前要素)的降雨量是在其累计总量减去上个月(先前要素)的累计总量。你可以看到[-1]部分就是告诉FME该值来自前一个要素的属性。

这是相邻属性如何工作的很简单的一个示例,你可以看到替换值很重要,因为1月没有先前要素去减。如果不为该方案设置默认值,则会运行失败。

还有更复杂的场景......


相邻要素属性:文本读取示例

我真正想要展示的例子是比降雨量数据更频繁出现的例子:从结构化文本文件中读取数据。

与CSV文件不同,数据排列整齐并以逗号(或类似字符)分隔,文本文件通常采用数据分布在多行中的格式,如下所示:

人阅读起来很简单,但软件读取起来很困难。因为这些通常是专有格式或结构,并不是统一的结构,因此也不存在标准解决方案。在某些情况下,结构可能非常复杂,具有未知数量的标题行,在读取之前需要先进行重组。

培训期间遇到的问题

在培训期间,有用户提出下面一个问题:

它本质上是一个要处理要素列表的日志。添加要素(ADDN),更改要素(CHG),删除要素(DEL)。使用FME文本行读模块读本文,从标题和分隔符行中提取要素并不困难。

难点是在如何表达:FEATURE 12345是ADDN,因为“ADDN”部分是在标题中定义的(我们称之为Action Header)并且只是单独读取一个要素且不包括Action Header内容。

此外,文本结构不固定。文本可能并不总是恰好添加6个要素,或者并不删除任何要素。所以我们不能用定义行数、或文件结构的方法读取数据。

在此之前,有一种解决方案是使用VariableSetter和VariableRetriever转换器。 将Action Header保存为变量并应用于所有后续要素。但至少对我来说 ,这不是处理这些数据的最佳方式。使用这样的变量需要工作空间中的要素流是可预测的,我更喜欢确定性而不是预测!

因此,我提出了使用相邻要素属性的解决方案。


相邻要素属性:文本读取解决方案

我在培训的休息期间粗略的做了一个解决方案,虽然很简陋,但是已经够用了。它使用TEXTLINE读模块读取数据并使用两个AttributeManager转换器来执行处理:


第一个转换器清除Action Header,使用一组条件语句将“ADDN,ID:XYZ”输出为“ADDN”:

我本可以使用tester转换器,进一步可能用到SubstringExtractor。使用条件是改选有两个好处。首先,整个页面简洁、漂亮;其次,更重要的是,请注意“Else”字段设置为<null>,这代表每个不是Action Header的行都会返回<null>,表示我们暂时还没定义其操作。当我们使用相邻的要素属性时,<null>将被替换。


第二个AttributeManager

第二个变换器的上层参数如下所示:

通过前一个要素确定相应的操作,但并非文件中的每一行都有先前要素的操作,因此我们将默认值设置为XXXX。

然后设置条件语句:

新的Action字段定义了该行数据的操作,具体取决于先前要素。详情如下:

基本逻辑如下:

  • 如果先前要素是ADDN(或CHG或DEL)
  • 并且该要素没有新的Action
  • 并且不是分隔符----
  • 则输出ADDN(或CHG或DEL)

“并且该要素没有新的Action”很重要。它的意思是“这一行是Action Header吗?” 如果是,则不用先前要素的Action将其覆盖。

现在每个要素都标记有正确的操作。创建NewLine属性包含Action的新文本行,由FME将其写入重构的输出文件:

基本逻辑如下:

  • 如果文本行不以Action开头
  • 并且Action不是XXXX
  • 则将其认定为一个附加了Action的要素
  • ELSE只使用原始内容

第一个if语句检查这是否已经是一个Action Header(有操作指令,但不需要执行)。

第二个if语句检查是否有任何其他操作或分隔符行(仍然有XXXX作为其操作指令)。

输出:

最后,FME将数据写入文本文件。结果如下所示:

现在,读取数据并确定特定行与哪个操作相关联起来要容易得多。

总结

这是一个含有条件筛选的相邻要素属性的简短示例。它不是很简洁,但也并不复杂!毕竟我是在比较匆忙的情况下做的。

回想一下,两个AttributeManager都需要不同的substitute value。是因在某一行还没有开始执行的时候,第一个<Null>已经被定义了。同时我们正在使用相邻要素,所以需要一个不同的substitute value来处理顶行(没有先前要素的那一行)。

无论如何,我不知道是否还有更简单的解决方法。相邻要素属性使我们能够从先前要素中获取操作,其余部分都经过筛选,以确保不会覆盖新的Action Header。这很简单。

首先,所有要素都会获取先前要素的最新操作。例如,FEATURE 12345是从Action Header获取的操作,FEATURE 12346是使用FEATURE 12345的操作更新的操作。我想表达的是相邻要素属性是根据先前要素动态更新的。

其次,在第二个转换器中,第二条件取决于第一个转换器。换句话说,这也是动态的,放置这些条件属性的顺序很重要。这意味着我只用了一个转换器上实现了在一个转换器中生成属性,另一个转换器来处理的操作。

我希望这个小例子对你很感兴趣。如果你需要查看详情,则可以在Dropbox上找到它。

https://www.dropbox.com/s/jn1ru8dum68fo2u/AdjacentFeatureAttrs.fmwt?dl=1


11

主题

2万

铜板

9

好友

地信院士

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

积分
2746

童话节勋章

发表于 2021-10-28 16:03 | 显示全部楼层
6666666666666666666
回复 支持 反对

使用道具 举报

5

主题

4402

铜板

3

好友

高级工程师

Rank: 9Rank: 9Rank: 9

积分
979
发表于 2021-10-29 15:30 | 显示全部楼层
感谢楼主分享
回复 支持 反对

使用道具 举报

10

主题

1万

铜板

20

好友

资深会员

Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

积分
3718
发表于 2021-11-10 10:56 | 显示全部楼层
谢谢分享
回复

使用道具 举报

0

主题

5148

铜板

1

好友

地信院士

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

积分
2100
发表于 2022-7-3 16:34 | 显示全部楼层
感谢楼主分享
回复 支持 反对

使用道具 举报

2

主题

4万

铜板

7

好友

钻石会员

Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26

积分
6445
发表于 2024-3-4 19:30 | 显示全部楼层
谢谢分享
回复

使用道具 举报

2

主题

4万

铜板

7

好友

钻石会员

Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26

积分
6445
发表于 2024-3-4 19:31 | 显示全部楼层
谢谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

在线客服
快速回复 返回顶部 返回列表