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

原文链接: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字段定义了该行数据的操作,具体取决于先前要素。详情如下:

基本逻辑如下:

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

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

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

基本逻辑如下:

  1. 如果文本行不以Action开头
  2. 并且Action不是XXXX
  3. 则将其认定为一个附加了Action的要素
  4. 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

 

 

 

发布了350 篇原创文章 · 获赞 169 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/fmechina/article/details/91854162