使用XSLT为csv输出中的每个xml同级生成一个唯一的记录



我正在尝试将下面的xml转换为csv。每个记录都应该是csv输出中自己的条目,然而,我也希望每个";TO_日期";在csv输出中为该ID生成一个唯一的条目。所需.csv输出的示例位于XML下方。我该怎么做?我最初认为一个for each可以做到这一点,但我一直没能让它发挥作用,我读到在XSLT中使用for each这样的东西是不好的做法。

<Data>
<Record>
<Person>
<Person_ID>0000002</Person_ID>
</Person>
<LOA_Event>
<LOA_First_Day>01-02-2020</LOA_First_Day>
<LOA_Last_Day>30-06-2020</LOA_Last_Day>
<LOA_Reason Descriptor="Mat">
<ID>2</ID>
<LOA_Reason>
</LOA_Event>
</Record>

<Record>
<Person>
<Person_ID>0000001</Person_ID>
</Person>
<TO_Event>
<TO_First_Day>01-01-2020</TO_First_Day>
<TO_Last_Day>03-01-2020</TO_Last_Day>
<TO_Reason Descriptor="Other">
<ID>2</ID>
</TO_Reason>
<TO_Date Descriptor="01-Jan-2020 - 1 Days">
<ID>1</ID>
</TO_Date>
<TO_Date Descriptor="02-Jan-2020 - 1 Days">
<ID>1</ID>
</TO_Date>
<TO_Date Descriptor="03-Jan-2020 - 1 Days">
<ID>1</ID>
</TO_Date>
<Plus_or_Minus>1</Plus_or_Minus>
</TO_Event>
</Record>
</Data>

Person,FirstDay,LastDay,Reason,PlusMinus
"0000002","01-02-2020","30-06-2020","Mat",""
"0000001","01-Jan-2020","","Other","1"
"0000001","02-Jan-2020","","Other","1"
"0000001","03-Jan-2020","","Other","1"

我最初认为一个for each可以做到这一点,但我没能让它在上工作

实际上,使用xsl:for-each:很容易做到这一点

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/Data"> 
<xsl:text>Person,FirstDay,LastDay,Reason,PlusMinus&#10;</xsl:text>
<xsl:for-each select="//LOA_Event | //TO_Date">
<xsl:text>"</xsl:text>
<xsl:value-of select="ancestor::Record/Person/Person_ID"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="substring(LOA_Last_Day | @Descriptor, 1, 11)"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="LOA_Last_Day"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="LOA_Reason/@Descriptor | ../TO_Reason/@Descriptor"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="../Plus_or_Minus"/>
<xsl:text>"&#10;</xsl:text>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

然而,这种方法有两个缺点:

  1. 代码并行处理两个非常不同的节点,使其难以阅读和维护
  2. 频繁地在树上来回走动以从祖先/兄弟节点检索值是低效的

OTOH,使用模板进行操作需要更多代码:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/Data"> 
<xsl:text>Person,FirstDay,LastDay,Reason,PlusMinus&#10;</xsl:text>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Record"> 
<xsl:apply-templates select="LOA_Event | TO_Event">
<xsl:with-param name="personID" select="Person/Person_ID"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="LOA_Event">
<xsl:param name="personID"/> 
<xsl:text>"</xsl:text>
<xsl:value-of select="$personID"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="LOA_First_Day"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="LOA_Last_Day"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="LOA_Reason/@Descriptor"/>
<xsl:text>",""&#10;</xsl:text>
</xsl:template>
<xsl:template match="TO_Event">
<xsl:param name="personID"/> 
<xsl:apply-templates select="TO_Date">
<xsl:with-param name="personID" select="$personID"/>
<xsl:with-param name="reason" select="TO_Reason/@Descriptor"/>
<xsl:with-param name="plusMinus" select="Plus_or_Minus"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="TO_Date">
<xsl:param name="personID"/> 
<xsl:param name="reason"/> 
<xsl:param name="plusMinus"/> 
<xsl:text>"</xsl:text>
<xsl:value-of select="$personID"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="substring(@Descriptor, 1, 11)"/>
<xsl:text>","","</xsl:text>
<xsl:value-of select="$reason"/>
<xsl:text>","</xsl:text>
<xsl:value-of select="$plusMinus"/>
<xsl:text>"&#10;</xsl:text>
</xsl:template>
</xsl:stylesheet>

最新更新