【发布时间】:2017-10-25 09:34:44
【问题描述】:
我正在处理一组记录,这些记录具有多个可重复的不同子节点类型。最终目标是创建一个 CSV 映射,并且由于嵌套,每个 XML 记录可以映射到许多 CSV 行项目。
我了解如何使用for-each 创建多个输出行,但我遇到了麻烦,因为有两种不同的情况需要循环。
在以下示例中,App 是基本记录,SST_Interval 是可重复的(1 个或多个),ReplacementPart 可以有 0 个或多个 PartTypes。
我想提取具有以下格式的 CSV
app_id|base_vehicle_id|sst_interval_id|sst_interval_month|part_type_id
对于下面显示的记录,结果如下所示
915152|18287|646|12|10007
915152|18287|646|12|12277
915152|18287|646|12|18159
915152|18287|32523|24|10007
915152|18287|32523|24|12277
915152|18287|32523646|24|18159
这是记录
<App action="A" id="915152" ref="568874">
<BaseVehicle id="18287" />
<EngineVIN id="25" />
<Note id="8722" vehicleattribute="no" />
<Position id="1" />
<MOTOR_Operation id="551841">
<SkillCode>G</SkillCode>
<Base_MOTOR_EWT minutes="1" />
<SST_Interval id="646">
<SST_IndicatorImage><![CDATA[sstgm140001]]></SST_IndicatorImage>
<SST_IndicatorText><![CDATA[Change Engine Oil Soon]]></SST_IndicatorText>
<SST_Frequency id="7" />
<SST_IntervalMonth><![CDATA[12]]></SST_IntervalMonth>
<SST_SevereService id="2080" />
<SST_Note1 id="5117" />
</SST_Interval>
<SST_Interval id="32523">
<SST_IndicatorImage><![CDATA[sstgm140001]]></SST_IndicatorImage>
<SST_IndicatorText><![CDATA[Change Engine Oil Soon]]></SST_IndicatorText>
<SST_Frequency id="7" />
<SST_IntervalMonth><![CDATA[24]]></SST_IntervalMonth>
<SST_SevereService id="2080" />
<SST_Note1 id="5117" />
</SST_Interval>
<ReplacementPart>
<PartType id="10007" servicetype_id="1" />
<PartType id="12277" servicetype_id="1" />
<PartType id="18159" servicetype_id="1" />
</ReplacementPart>
</MOTOR_Operation>
</App>
这是我尝试过的 XSLT。如果您能指出正确的方向,我将不胜感激。
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Header|Footer">
</xsl:template>
<xsl:template match="App">
<xsl:apply-templates select="MOTOR_Operation/SST_Interval"/>
</xsl:template>
<xsl:template match="PartType">
<xsl:apply-templates select="@id" mode="csv"/>
</xsl:template>
<xsl:template match="SST_Interval">
<xsl:variable name="tmp">
<xsl:apply-templates select="ancestor::App/@id" mode="csv"/>
<xsl:apply-templates select="@id" mode="csv-nl"/>
</xsl:variable>
<xsl:for-each select="ancestor::App/MOTOR_Operation/ReplacementPart/PartType">
<xsl:copy-of select="$tmp"/>
<xsl:apply-templates select="." />
</xsl:for-each>
</xsl:template>
<xsl:template match="text()|@*" mode="csv">
<xsl:value-of select="concat(., '|')" />
</xsl:template>
<xsl:template match="text()|@*" mode="csv-nl">
<xsl:value-of select="concat(., '
')" />
</xsl:template>
</xsl:stylesheet>
【问题讨论】:
-
如果有0个
PartTypes,预期的结果是什么? -
最后一个字段,
part_type_id会像这样为空:915152|18287|646|12|| -
但是应该有多少行?每个现有的
PartType都有一行,所以如果不存在,逻辑上应该有 0 行。 -
你说得很好。完全规范化,应该有两个单独的表,一个用于服务,一个用于服务部分映射。如果是这种情况,如果没有部件,则服务部件表将没有条目。作为第一遍,我将 XML 转换为更加非规范化的形式,所以我想在一行中说这个服务存在并且它没有部分