生成所有值的组合

时间:2018-03-16 13:47:03

标签: xml xslt

我经常需要生成测试数据文件,其中包含3或4个字段的所有可能值。这是一个包含3个值的示例XML(但通常还有更多......)

 <xml>
  <dataset  name="service">
    <row name="Tracked" code="T"/>
    <row name="Untracked" code="U"/>
  </dataset>

   <dataset name="terminal">
    <row name="New York" code="JFK"/>
    <row name="Newark" code="EWR"/>
    <row name="Chicago" code="ORD" />
  </dataset>

  <dataset name="lodgement">
    <row name="Melbourne" code="MEL" />
    <row name="Perth" code="PER" />
    <row name="Sydney" code="SYD"/>
  </dataset>
</xml>

我希望创建以下输出

<xml>
    <row service='T' terminal='JFK' lodgement='MEL'/>
    <row service='T' terminal='JFK' lodgement='PER'/>
    <row service='T' terminal='JFK' lodgement='SYD'/>

    <row service='T' terminal='EWR' lodgement='MEL'/>
    <row service='T' terminal='EWR' lodgement='PER'/>
    <row service='T' terminal='EWR' lodgement='SYD'/>

    <row service='T' terminal='ORD' lodgement='MEL'/>
    <row service='T' terminal='ORD' lodgement='PER'/>
    <row service='T' terminal='ORD' lodgement='SYD'/>

    <row service='U' terminal='JFK' lodgement='MEL'/>
    <row service='U' terminal='JFK' lodgement='PER'/>
    <row service='U' terminal='JFK' lodgement='SYD'/>

    <row service='U' terminal='EWR' lodgement='MEL'/>
    <row service='U' terminal='EWR' lodgement='PER'/>
    <row service='U' terminal='EWR' lodgement='SYD'/>

    <row service='U' terminal='ORD' lodgement='MEL'/>
    <row service='U' terminal='ORD' lodgement='PER'/>
    <row service='U' terminal='ORD' lodgement='SYD'/>
</xml> 

我有这个XSL工作,但它在这种情况下完全硬编码,我正在寻找一个适用于任意数量数据集的通用解决方案。

<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name='servicerow' select='//dataset[@name="service"]/row'/>
<xsl:variable name='terminalrow' select='//dataset[@name="terminal"]/row'/>
<xsl:variable name='lodgementrow' select='//dataset[@name="lodgement"]/row'/>

<xsl:template match='/'>
    <xml>
        <xsl:for-each select='$servicerow'>
            <xsl:variable name='service' select='@code'/>
            <xsl:for-each select='$terminalrow'>
                <xsl:variable name='terminal' select='@code'/>
                <xsl:for-each select='$lodgementrow'>
                    <xsl:variable name='lodgement' select='@code'/>
                    <xsl:element name='row'>
                        <xsl:attribute name='service'><xsl:value-of select='$service'/></xsl:attribute>
                        <xsl:attribute name='terminal'><xsl:value-of select='$terminal'/></xsl:attribute>
                        <xsl:attribute name='lodgement'><xsl:value-of select='$lodgement'/></xsl:attribute>
                    </xsl:element>
                </xsl:for-each> <!-- lodgement -->
            </xsl:for-each> <!-- terminal -->
        </xsl:for-each> <!-- service -->
    </xml>
</xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:3)

这会为你做这件事吗....

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" indent="yes" />

<xsl:template match='/xml'>
    <xml>
        <xsl:apply-templates select="dataset[1]/row" />
    </xml>
</xsl:template>

<xsl:template match="row">
    <xsl:param name="prev" />
    <xsl:choose>
        <xsl:when test="../following-sibling::dataset">
            <xsl:choose>
                <xsl:when test="$prev">
                    <xsl:apply-templates select="../following-sibling::dataset[1]/row">
                       <xsl:with-param name="prev" select=". | $prev" />
                    </xsl:apply-templates>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="../following-sibling::dataset[1]/row">
                       <xsl:with-param name="prev" select="." />
                    </xsl:apply-templates>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
            <row>
                <xsl:for-each select="$prev|.">
                    <xsl:attribute name="{../@name}">
                        <xsl:value-of select="@code" />
                    </xsl:attribute>
                </xsl:for-each>
            </row>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>