如何一次性将复杂XML数据导入多个FileMaker表?
嘿,我来帮你搞定这个FileMaker XML导入的难题!结合你已有的XML和XSLT基础,我们完全可以在FileMaker内部完成转换导入,不用额外做外部预处理,还能让用户操作更便捷。下面是具体的方案:
核心方案:用XSLT将非标准XML转成FileMaker兼容的
fmpxmlresult格式 FileMaker导入XML时支持直接应用XSLT转换,我们可以通过自定义XSLT脚本,把你那混合了标准XML和非标准换行文本的数据源,转换成FileMaker能识别的结构化格式,同时完成三个表的关联导入。
1. XSLT转换脚本(针对你的数据源定制)
下面是专门适配你提供的XML结构的XSLT代码,我会逐段帮你解释:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:FMP="http://www.filemaker.com/fmpxmlresult"> <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes"/> <!-- 生成FileMaker要求的根结构 --> <xsl:template match="/"> <FMP:FMPXMLRESULT xmlns:FMP="http://www.filemaker.com/fmpxmlresult"> <FMP:ERRORCODE>0</FMP:ERRORCODE> <!-- 生成主表记录:提取<data>的属性作为主表字段 --> <FMP:RECORDSET> <FMP:RECORD MODID="0" RECORDID="1"> <FMP:FIELD NAME="resultMode"><FMP:DATA><xsl:value-of select="/result/data/@mode"/></FMP:DATA></FMP:FIELD> <FMP:FIELD NAME="resultRam"><FMP:DATA><xsl:value-of select="/result/data/@ram"/></FMP:DATA></FMP:FIELD> </FMP:RECORD> </FMP:RECORDSET> <!-- 处理数据点表:拆分<data>里的非标准换行文本 --> <FMP:RECORDSET> <xsl:call-template name="splitDataLines"> <xsl:with-param name="text" select="/result/data"/> <xsl:with-param name="parentResultID" select="1"/> <!-- 关联主表的唯一ID --> </xsl:call-template> </FMP:RECORDSET> <!-- 处理位置表:直接转换标准XML节点 --> <FMP:RECORDSET> <xsl:for-each select="/result/statistics/positions/position"> <FMP:RECORD MODID="0" RECORDID="{@id}"> <FMP:FIELD NAME="positionID"><FMP:DATA><xsl:value-of select="@id"/></FMP:DATA></FMP:FIELD> <FMP:FIELD NAME="positionUnit"><FMP:DATA><xsl:value-of select="@unit"/></FMP:DATA></FMP:FIELD> <FMP:FIELD NAME="positionValue"><FMP:DATA><xsl:value-of select="."/></FMP:DATA></FMP:FIELD> <FMP:FIELD NAME="resultID"><FMP:DATA>1</FMP:DATA></FMP:FIELD> <!-- 关联主表 --> </FMP:RECORD> </xsl:for-each> </FMP:RECORDSET> </FMP:FMPXMLRESULT> </xsl:template> <!-- 自定义模板:把<data>里的换行文本拆分成单独记录 --> <xsl:template name="splitDataLines"> <xsl:param name="text"/> <xsl:param name="parentResultID"/> <xsl:param name="recordIndex" select="1"/> <!-- 提取单行内容(用换行符分割) --> <xsl:variable name="currentLine" select="normalize-space(substring-before(concat($text, ' '), ' '))"/> <xsl:if test="$currentLine != ''"> <FMP:RECORD MODID="0" RECORDID="{$recordIndex}"> <FMP:FIELD NAME="resultID"><FMP:DATA><xsl:value-of select="$parentResultID"/></FMP:DATA></FMP:FIELD> <!-- 拆分逗号分隔的数值 --> <FMP:FIELD NAME="dataValue1"><FMP:DATA><xsl:value-of select="normalize-space(substring-before($currentLine, ','))"/></FMP:DATA></FMP:FIELD> <xsl:variable name="remainingPart" select="substring-after($currentLine, ',')"/> <FMP:FIELD NAME="dataValue2"><FMP:DATA><xsl:value-of select="normalize-space(substring-before(concat($remainingPart, ','), ','))"/></FMP:DATA></FMP:FIELD> <!-- 检测是否有"E"标记 --> <FMP:FIELD NAME="dataStatus"><FMP:DATA> <xsl:choose> <xsl:when test="contains($remainingPart, 'E')">E</xsl:when> <xsl:otherwise></xsl:otherwise> </xsl:choose> </FMP:DATA></FMP:FIELD> </FMP:RECORD> <!-- 递归处理剩余行 --> <xsl:call-template name="splitDataLines"> <xsl:with-param name="text" select="substring-after($text, ' ')"/> <xsl:with-param name="parentResultID" select="$parentResultID"/> <xsl:with-param name="recordIndex" select="$recordIndex + 1"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet>
脚本关键说明:
- 主表处理:提取
<data>的mode和ram属性作为主表字段,给主表一个固定的RECORDID=1,用来关联另外两个表 - 数据点表处理:通过自定义模板
splitDataLines,用换行符 分割<data>里的每行文本,把每行拆分成单独的记录,同时处理带", E"的标记字段 - 位置表处理:直接遍历标准的
<position>节点,提取属性和文本值,自动添加关联主表的resultID
2. FileMaker导入步骤(简化用户操作)
- 提前准备好三个表的结构:主表(含
resultMode、resultRam、resultID主键)、数据点表(含resultID外键、dataValue1、dataValue2、dataStatus)、位置表(含resultID外键、positionID、positionUnit、positionValue),并建立好表间关联 - 选择
文件 > 导入记录 > XML... - 在导入向导中:
- 选择你的原始XML文件
- 勾选「使用XSLT样式表」,选中上面写好的XSLT文件
- 点击「继续」,对应好每个表的字段映射(第一次设置后可以保存导入配置)
- 完成导入,三个表会自动填充关联好的数据
3. 优化用户体验的小技巧
- 保存导入脚本:把整个导入流程录制成FileMaker脚本,用户只需要点击脚本就能完成导入,不用重复设置
- 添加文件选择步骤:在脚本里加入「选择文件」的步骤,让用户可以一键选择要导入的XML文件
- 自动记录导入时间:在主表添加
导入时间字段,脚本里自动填充当前时间,方便追溯数据来源
如果你的表结构有调整,只需要修改XSLT里的<FMP:FIELD NAME="xxx">部分对应你的字段名就行,全程不用外部工具预处理,用户操作起来非常省心!
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

