具有各种长度的列数据的固定格式输出

Fixed Format Output w/ Column Data of Various Lengths

XSLT 版本 1.0 来源 XML

    <Vehicle>
       <Parts>
         <Part SN="1234567" PartNumber="223232" Build="2W345" Manuf="K3E4" Mater="12312">
           <Inspections ManufI="K3F4"/> 
           <Recalls  ID="1223-4" Status="02"/>
           <Recalls  ID="1987-9" Status="07" />
           <Recalls ID="1211-10" Status="17" />
           <Recalls ID="4545-1" Status="07" />
           <Recalls ID="2291-7" Status="01" />
           <Recalls ID="2322-4" Status="04" />
         </Part>
         <Part SN="1255" PartNumber="87666" Build="3ED55" Manuf="98772" Mater="8YT76">
           <Inspections /> 
           <Recalls  ID="5676-4" Status="01"/>
           <Recalls  ID="13347-9" Status="01" /> 
             <Part> SN="1256" PartNumber="76554" Build="3R453" Manuf="7U7Yt" 
                                    Mater="9I123">
              <Inspections />
              <Recalls />
             </Part>
         </Part>
    </Parts>
    </Vehicle>

我正在尝试生成以下固定格式文件。 'recalls' 列表只是序列号 (SN) 的召回列表,与其左侧的类型和代码列无关。如示例所示,它可能比类型和代码列表更长或更短。

SN          PartNumber  Type    Code         Recall     Status
1234567     223232      Manuf   K3E4         1223-4     02
                        ManufI  K3F4         1987-9     07
                        Mater   12312        1211-10    17
                        Build   2W345        4545-1     07
                                             2291-7     01
                                             2322-4     01

1255        87666       Manuf   98772        5676-4     01
                        Mater   8YT76        13347-9    01
                        Build   3ED55    

1256        76554       Manuf   7U7Yt
                        Mater   9I123
                        Build   3R453  

这是您可以用作起点的示例。为简单起见,它生成 CSV 输出而不是固定宽度的文件。

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/Vehicle">
    <xsl:text>SN, PartNumber, Type, Code, Recall, Status&#10;</xsl:text>    
    <xsl:for-each select="Parts/Part">
        <xsl:call-template name="generate-rows">
            <xsl:with-param name="types" select="@Manuf | @Build | @Mater | Inspections/@ManufI" />
        </xsl:call-template>
    </xsl:for-each>
</xsl:template>

<xsl:template name="generate-rows">
    <xsl:param name="types"/>
    <xsl:param name="i" select="1"/>
    <!-- part columns -->
    <xsl:value-of select="@SN[$i]"/>
    <xsl:text>, </xsl:text> 
    <xsl:value-of select="@PartNumber[$i]"/>
    <xsl:text>, </xsl:text> 
    <!-- type columns -->
    <xsl:value-of select="name($types[$i])"/>
    <xsl:text>, </xsl:text> 
    <xsl:value-of select="$types[$i]"/>
    <xsl:text>, </xsl:text> 
    <!-- recall columns -->
    <xsl:value-of select="Recalls[$i]/@ID"/>
    <xsl:text>, </xsl:text> 
    <xsl:value-of select="Recalls[$i]/@Status"/>
    <xsl:text>&#10;</xsl:text>
    <!-- recursive call -->
    <xsl:if test="$i &lt; count($types) or $i &lt; count(Recalls)">
        <xsl:call-template name="generate-rows">
            <xsl:with-param name="types" select="$types"/>
            <xsl:with-param name="i" select="$i + 1"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,这将产生:

结果

SN, PartNumber, Type, Code, Recall, Status
1234567, 223232, Build, 2W345, 1223-4, 02
, , Manuf, K3E4, 1987-9, 07
, , Mater, 12312, 1211-10, 17
, , ManufI, K3F4, 4545-1, 07
, , , , 2291-7, 01
, , , , 2322-4, 04
1255, 87666, Build, 3ED55, 5676-4, 01
, , Manuf, 98772, 13347-9, 01
, , Mater, 8YT76, , 

对应于: