我经常需要生成测试数据文件,其中包含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>
答案 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>