FME作为转换神器,支持几百种格式的互转,实现互操作化。从fme.exe执行方式入手,讨论Command命令式执行模板(.fmw/.fmwt)和脚本(.tcl/.py)实现自动化批量转换。
1、fme.exe命令分析
一般打开CMD命令后直接输入fme可执行,系统环境变量已将FME按照目录加进去了。
图1 fme.exe命令
从红圈看出FME本身执行也是靠fme.exe来执行ControlFile(控制文件)和ScriptFile(脚本文件)的。对于ControlFile可以利用FMEWorkBench来制作,对于ScriptFile有2种方式:FMEWorkBench和FMEQuickTranslator【这里是FME2014】来创建。
注:其他命令和参数设置这里不做详述。
2、批量自动化转换
(1)ScriptFile方式,.tcl控制内容,.bat执行
此处可在【FME Desktop Help】中 FME Workbench > Workspace Basics > Running and Debugging Workspaces > Running a Batch Translation找到相关内容。
FMEWorkBench在制作完.FMW后,可在File—BatchDeploy向导式部署导出BAT和TCL脚本,数据源选择可以使用增加数据源目录或多个文件。
图2 batch数据源设置
FMEQuickTranslator可以用Tools—CreateBatch来创建,数据源设置目录或文件与图2相同,设置原始数据格式和原始数据格式,再设置Batch导出。
图3 FMEQuickTranslator批量脚本
生成后.bat文件就一行,fme开头执行.tcl文件。
.tcl文件存储了基本的设置:工作空间、原始数据及格式、目标数据及格式,日志,相关转换等参数,可用记事本打开查看和随时改动,脚本方式执行.bat文件即可完成批量自动化转换。
(2)ControlFile方式,Process程序执行【fme.exe ControlFile PublishParams】
此处可在【FME Desktop Help】中 FME Workbench > Workspace Basics > Running and Debugging Workspaces > Working with Command Files找到相关内容。
执行方式如下:
Fme.exe [.fmw/.fmwt文件] [对应发布参数] Eg: fme.exe c:\temp\command.fmw --SourceDataset_ACAD "\"\"C:\FMEData\Data\Water\distribution_L25.dwg\" \"C:\FME Data\Data\Water\distribution_L26.dwg\"\"" --DestDataset_DGNV8 c:\temp\output.dgn LOG_FILENAME c:\fme.log |
可以看到关键在于发布参数的动态设置,一个完整的工作空间中有那么几个需要自定义的参数需要设置,UserParameter设置对应PromptAndRunTranslation(提示并运行转换)相关参数是对应的,而且用户发布参数决定着整个工作空间运行的情况。
图4 用户发布参数与转换参数对应
程序执行批量自动化转换:一是提取FME核心和注册表相关来进行命令组合,类似于打开CMD后输入命令,不过是程序实现;二是自动提取FME用户发布参数,这个是核心,需要从.fmw中提取。
这里仔细描述下用户发布参数提取方式,由于是从.fmw文件中提取的,记事本或写字板打开一个.fmw文件,搜索“DEFAULT_MACRO”,我们就可以找到用户发布参数显示的地方,如下例为1个【DestDataset_GEODATABASE_FILE】发布参数,后面加地址,GUI指出文件类型,而此“DEFAULT_MACRO”和“GUI”组成一个发布参数。
DEFAULT_MACRO DestDataset_GEODATABASE_FILE E:\KSDE\test.gdb GUI DEST_GEODATABASE DestDataset_GEODATABASE_FILE Destination ESRI Geodatabase (File-based) File: |
那么如何利用程序从.fmw中提取出这些发布参数?
分析:.fmw文件中针对“DEFAULT_MACRO”和“GUI”组合的内容有很多,只有前部分是用户发布参数,后部分是工作空间数据源、目标数据、转换器等的相关参数,区分标识在于标签:#! START_HEADER、#! END_HEADER,在此标签(当做XML标签)之间又有:
#! START_WB_HEADER、#! END_WB_HEADER;
#! START_SOURCE_HEADER、#! END_SOURCE_HEADER;
#! START_DEST_HEADER、#! END_DEST_HEADER;
利用XML形式表达层次为:
1 < START_HEADER> 2 < START_SOURCE_HEADER> 3 <START_WB_HEADER><END_WB_HEADER> 4 < END_SOURCE_HEADER> 5 < START_DEST_HEADER> 6 <START_WB_HEADER><END_WB_HEADER> 7 < END_DEST_HEADER> 8 < END_HEADER>
由此可通过标签过滤得到用户发布参数,再通过“GUI”识别类型,通过换行符“\”和分隔符“ ”进行分割得到每个发布参数,最后程序实现读取发布参数。因此,可实现读取和存入数据,动态的执行.fmw,达到批量自动化数据转换。
给出发布参数读取方法供参考,过程源于【参考1】:
1)、通过标签进行过滤得到《用户发布参数》范围。
1 public List<FMEParameter> GetParameters(string fmeFile) 2 { 3 List<FMEParameter> list = new List<FMEParameter>(); 4 XmlDocument document = null; 5 string str = null; 6 char[] trimChars = new char[] { '#', '!', ' ' }; 7 using (StreamReader reader = new StreamReader(fmeFile, Encoding.Default)) 8 { 9 StringBuilder builder = new StringBuilder(); 10 while (!reader.EndOfStream) 11 { 12 str = reader.ReadLine().Trim(); 13 if (str.StartsWith(Resource.StringFMWXmlPrefix)) 14 { 15 if (str == Resource.StringFMWXmlPrefix) 16 { 17 break; 18 } 19 builder.Append(string.Format("{0} ", str.TrimStart(trimChars))); 20 } 21 } 22 document = new XmlDocument(); 23 try 24 { 25 document.LoadXml(builder.ToString()); 26 } 27 catch (Exception) 28 { 29 document = null; 30 } 31 } 32 if (document != null) 33 { 34 foreach (XmlNode node2 in document.SelectSingleNode(Resource.StringFMWParameterPath)) 35 { 36 FMEParameter item = this.GetParameter(node2); 37 if (string.IsNullOrEmpty(item.Name)) 38 { 39 Trace.WriteLine(node2.Attributes[Resource.StringFMWParameterDefaultValue].Value); 40 } 41 else 42 { 43 list.Add(item); 44 } 45 } 46 } 47 return list; 48 }
2)、《用户发布参数》范围解析,得到FME发布参数
1 private FMEParameter GetParameter(XmlNode node) 2 { 3 FMEParameter parameter = new FMEParameter { 4 DefaultValue = node.Attributes[Resource.StringFMWParameterDefaultValue].Value 5 }; 6 string input = node.Attributes[Resource.StringFMWParameterInfo].Value; 7 parameter.Optional = Regex.IsMatch(input, @"GUI\s+OPTIONAL\s+", RegexOptions.IgnoreCase); 8 parameter.Published = !Regex.IsMatch(input, @"GUI\s+OPTIONAL\s+IGNORE\s+|GUI\s+IGNORE\s+", RegexOptions.IgnoreCase); 9 input = Regex.Split(input, @"GUI\s+OPTIONAL\s+IGNORE\s+(.+)|GUI\s+IGNORE\s+(.+)|GUI\s+OPTIONAL\s+(.+)|GUI\s+(.+)", RegexOptions.IgnoreCase)[1]; 10 string[] strArray = Regex.Split(input, @"([^\s]+)\s+([^\s]+)\s+(.+)", RegexOptions.IgnoreCase); 11 parameter.Type = strArray[1]; 12 parameter.Name = strArray[2]; 13 if (this.hasConfiguration(parameter.Type)) 14 { 15 strArray = this.SplitConfigurationPrompt(strArray[3]); 16 parameter.Configuration = strArray[0]; 17 parameter.Label = strArray[1]; 18 return parameter; 19 } 20 parameter.Label = strArray[3]; 21 parameter.Configuration = string.Empty; 22 return parameter; 23 }
总结:通过fme.exe命令执行方式探讨了2种批量自动化数据转换方法,详细论述了具体实现过程和关键技术点,提供相关参考。
另:有【自定义FME批处理脚本,安图博客 】,通过DOS命令,自定义设置FME模板、数据源路经、目标数据路径、以及日志等信息,基本也属于命令执行范畴。
【引用已说明出处,转载请说明出处。】
参考:
[1] FME 开发篇(二) .安图163博客,2014.5