Xslt 如何对嵌套元素进行笛卡尔积?
鉴于这些数据:Xslt 如何对嵌套元素进行笛卡尔积?,xslt,permutation,self-join,cartesian-product,Xslt,Permutation,Self Join,Cartesian Product,鉴于这些数据: <?xml version='1.0' encoding='utf-8'?> <data> <pricePoint> <optionGroup id='g1'> <option id='a1'>a1</option> <option id='a2'>a2</option> </optionGr
<?xml version='1.0' encoding='utf-8'?>
<data>
<pricePoint>
<optionGroup id='g1'>
<option id='a1'>a1</option>
<option id='a2'>a2</option>
</optionGroup>
<optionGroup id='g2'>
<option id='b1'>b1</option>
<option id='b2'>b2</option>
</optionGroup>
<optionGroup id='g3'>
<option id='c1'>c1</option>
<option id='c2'>c2</option>
</optionGroup>
</pricePoint>
</data>
a1
a2
b1
b2
c1
c2
我寻求的结果是:
<result>
<variant>
<option id='a1'>a1</option>
<option id='b1'>b1</option>
<option id='c1'>c1</option>
</variant>
<variant>
<option id='a1'>a1</option>
<option id='b1'>b1</option>
<option id='c2'>c2</option>
</variant>
<variant>
<option id='a1'>a1</option>
<option id='b2'>b2</option>
<option id='c1'>c1</option>
</variant>
<variant>
<option id='a1'>a1</option>
<option id='b2'>b2</option>
<option id='c2'>c2</option>
</variant>
<variant>
<option id='a2'>a2</option>
<option id='b1'>b1</option>
<option id='c1'>c1</option>
</variant>
<variant>
<option id='a2'>a2</option>
<option id='b1'>b1</option>
<option id='c2'>c2</option>
</variant>
<variant>
<option id='a2'>a2</option>
<option id='b2'>b2</option>
<option id='c1'>c1</option>
</variant>
<variant>
<option id='a2'>a2</option>
<option id='b2'>b2</option>
<option id='c2'>c2</option>
</variant>
</result>
a1
b1
c1
a1
b1
c2
a1
b2
c1
a1
b2
c2
a2
b1
c1
a2
b1
c2
a2
b2
c1
a2
b2
c2
就是
,遍历所有其他
s
并将其
与“当前”元素“连接”,生成一个包含结果文档中所有这些
的元素
元素中
元素的数量未知(一个或多个),任何
元素中
元素的数量也未知(一个或多个)
据我所知,这是一个制作笛卡尔产品的经典案例,但我不知道如何用XSLT1.0正确实现这一点
到目前为止,我(相当无助)的尝试围绕着这样一个想法:在处理其中一个元素并试图将其排除在进一步处理之外时,应用模板匹配
元素,如下所示:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="optionGroup">
<xsl:message>Saw optionGroup <xsl:value-of select="@id" /></xsl:message>
<xsl:variable name="id" select="@id" />
<xsl:apply-templates select="../optionGroup[@id != $id]" />
</xsl:template>
<xsl:template match="option">
<xsl:message>Saw option</xsl:message>
</xsl:template>
</xsl:stylesheet>
锯选组
锯选项
当然,到目前为止,我的所有尝试在应用模板时都以无限递归失败。这里有一个方法,尽管我不确定它的效率,因为它必须重复创建以前节点的副本
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="pricePoint">
<xsl:apply-templates select="optionGroup[1]/option" />
</xsl:template>
<xsl:template match="optionGroup[following-sibling::*]/option">
<xsl:param name="previous" />
<xsl:apply-templates select="../following-sibling::optionGroup[1]/option">
<xsl:with-param name="previous">
<xsl:if test="$previous">
<xsl:copy-of select="$previous" />
</xsl:if>
<xsl:copy-of select="." />
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="option">
<xsl:param name="previous" />
<variant>
<xsl:copy-of select="$previous" />
<xsl:copy-of select="." />
</variant>
</xsl:template>
</xsl:stylesheet>
我认为你不需要这些拷贝,你可以把这些元素传下去:“你说得对!我把事情复杂化了一点。根据你的评论,我在回答中添加了一个新的改进版本。非常感谢。谢谢你们,@MartinHonnen和Tim!我开始认为仅使用XSLT并不能真正解决这个问题,因为它需要从“last”集中的每个元素进行某种回溯,我不知道如何实现它。很高兴我错了。再次感谢!我还将
缩短为
。
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="pricePoint">
<xsl:apply-templates select="optionGroup[1]/option" />
</xsl:template>
<xsl:template match="optionGroup[following-sibling::*]/option">
<xsl:param name="previous" select="/.." />
<xsl:apply-templates select="../following-sibling::optionGroup[1]/option">
<xsl:with-param name="previous" select="$previous | ." />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="option">
<xsl:param name="previous" />
<variant>
<xsl:copy-of select="$previous" />
<xsl:copy-of select="." />
</variant>
</xsl:template>
</xsl:stylesheet>