xslt:在for-each上设置变量

时间:2013-03-22 12:02:40

标签: xml debugging xslt iteration reusability

我正在尝试使用XSLT从filemaker导出xml格式的一些数据。我想在xml上的三个位置显示相同的数据。我通过使用for-each标签一次显示数据。一些变量如何在这里使用,但我不知道如何。

<xsl:for-each select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW">
  <xsl:for-each select="fmp:COL[3]/fmpATA">
    <marker>
      <name>
        <xsl:value-of select="."/>
      </name>
      <xsl:variable name="pos" select="position()" />
      <comment>
        <xsl:value-of select="../../fmp:COL[6]/fmpATA[$pos]"/>
      </comment>
      <in>
        <xsl:value-of select="../../fmp:COL[4]/fmpATA[$pos]"/>
      </in>
      <out>
      <xsl:value-of select="../../fmp:COL[5]/fmpATA[$pos]"/>
      </out>
    </marker>
  </xsl:for-each>
</xsl:for-each>

但是当我想在同一个XML中的三个不同位置导出上述数据时,它就失败了。无论上面的数据是什么,都需要复制,以便我可以在同一个xslt的其他地方使用它。我不是XSLT的人,所以如果我不清楚,我会在开始时道歉。非常感谢

输出:

<?xml version="1.0" encoding="UTF-8"?>
<xmeml version="1">
<sequence id="test_clip">
<name>test_clip</name>
<duration>7704</duration>
<rate>
<ntsc>FALSE</ntsc>
<timebase>25</timebase>
</rate>
<timecode>
<rate>
<ntsc>FALSE</ntsc>
<timebase>25</timebase>
</rate>
<string/>
<frame>90000</frame>
<source>source</source>
<displayformat>NDF</displayformat>
</timecode>
<in>-1</in>
<out>-1</out>
<media>
<video>
<format>
<samplecharacteristics>
<width>1024</width>
<height>576</height>
<anamorphic>FALSE</anamorphic>
<pixelaspectratio>Square</pixelaspectratio>
<fielddominance>none</fielddominance>
<rate>
<ntsc>FALSE</ntsc>
<timebase>25</timebase>
</rate>
<colordepth>24</colordepth>
<codec>
<name>H.264</name>
<appspecificdata>
<appname>Final Cut Pro</appname>
<appmanufacturer>Apple Inc.</appmanufacturer>
<appversion>7.0</appversion>
<data>
<qtcodec>
<codecname>H.264</codecname>
<codectypename>H.264</codectypename>
<codectypecode>avc1</codectypecode>
<codecvendorcode>appl</codecvendorcode>
<spatialquality>1023</spatialquality>
<temporalquality>0</temporalquality>
<keyframerate>0</keyframerate>
<datarate>0</datarate>
</qtcodec>
</data>
</appspecificdata>
</codec>
</samplecharacteristics>
<appspecificdata>
<appname>Final Cut Pro</appname>
<appmanufacturer>Apple Inc.</appmanufacturer>
<appversion>7.0</appversion>
<data>
<fcpimageprocessing>
<useyuv>TRUE</useyuv>
<usesuperwhite>FALSE</usesuperwhite>
<rendermode>YUV8BPP</rendermode>
</fcpimageprocessing>
</data>
</appspecificdata>
</format>
<track>
<clipitem id="testclip3 ">
<name>testclip3</name>
<duration>7501</duration>
<rate>
<ntsc>FALSE</ntsc>
<timebase>25</timebase>
</rate>
<in>0</in>
<out>7501</out>
<start>203</start>
<end>7704</end>
<pixelaspectratio>Square</pixelaspectratio>
<enabled>TRUE</enabled>
<anamorphic>FALSE</anamorphic>
<alphatype>none</alphatype>
<masterclipid>testclip3 1</masterclipid>
<logginginfo>
<good>FALSE</good>
</logginginfo>
<file id="testclip3 2">
<name>testclip3.mov</name>
<pathurl>file://localhost/Users/itsupport/Desktop/testclip3.mov</pathurl>
<rate>
<timebase>25</timebase>
</rate>
<duration>7501</duration>
<media>
<video>
<duration>7501</duration>
<samplecharacteristics>
<width>1024</width>
<height>576</height>
</samplecharacteristics>
</video>
<audio>
<rate>
<timebase>48000</timebase>
</rate>
<trackcount>2</trackcount>
<samplecharacteristics>
<depth>16</depth>
</samplecharacteristics>
</audio>
</media>
</file>
<marker>
<name>Marker 1</name>
<comment>Man uses lit lighter to read postcard and sets fire to it accidentally</comment>
<in>911814</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 2</name>
<comment>Painting</comment>
<in>913654</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 3</name>
<comment/>
<in>914031</in>
<out>914032</out>
</marker>
<marker>
<name>Marker 4</name>
<comment>Women</comment>
<in>925375</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 5</name>
<comment>Old woman</comment>
<in>932350</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 6</name>
<comment>car accident</comment>
<in>933750</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 7</name>
<comment/>
<in>900000</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 8</name>
<comment/>
<in>943925</in>
<out>-1</out>
</marker>
<sourcetrack>
<mediatype>video</mediatype>
</sourcetrack>
<link>
<linkclipref>testclip3 </linkclipref>
<mediatype>video</mediatype>
<trackindex>1</trackindex>
<clipindex>1</clipindex>
</link>
<link>
<linkclipref>testclip3 3</linkclipref>
<mediatype>audio</mediatype>
<trackindex>1</trackindex>
<clipindex>1</clipindex>
<groupindex>1</groupindex>
</link>
<link>
<linkclipref>testclip3 4</linkclipref>
<mediatype>audio</mediatype>
<trackindex>2</trackindex>
<clipindex>1</clipindex>
<groupindex>1</groupindex>
</link>
<fielddominance>none</fielddominance>
</clipitem>
<enabled>TRUE</enabled>
<locked>FALSE</locked>
</track>
</video>
<audio/>
</media>
<ismasterclip>FALSE</ismasterclip>
<marker>
<name>Marker 1</name>
<comment>Man uses lit lighter to read postcard and sets fire to it accidentally</comment>
<in>911814</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 2</name>
<comment>Painting</comment>
<in>913654</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 3</name>
<comment/>
<in>914031</in>
<out>914032</out>
</marker>
<marker>
<name>Marker 4</name>
<comment>Women</comment>
<in>925375</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 5</name>
<comment>Old woman</comment>
<in>932350</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 6</name>
<comment>car accident</comment>
<in>933750</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 7</name>
<comment/>
<in>900000</in>
<out>-1</out>
</marker>
<marker>
<name>Marker 8</name>
<comment/>
<in>943925</in>
<out>-1</out>
</marker>
<filter>
<effect>
<name>Distort</name>
<effectid>deformation</effectid>
<effectcategory>motion</effectcategory>
<effecttype>motion</effecttype>
<mediatype>video</mediatype>
<parameter>
<parameterid>aspect</parameterid>
<name>Aspect</name>
<valuemin>-10000</valuemin>
<valuemax>10000</valuemax>
<value>33.3333</value>
</parameter>
</effect>
</filter>
</sequence>
</xmeml>

你会注意到marker1,2,3 ... 8标签在上面的xml中显示两次。这就是我想要显示xml的方式。 现在在XSLT中请注意我已经复制了“for-each”标签两次。这不起作用。 XSLT:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" 
xmlns:fmp="http://www.filemaker.com/fmpxmlresult"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="fmp">

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

<xsl:template match="/">

<xmeml version="1">
<sequence id="test_clip">
    <name>test_clip</name>
    <duration>7704</duration>
    <rate>
        <ntsc>FALSE</ntsc>
        <timebase>25</timebase>
    </rate>
    <timecode>
        <rate>
            <ntsc>FALSE</ntsc>
            <timebase>25</timebase>
        </rate>
        <string><xsl:value-of select="fmp:COL[1]/fmp:DATA"/></string>
        <frame>90000</frame>
        <source>source</source>
        <displayformat>NDF</displayformat>
    </timecode>
    <in>-1</in>
    <out>-1</out>
    <media>
        <video><format>
                <samplecharacteristics>
                    <width>1024</width>
                    <height>576</height>
                    <anamorphic>FALSE</anamorphic>
                    <pixelaspectratio>Square</pixelaspectratio>
                    <fielddominance>none</fielddominance>
                    <rate>
                        <ntsc>FALSE</ntsc>
                        <timebase>25</timebase>
                    </rate>
                    <colordepth>24</colordepth>
                    <codec>
                        <name>H.264</name>
                        <appspecificdata>
                            <appname>Final Cut Pro</appname>
                            <appmanufacturer>Apple Inc.</appmanufacturer>
                            <appversion>7.0</appversion>
                            <data>
                                <qtcodec>
                                    <codecname>H.264</codecname>
                                    <codectypename>H.264</codectypename>
                                    <codectypecode>avc1</codectypecode>
                                    <codecvendorcode>appl</codecvendorcode>
                                    <spatialquality>1023</spatialquality>
                                    <temporalquality>0</temporalquality>
                                    <keyframerate>0</keyframerate>
                                    <datarate>0</datarate>
                                </qtcodec>
                            </data>
                        </appspecificdata>
                    </codec>
                </samplecharacteristics>
                <appspecificdata>
                    <appname>Final Cut Pro</appname>
                    <appmanufacturer>Apple Inc.</appmanufacturer>
                    <appversion>7.0</appversion>
                    <data>
                        <fcpimageprocessing>
                            <useyuv>TRUE</useyuv>
                            <usesuperwhite>FALSE</usesuperwhite>
                            <rendermode>YUV8BPP</rendermode>
                        </fcpimageprocessing>
                    </data>
                </appspecificdata>
            </format>
            <track>
                <clipitem id="testclip3 ">
                    <name>testclip3</name>
                    <duration>7501</duration>
                    <rate>
                        <ntsc>FALSE</ntsc>
                        <timebase>25</timebase>
                    </rate>
                    <in>0</in>
                    <out>7501</out>
                    <start>203</start>
                    <end>7704</end>
                    <pixelaspectratio>Square</pixelaspectratio>
                    <enabled>TRUE</enabled>
                    <anamorphic>FALSE</anamorphic>
                    <alphatype>none</alphatype>
                    <masterclipid>testclip3 1</masterclipid>
                    <logginginfo>
                        <good>FALSE</good>
                    </logginginfo>
                    <file id="testclip3 2">
                        <name>testclip3.mov</name>
                        <pathurl>file://localhost/Users/itsupport/Desktop/testclip3.mov</pathurl>
                        <rate>
                            <timebase>25</timebase>
                        </rate>
                        <duration>7501</duration>
                        <media>
                            <video>
                                <duration>7501</duration>
                                <samplecharacteristics>
                                    <width>1024</width>
                                    <height>576</height>
                                </samplecharacteristics>
                            </video>
                            <audio>
                                <rate>
                                    <timebase>48000</timebase>
                                </rate>
                                <trackcount>2</trackcount>
                                <samplecharacteristics>
                                    <depth>16</depth>
                                </samplecharacteristics>
                            </audio>
                        </media>
                    </file>

        <xsl:for-each select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW">

    <xsl:for-each select="fmp:COL[3]/fmp:DATA">
        <marker>
        <name>
            <xsl:value-of select="."/>
        </name>
            <xsl:variable name="pos" select="position()" />

            <comment>
            <xsl:value-of select="../../fmp:COL[6]/fmp:DATA[$pos]"/>
            </comment>

            <in>
            <xsl:value-of select="../../fmp:COL[4]/fmp:DATA[$pos]"/>
            </in>

            <out>
            <xsl:value-of select="../../fmp:COL[5]/fmp:DATA[$pos]"/>
            </out>

        </marker>
    </xsl:for-each>

</xsl:for-each>




                    <sourcetrack>
                        <mediatype>video</mediatype>
                    </sourcetrack>
                    <link>
                        <linkclipref>testclip3 </linkclipref>
                        <mediatype>video</mediatype>
                        <trackindex>1</trackindex>
                        <clipindex>1</clipindex>
                    </link>
                    <link>
                        <linkclipref>testclip3 3</linkclipref>
                        <mediatype>audio</mediatype>
                        <trackindex>1</trackindex>
                        <clipindex>1</clipindex>
                        <groupindex>1</groupindex>
                    </link>
                    <link>
                        <linkclipref>testclip3 4</linkclipref>
                        <mediatype>audio</mediatype>
                        <trackindex>2</trackindex>
                        <clipindex>1</clipindex>
                        <groupindex>1</groupindex>
                    </link>
                    <fielddominance>none</fielddominance>
                </clipitem>
                <enabled>TRUE</enabled>
                <locked>FALSE</locked>
            </track>

            </video>
        <audio></audio>
        </media>
            <ismasterclip>FALSE</ismasterclip>

        <xsl:for-each select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW">

    <xsl:for-each select="fmp:COL[3]/fmp:DATA">
        <marker>
        <name>
            <xsl:value-of select="."/>
        </name>
            <xsl:variable name="pos" select="position()" />

            <comment>
            <xsl:value-of select="../../fmp:COL[6]/fmp:DATA[$pos]"/>
            </comment>

            <in>
            <xsl:value-of select="../../fmp:COL[4]/fmp:DATA[$pos]"/>
            </in>

            <out>
            <xsl:value-of select="../../fmp:COL[5]/fmp:DATA[$pos]"/>
            </out>

        </marker>
    </xsl:for-each>

</xsl:for-each>

<filter>
        <effect>
        <name>Distort</name>
        <effectid>deformation</effectid>
        <effectcategory>motion</effectcategory>
        <effecttype>motion</effecttype>
        <mediatype>video</mediatype>
            <parameter>
                <parameterid>aspect</parameterid>
                <name>Aspect</name>
                <valuemin>-10000</valuemin>
                <valuemax>10000</valuemax>
                <value>33.3333</value>
            </parameter>
        </effect>
    </filter>
</sequence>
</xmeml>

</xsl:template>
</xsl:stylesheet>

3 个答案:

答案 0 :(得分:1)

如果您向我们展示样本输入和输出,那将非常有用。但是根据你的描述,你想要做的是在变量中捕获xsl:-each的结果:

<xsl:variable name="temp">
  <xsl:for-each select="...">

  </xsl:for-each>
</xsl:variable>

唯一需要注意的是,在XSLT 1.0中,$ temp的值是“结果树片段”,并且对如何使用它有严重的限制;通常需要使用特定于供应商的xx:node-set()扩展名将其转换为普通节点。

答案 1 :(得分:0)

您可以拆分循环的定义和执行。

然后你的循环变为:

<xsl:template match="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW">
  <xsl:for-each select="fmp:COL[3]/fmpATA">
    <marker>
      <name>
        <xsl:value-of select="."/>
      </name>
      <xsl:variable name="pos" select="position()" />
      <comment>
        <xsl:value-of select="../../fmp:COL[6]/fmpATA[$pos]"/>
      </comment>
      <in>
        <xsl:value-of select="../../fmp:COL[4]/fmpATA[$pos]"/>
      </in>
      <out>
        <xsl:value-of select="../../fmp:COL[5]/fmpATA[$pos]"/>
      </out>
    </marker>
  </xsl:for-each>
</xsl:template>

无论何时你想调用那个循环你都要做

<xsl:apply-templates select="/fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW" />

答案 2 :(得分:0)

正如Michael Kay所提到的,您可以在变量中捕获for-each的结果,然后您可以使用xsl:copy-of在任何需要的地方输出它,如下所示:

<xsl:stylesheet version="1.0"
    xmlns:fmp="http://www.filemaker.com/fmpxmlresult"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="fmp">

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

  <xsl:template match="/">

    <xsl:variable name="rowData">
      <xsl:for-each select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW">
        <xsl:for-each select="fmp:COL[3]/fmp:DATA">
          <marker>
            <name>
              <xsl:value-of select="."/>
            </name>
            <xsl:variable name="pos" select="position()" />

            <comment>
              <xsl:value-of select="../../fmp:COL[6]/fmp:DATA[$pos]"/>
            </comment>

            <in>
              <xsl:value-of select="../../fmp:COL[4]/fmp:DATA[$pos]"/>
            </in>

            <out>
              <xsl:value-of select="../../fmp:COL[5]/fmp:DATA[$pos]"/>
            </out>

          </marker>
        </xsl:for-each>
      </xsl:for-each>
    </xsl:variable>

    <xmeml version="1">
      <sequence id="test_clip">
        <name>test_clip</name>
        <duration>7704</duration>
        <rate>
          <ntsc>FALSE</ntsc>
          <timebase>25</timebase>
        </rate>
        <timecode>
          <rate>
            <ntsc>FALSE</ntsc>
            <timebase>25</timebase>
          </rate>
          <string>
            <xsl:value-of select="fmp:COL[1]/fmp:DATA"/>
          </string>
          <frame>90000</frame>
          <source>source</source>
          <displayformat>NDF</displayformat>
        </timecode>
        <in>-1</in>
        <out>-1</out>
        <media>
          ...

          <!-- Output the variable -->
          <xsl:copy-of select="rowData"/>
          <audio></audio>
        </media>
        <ismasterclip>FALSE</ismasterclip>

        <!-- Output the variable -->
        <xsl:copy-of select="$rowData"/>
        <filter>
          <effect>
            ...
          </effect>
        </filter>
      </sequence>
    </xmeml>
  </xsl:template>
</xsl:stylesheet>

一种更具可读性的方法是将for-each分离为命名模板并在需要的地方调用:

<xsl:stylesheet version="1.0"
    xmlns:fmp="http://www.filemaker.com/fmpxmlresult"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="fmp">

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

  <xsl:template match="/">

    <xmeml version="1">
      <sequence id="test_clip">
        <name>test_clip</name>
        <duration>7704</duration>
        <rate>
          <ntsc>FALSE</ntsc>
          <timebase>25</timebase>
        </rate>
        <timecode>
          <rate>
            <ntsc>FALSE</ntsc>
            <timebase>25</timebase>
          </rate>
          <string>
            <xsl:value-of select="fmp:COL[1]/fmp:DATA"/>
          </string>
          <frame>90000</frame>
          <source>source</source>
          <displayformat>NDF</displayformat>
        </timecode>
        <in>-1</in>
        <out>-1</out>
        <media>
          ...

          <!-- Call the template -->
          <xsl:call-template name="RowData" />
          <audio></audio>
        </media>
        <ismasterclip>FALSE</ismasterclip>

        <!-- Call the template -->
        <xsl:call-template name="RowData" />
        <filter>
          <effect>
            ...
          </effect>
        </filter>
      </sequence>
    </xmeml>
  </xsl:template>

  <xsl:template name="RowData">
    <xsl:for-each select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW">
      <xsl:for-each select="fmp:COL[3]/fmp:DATA">
        <marker>
          <name>
            <xsl:value-of select="."/>
          </name>
          <xsl:variable name="pos" select="position()" />

          <comment>
            <xsl:value-of select="../../fmp:COL[6]/fmp:DATA[$pos]"/>
          </comment>

          <in>
            <xsl:value-of select="../../fmp:COL[4]/fmp:DATA[$pos]"/>
          </in>

          <out>
            <xsl:value-of select="../../fmp:COL[5]/fmp:DATA[$pos]"/>
          </out>

        </marker>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

但最干净,最常用的XSLT方法是正确使用模式匹配模板,完全摆脱for-each es:

<xsl:stylesheet version="1.0"
    xmlns:fmp="http://www.filemaker.com/fmpxmlresult"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="fmp">

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

  <xsl:template match="/">

    <!-- Store a variable with all the source rows, for easy access -->
    <xsl:variable name="rows" select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW" />

    <xmeml version="1">
      <sequence id="test_clip">
        <name>test_clip</name>
        <duration>7704</duration>
        <rate>
          <ntsc>FALSE</ntsc>
          <timebase>25</timebase>
        </rate>
        <timecode>
          <rate>
            <ntsc>FALSE</ntsc>
            <timebase>25</timebase>
          </rate>
          <string>
            <xsl:value-of select="fmp:COL[1]/fmp:DATA"/>
          </string>
          <frame>90000</frame>
          <source>source</source>
          <displayformat>NDF</displayformat>
        </timecode>
        <in>-1</in>
        <out>-1</out>
        <media>
          ...

          <!-- Apply templates to the rows -->
          <xsl:apply-templates select="$rows" />
          <audio></audio>
        </media>
        <ismasterclip>FALSE</ismasterclip>

        <!-- Apply templates to the rows -->
        <xsl:apply-templates select="$rows" />
        <filter>
          <effect>
            ...
          </effect>
        </filter>
      </sequence>
    </xmeml>
  </xsl:template>

  <xsl:template match="fmp:ROW">
    <xsl:apply-templates select="fmp:COL[3]/fmp:DATA" />
  </xsl:template>

  <xsl:template match="fmp:DATA">
    <marker>
      <name>
        <xsl:value-of select="."/>
      </name>
      <xsl:variable name="pos" select="position()" />

      <comment>
        <xsl:value-of select="../../fmp:COL[6]/fmp:DATA[$pos]"/>
      </comment>

      <in>
        <xsl:value-of select="../../fmp:COL[4]/fmp:DATA[$pos]"/>
      </in>

      <out>
        <xsl:value-of select="../../fmp:COL[5]/fmp:DATA[$pos]"/>
      </out>

    </marker>
  </xsl:template>
</xsl:stylesheet>