Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xslt 如何对嵌套元素进行笛卡尔积?_Xslt_Permutation_Self Join_Cartesian Product - Fatal编程技术网

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>