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

嗨FME'ers,

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

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

相邻要素属性的定义:

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

e2c048ccdd52096a3942d8b84466e28a.png

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

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

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

3db0fef2bbafcc4bb3e44096c66a5c7a.png

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

ebfd0a94534812fd6e20e24544b3477c.png

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

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

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

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

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

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

66f26cc298989fdb0c6c1d3a0a1e8d5c.png

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

培训期间遇到的问题

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

c6bed289a94701b2a0a04f5549174023.png

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

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

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

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

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

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

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

edd7ab51a4668ff79e324bf7470436af.png

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

37a17e82f59b7db549af2c32b62eb447.png

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

第二个AttributeManager

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

22959172c5828c0214a6f362f1547045.png

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

然后设置条件语句:

5c99c9633d2f3ad7b0c8685a737d39db.png

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

1ee4ed59c614339f5dee7e1229862afa.png

基本逻辑如下:

l  如果先前要素是ADDN(或CHG或DEL)

l 并且该要素没有新的Action

l 并且不是分隔符----

l  则输出ADDN(或CHG或DEL)

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

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

fc025af3d40e58a0323dd537cd575e6b.png

基本逻辑如下:

l  如果文本行不以Action开头

l  并且Action不是XXXX

l  则将其认定为一个附加了Action的要素

l  ELSE只使用原始内容

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

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

输出

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

4ded3efc51de5d78eb8d068e93971b3e.png

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

总结

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

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

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

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值