Re: [xslt] cartesian product of lists



Am 14.07.2010 um 14:42 schrieb Michael Ludwig:

> Boris Boesler schrieb am 14.07.2010 um 13:56 (+0200):
> 
>> Can I post more code?
> 
> Yes. Ideally, post a cut-down but self-contained example that people can
> run at home to see what you're doing and what has to be changed to make
> it work as desired.

 Example XML file:

<?xml version="1.0"?>
<funny name="palettes">
  <colors name="list1">
    <alternative name="redish">
      <color name="red"/>
      <!--<color name="pink"/>-->
    </alternative>
    <alternative name="greenish">
      <color name="green1"/>
      <!--<color name="green2"/>-->
    </alternative>
  </colors>
  <colors name="list2">
    <alternative name="blueish">
      <color name="blue1"/>
      <!--<color name="blue2"/>-->
    </alternative>
    <alternative name="dark">
      <color name="black"/>
      <!--<color name="grey"/>-->
    </alternative>
  </colors>
  <palette name="palette1">
    <color-alternatives name="list1"/>
    <color-alternatives name="list2"/>
    <color name="white"/>
  </palette>
</funny>


The XSLT-stylesheet:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:exsl="http://exslt.org/common";
                extension-element-prefixes="exsl">

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

  <xsl:template match="/funny">
    <xsl:for-each select="palette">
      <xsl:call-template name="dump_palette">
        <xsl:with-param name="palette" select="."/>
        <xsl:with-param name="name" select="@name"/>
      </xsl:call-template>
    </xsl:for-each>
  </xsl:template>

  <!-- **************************************** -->
  <!--
      resolve normalform palettes
      - resolve color-lists
  -->
  <xsl:template name="dump_palette">
    <xsl:param name="palette"/>
    <xsl:param name="name"/>

    <!-- debugging, write to ouput file -->
    <xsl:for-each select="$palette">
      // Resolve patterns from: <xsl:value-of select="@name"/>
      // type: <xsl:value-of select="exsl:object-type(.)"/>
      // tree1: <xsl:copy-of select="."/>
      // tree2: <xsl:apply-templates select="."  mode="print"/>
      // alternatives:
      <xsl:for-each select="color-alternatives">
        // <xsl:value-of select="@name"/>,
      </xsl:for-each>
    </xsl:for-each>

    <xsl:choose>
      <xsl:when test="0 = count($palette/color-alternatives)">
        <xsl:message>
          // recursion ends in <xsl:value-of select="$name"/>:<xsl:value-of select="count($palette/color-alternatives)"/>.
        </xsl:message>
        <xsl:call-template name="dump_normalform_palette">
          <xsl:with-param name="palette" select="$palette"/>
          <xsl:with-param name="name"    select="$name"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:message>
          // recursion continues for <xsl:value-of select="$name"/>:<xsl:value-of select="count($palette/color-alternatives)"/>.
        </xsl:message>
        <!--
            unfold all alternative operands
        -->
        <xsl:for-each select="$palette/color-alternatives">
          <!-- resolve the first entry only -->
          <xsl:if test="1 = position()">
            <xsl:variable name="list" select="."/>
            <!-- list of alternatives -->
            <xsl:variable name="alternatives"
                          select="/funny/colors[ name = $list/@name]"/>
            <xsl:for-each select="$alternatives/alternative">
              <!-- a single alternative -->
              <xsl:variable name="alt" select="."/>
              
              <!-- new palette name -->
              <xsl:variable name="new_name">
                <xsl:value-of select="$palette/@name"/>_<xsl:value-of select="$list/@name"/>_<xsl:value-of select="$alt/@name"/>
              </xsl:variable>
              
              <!--
                  call dump_palette with a copy of palette node with
                  $list unfolded
              -->
              <xsl:for-each select="$palette">
                <xsl:variable name="new_palette">
                  <xsl:copy>
                    <xsl:attribute name="name">
                      <xsl:value-of select="$new_name"/>
                    </xsl:attribute>
                    <!--<xsl:value-of select="."/> ??-->
                    <!-- copy old palette colors, ok -->
                    <xsl:message>
                      // copy old colors
                    </xsl:message>
                    <xsl:for-each select="color">
                      <xsl:message>
                        // copy old color <xsl:value-of select="@name"/>
                      </xsl:message>
                      <xsl:copy-of select="."/>
                    </xsl:for-each>
                    <!-- resolve list with one element -->
                    <xsl:message>
                      // from alternative <xsl:value-of select="$alt/@name"/>
                    </xsl:message>
                    <xsl:for-each select="$alt/color">
                      <xsl:message>
                        // copy alternative color <xsl:value-of select="@name"/>
                      </xsl:message>
                      <xsl:copy-of select="."/>
                    </xsl:for-each>
                    <!-- copy other lists -->
                    <xsl:message>
                      // copy other lists
                    </xsl:message>
                    <xsl:for-each select="color-alternatives[ name != $list/@name]">
                      <xsl:message>
                        // copy other list <xsl:value-of select="@name"/>
                      </xsl:message>
                      <xsl:copy-of select="."/>
                    </xsl:for-each>
                  </xsl:copy>
                </xsl:variable>
                
                <!-- create new tempate -->
                <xsl:for-each select="exsl:node-set($new_palette)">
                  <xsl:message>
                    // new palette name: <xsl:value-of select="@name"/> vs <xsl:value-of select="$new_name"/>.
                  </xsl:message>
                  <xsl:comment>generated palette:</xsl:comment>
                  <xsl:apply-templates select="."  mode="print"/>
                </xsl:for-each>
                
                <xsl:variable name="new_palette_node">
                  <xsl:copy-of select="$new_palette"/>
                </xsl:variable>
                
                <!-- recursion -->
                <xsl:call-template name="dump_palette">
                  <xsl:with-param name="palette"
                                  select="exsl:node-set($new_palette)"/>
                  <xsl:with-param name="name"     select="$new_name"/>
                </xsl:call-template>
                
              </xsl:for-each> <!-- palette -->
            </xsl:for-each> <!-- $alternatives/alternative -->
          </xsl:if>
        </xsl:for-each> <!-- $palette/color-alternatives -->
        
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!--
      dump code to initialise palette array for the given palette
  -->
  <xsl:template name="dump_normalform_palette">
    <xsl:param name="palette"/>
    <xsl:param name="name"/>
    <!-- print all colors, for-each should be useless here  -->
    <!-- no attribute name and no colors here -->
    <p1 name="{$palette/@name}" name2="{$name}">
      <xsl:for-each select="$palette/color">
        <c name="{ name}"/>
      </xsl:for-each>
    </p1>
    <!-- all colors are present -->
    <p2 name="{$palette/@name}" name2="{$name}">
      <xsl:for-each select="$palette//color">
        <c name="{ name}"/>
      </xsl:for-each>
        <!-- these should have been resolved -->
        <xsl:for-each select="$palette//color-alternatives">
          <ca name="{ name}"/>
        </xsl:for-each>
    </p2>
  </xsl:template>

  <!--
      debugging: print
  -->
  <xsl:template match="*" mode="print">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates mode="print"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="comment()|processing-instruction()" mode="print">
    <xsl:copy />
  </xsl:template>

</xsl:stylesheet>


 Somehow my copying is wrong. I don't understand that mode="print" returns a correct XML-tree, but I can't access it properly.

Thanks,
Boris



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]