XSLT 计数器递归和传递参数
XSLT Counters Recursion and Passing Parameters
我已经能够创建一个 XSLT(包含)以将源 XML 转换为所需的目标 XML 格式(包含),但是我相信这可以利用一些内置的优化XSLT 功能超出了我的熟练程度。感谢任何想法。
核心要求是输入 XML 包含 header 值和数据(第一条记录包含 header/labels,后续记录包含相应标签的数据,因此输出数据是位置与第一条记录匹配),OutPut XML 包含名称值对,名称描述数据元素(header/label 来自源中的第一条记录)并且元素是 "labelXX","valueXX",因此需要计数器递增 XX。输出还包含一个 header 记录,它基本上只包含元素的名称,其余的可以从输出中自行解释。
来源XML
<?xml version="1.0" encoding="UTF-8"?>
<SpecExportFF>
<recordset>
<value>12345</value>
<value>xyz</value>
<value>a0</value>
<value>b0</value>
<value>c0</value>
<value>d0</value>
<value>e0</value>
<value>f0</value>
<value>g0</value>
<value>h0</value>
<value>i0</value>
<value>j0</value>
<value>k0</value>
<value>l0</value>
<value>m0</value>
<value>n0</value>
<value>o0</value>
<value>p0</value>
<value>q0</value>
<value>r0</value>
<value>s0</value>
<value>t0</value>
<value>a1</value>
<value>b1</value>
<value>c1</value>
<value>d1</value>
<value>e1</value>
<value>f1</value>
<value>g1</value>
<value>h1</value>
<value>i1</value>
<value>j1</value>
<value>k1</value>
<value>l1</value>
<value>m1</value>
<value>n1</value>
<value>o1</value>
<value>p1</value>
<value>q1</value>
<value>r1</value>
<value>s1</value>
<value>t1</value>
<value>a2</value>
<value>b2</value>
<value>c2</value>
<value>d2</value>
<value>e2</value>
<value>f2</value>
<value>g2</value>
<value>h2</value>
<value>i2</value>
<value>j2</value>
<value>k2</value>
<value>l2</value>
<value>m2</value>
<value>n2</value>
<value>o2</value>
<value>p2</value>
<value>q2</value>
<value>r2</value>
<value>s2</value>
<value>t2</value>
</recordset>
<recordset>
<value>A12345</value>
<value>snacks</value>
<value>1</value>
<value>cereals</value>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
</recordset>
<recordset>
<value>A245678</value>
<value>snacks</value>
<value>1</value>
<value>chips</value>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value>potato</value>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value>fried</value>
<value/>
<value></value>
<value/>
<value>baked</value>
<value></value>
<value></value>
<value></value>
<value/>
<value></value>
<value/>
<value>20g</value>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value></value>
</recordset>
</SpecExportFF>
输出目标XML
<?xml version="1.0" encoding="UTF-8"?>
<SpecExportOutputFF>
<header>
<item>item</item>
<category>category</category>
<label01>label01</label01>
<spec01>spec01</spec01>
<label02>label02</label02>
<spec02>spec02</spec02>
<label03>label03</label03>
<spec03>spec03</spec03>
<label04>label04</label04>
<spec04>spec04</spec04>
<label05>label05</label05>
<spec05>spec05</spec05>
<label06>label06</label06>
<spec06>spec06</spec06>
<label07>label07</label07>
<spec07>spec07</spec07>
<label08>label08</label08>
<spec08>spec08</spec08>
<label09>label09</label09>
<spec09>spec09</spec09>
<label10>label10</label10>
<spec10>spec10</spec10>
<label11>label11</label11>
<spec11>spec11</spec11>
<label12>label12</label12>
<spec12>spec12</spec12>
<label13>label13</label13>
<spec13>spec13</spec13>
<label14>label14</label14>
<spec14>spec14</spec14>
<label15>label15</label15>
<spec15>spec15</spec15>
<label16>label16</label16>
<spec16>spec16</spec16>
<label17>label17</label17>
<spec17>spec17</spec17>
<label18>label18</label18>
<spec18>spec18</spec18>
<label19>label19</label19>
<spec19>spec19</spec19>
<label20>label20</label20>
<spec20>spec20</spec20>
<label21>label21</label21>
<spec21>spec21</spec21>
<label22>label22</label22>
<spec22>spec22</spec22>
<label23>label23</label23>
<spec23>spec23</spec23>
<label24>label24</label24>
<spec24>spec24</spec24>
<label25>label25</label25>
<spec25>spec25</spec25>
<label26>label26</label26>
<spec26>spec26</spec26>
<label27>label27</label27>
<spec27>spec27</spec27>
<label28>label28</label28>
<spec28>spec28</spec28>
<label29>label29</label29>
<spec29>spec29</spec29>
<label30>label30</label30>
<spec30>spec30</spec30>
<label31>label31</label31>
<spec31>spec31</spec31>
<label32>label32</label32>
<spec32>spec32</spec32>
<label33>label33</label33>
<spec33>spec33</spec33>
<label34>label34</label34>
<spec34>spec34</spec34>
<label35>label35</label35>
<spec35>spec35</spec35>
<label36>label36</label36>
<spec36>spec36</spec36>
<label37>label37</label37>
<spec37>spec37</spec37>
<label38>label38</label38>
<spec38>spec38</spec38>
<label39>label39</label39>
<spec39>spec39</spec39>
<label40>label40</label40>
<spec40>spec40</spec40>
<label41>label41</label41>
<spec41>spec41</spec41>
<label42>label42</label42>
<spec42>spec42</spec42>
<label43>label43</label43>
<spec43>spec43</spec43>
<label44>label44</label44>
<spec44>spec44</spec44>
<label45>label45</label45>
<spec45>spec45</spec45>
<label46>label46</label46>
<spec46>spec46</spec46>
<label47>label47</label47>
<spec47>spec47</spec47>
<label48>label48</label48>
<spec48>spec48</spec48>
<label49>label49</label49>
<spec49>spec49</spec49>
<label50>label50</label50>
<spec50>spec50</spec50>
<label51>label51</label51>
<spec51>spec51</spec51>
<label52>label52</label52>
<spec52>spec52</spec52>
<label53>label53</label53>
<spec53>spec53</spec53>
<label54>label54</label54>
<spec54>spec54</spec54>
<label55>label55</label55>
<spec55>spec55</spec55>
<label56>label56</label56>
<spec56>spec56</spec56>
<label57>label57</label57>
<spec57>spec57</spec57>
<label58>label58</label58>
<spec58>spec58</spec58>
<label59>label59</label59>
<spec59>spec59</spec59>
<label60>label60</label60>
<spec60>spec60</spec60>
</header>
<data>
<item>A12345</item>
<category>snacks</category>
<label01>a0</label01>
<spec01>1</spec01>
<label02>b0</label02>
<spec02>cereals</spec02>
</data>
<data>
<item>A245678</item>
<category>snacks</category>
<label01>a0</label01>
<spec01>1</spec01>
<label02>b0</label02>
<spec02>chips</spec02>
<label03>q0</label03>
<spec03>potato</spec03>
<label04>e1</label04>
<spec04>fried</spec04>
<label05>i1</label05>
<spec05>baked</spec05>
<label06>p1</label06>
<spec06>20g</spec06>
</data>
</SpecExportOutputFF>
我的 XSLT(它可以工作,但在我看来太复杂了,想对其进行优化)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/SpecExportFF">
<SpecExportOutputFF>
<xsl:for-each select="recordset">
<xsl:variable name="IndexOfCurrentRecordset">
<xsl:value-of select="position()"/>
</xsl:variable>
<xsl:if test="$IndexOfCurrentRecordset = 1">
<header>
<xsl:for-each select="value">
<xsl:variable name="IndexOfCurrentNode" select="position()"/>
<xsl:variable name="ElementSuffix" select="format-number(($IndexOfCurrentNode - 2),'00')"/>
<!--<hello1><xsl:value-of select="$IndexOfCurrentNode"/></hello1>-->
<xsl:choose>
<xsl:when test="$IndexOfCurrentNode = 1">
<xsl:element name="item">item</xsl:element>
</xsl:when>
<xsl:when test="$IndexOfCurrentNode = 2">
<xsl:element name="category">category</xsl:element>
</xsl:when>
<xsl:when test="($IndexOfCurrentNode > 2)">
<xsl:element name="{concat('label',$ElementSuffix)}">
<xsl:value-of select="concat('label',$ElementSuffix)"/>
</xsl:element>
<xsl:element name="{concat('spec',$ElementSuffix)}">
<xsl:value-of select="concat('spec',$ElementSuffix)"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</header>
</xsl:if>
<xsl:if test="$IndexOfCurrentRecordset > 1">
<data>
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="1"/>
<xsl:with-param name="currentNode" select="./value[1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="1"/>
</xsl:call-template>
</data>
</xsl:if>
</xsl:for-each>
</SpecExportOutputFF>
</xsl:template>
<xsl:template name="iterate_values">
<xsl:param name="i"/>
<xsl:param name="currentNode"/>
<xsl:param name="IndexOfCurrentRecordset"/>
<xsl:param name="IndexOfCurrentNode"/>
<xsl:variable name="ElementSuffix" select="format-number($i,'00')"/>
<xsl:choose>
<xsl:when test="$IndexOfCurrentNode = 1">
<xsl:element name="item">
<xsl:value-of select="$currentNode/text()"/>
</xsl:element>
<xsl:if test="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]">
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="$i"/>
<xsl:with-param name="currentNode" select="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="$IndexOfCurrentNode+1"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:when test="$IndexOfCurrentNode = 2">
<xsl:element name="category">
<xsl:value-of select="$currentNode/text()"/>
</xsl:element>
<xsl:if test="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]">
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="$i"/>
<xsl:with-param name="currentNode" select="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="$IndexOfCurrentNode+1"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:when test="$IndexOfCurrentNode > 2 and $currentNode/text() != ''">
<xsl:element name="{concat('label',$ElementSuffix)}">
<xsl:value-of select="/*/*[1]/value[$IndexOfCurrentNode]"/>
</xsl:element>
<xsl:element name="{concat('spec',$ElementSuffix)}">
<xsl:value-of select="$currentNode/text()"/>
</xsl:element>
<xsl:if test="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]">
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="$i+1"/>
<xsl:with-param name="currentNode" select="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="$IndexOfCurrentNode+1"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]">
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="$i"/>
<xsl:with-param name="currentNode" select="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="$IndexOfCurrentNode+1"/>
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
为了挑战,我想出了你想要做的事情。我认为主要问题是您在命令式思考,但需要转换您的思维方式,因为 XSLT 是一种函数式语言,而且情况非常不同。
确实,这就是我想出的...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:variable name="labels" select="/SpecExportFF/recordset[1]/value[position() > 2]" />
<xsl:template match="SpecExportFF">
<SpecExportOutputFF>
<xsl:apply-templates select="recordset" />
</SpecExportOutputFF>
</xsl:template>
<xsl:template match="recordset[1]">
<header>
<item>item</item>
<category>category</category>
<xsl:for-each select="value">
</xsl:for-each>
</header>
</xsl:template>
<xsl:template match="recordset[1]">
<header>
<item>item</item>
<category>category</category>
<xsl:for-each select="value[position() > 2]">
<xsl:variable name="ElementSuffix" select="format-number(position(),'00')"/>
<xsl:element name="{concat('label',$ElementSuffix)}">
<xsl:value-of select="concat('label',$ElementSuffix)"/>
</xsl:element>
<xsl:element name="{concat('spec',$ElementSuffix)}">
<xsl:value-of select="concat('spec',$ElementSuffix)"/>
</xsl:element>
</xsl:for-each>
</header>
</xsl:template>
<xsl:template match="recordset">
<data>
<item><xsl:value-of select="value[1]" /></item>
<category><xsl:value-of select="value[2]" /></category>
<xsl:for-each select="value[position() > 2][normalize-space()]">
<xsl:variable name="ElementSuffix" select="format-number(position(),'00')"/>
<xsl:variable name="LabelPos" select="count(preceding-sibling::value) - 1" />
<xsl:element name="{concat('label',$ElementSuffix)}">
<xsl:value-of select="$labels[position() = $LabelPos]" />
</xsl:element>
<xsl:element name="{concat('spec',$ElementSuffix)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</data>
</xsl:template>
</xsl:stylesheet>
我已经能够创建一个 XSLT(包含)以将源 XML 转换为所需的目标 XML 格式(包含),但是我相信这可以利用一些内置的优化XSLT 功能超出了我的熟练程度。感谢任何想法。
核心要求是输入 XML 包含 header 值和数据(第一条记录包含 header/labels,后续记录包含相应标签的数据,因此输出数据是位置与第一条记录匹配),OutPut XML 包含名称值对,名称描述数据元素(header/label 来自源中的第一条记录)并且元素是 "labelXX","valueXX",因此需要计数器递增 XX。输出还包含一个 header 记录,它基本上只包含元素的名称,其余的可以从输出中自行解释。
来源XML
<?xml version="1.0" encoding="UTF-8"?>
<SpecExportFF>
<recordset>
<value>12345</value>
<value>xyz</value>
<value>a0</value>
<value>b0</value>
<value>c0</value>
<value>d0</value>
<value>e0</value>
<value>f0</value>
<value>g0</value>
<value>h0</value>
<value>i0</value>
<value>j0</value>
<value>k0</value>
<value>l0</value>
<value>m0</value>
<value>n0</value>
<value>o0</value>
<value>p0</value>
<value>q0</value>
<value>r0</value>
<value>s0</value>
<value>t0</value>
<value>a1</value>
<value>b1</value>
<value>c1</value>
<value>d1</value>
<value>e1</value>
<value>f1</value>
<value>g1</value>
<value>h1</value>
<value>i1</value>
<value>j1</value>
<value>k1</value>
<value>l1</value>
<value>m1</value>
<value>n1</value>
<value>o1</value>
<value>p1</value>
<value>q1</value>
<value>r1</value>
<value>s1</value>
<value>t1</value>
<value>a2</value>
<value>b2</value>
<value>c2</value>
<value>d2</value>
<value>e2</value>
<value>f2</value>
<value>g2</value>
<value>h2</value>
<value>i2</value>
<value>j2</value>
<value>k2</value>
<value>l2</value>
<value>m2</value>
<value>n2</value>
<value>o2</value>
<value>p2</value>
<value>q2</value>
<value>r2</value>
<value>s2</value>
<value>t2</value>
</recordset>
<recordset>
<value>A12345</value>
<value>snacks</value>
<value>1</value>
<value>cereals</value>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
</recordset>
<recordset>
<value>A245678</value>
<value>snacks</value>
<value>1</value>
<value>chips</value>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value>potato</value>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value>fried</value>
<value/>
<value></value>
<value/>
<value>baked</value>
<value></value>
<value></value>
<value></value>
<value/>
<value></value>
<value/>
<value>20g</value>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value/>
<value></value>
</recordset>
</SpecExportFF>
输出目标XML
<?xml version="1.0" encoding="UTF-8"?> <SpecExportOutputFF> <header> <item>item</item> <category>category</category> <label01>label01</label01> <spec01>spec01</spec01> <label02>label02</label02> <spec02>spec02</spec02> <label03>label03</label03> <spec03>spec03</spec03> <label04>label04</label04> <spec04>spec04</spec04> <label05>label05</label05> <spec05>spec05</spec05> <label06>label06</label06> <spec06>spec06</spec06> <label07>label07</label07> <spec07>spec07</spec07> <label08>label08</label08> <spec08>spec08</spec08> <label09>label09</label09> <spec09>spec09</spec09> <label10>label10</label10> <spec10>spec10</spec10> <label11>label11</label11> <spec11>spec11</spec11> <label12>label12</label12> <spec12>spec12</spec12> <label13>label13</label13> <spec13>spec13</spec13> <label14>label14</label14> <spec14>spec14</spec14> <label15>label15</label15> <spec15>spec15</spec15> <label16>label16</label16> <spec16>spec16</spec16> <label17>label17</label17> <spec17>spec17</spec17> <label18>label18</label18> <spec18>spec18</spec18> <label19>label19</label19> <spec19>spec19</spec19> <label20>label20</label20> <spec20>spec20</spec20> <label21>label21</label21> <spec21>spec21</spec21> <label22>label22</label22> <spec22>spec22</spec22> <label23>label23</label23> <spec23>spec23</spec23> <label24>label24</label24> <spec24>spec24</spec24> <label25>label25</label25> <spec25>spec25</spec25> <label26>label26</label26> <spec26>spec26</spec26> <label27>label27</label27> <spec27>spec27</spec27> <label28>label28</label28> <spec28>spec28</spec28> <label29>label29</label29> <spec29>spec29</spec29> <label30>label30</label30> <spec30>spec30</spec30> <label31>label31</label31> <spec31>spec31</spec31> <label32>label32</label32> <spec32>spec32</spec32> <label33>label33</label33> <spec33>spec33</spec33> <label34>label34</label34> <spec34>spec34</spec34> <label35>label35</label35> <spec35>spec35</spec35> <label36>label36</label36> <spec36>spec36</spec36> <label37>label37</label37> <spec37>spec37</spec37> <label38>label38</label38> <spec38>spec38</spec38> <label39>label39</label39> <spec39>spec39</spec39> <label40>label40</label40> <spec40>spec40</spec40> <label41>label41</label41> <spec41>spec41</spec41> <label42>label42</label42> <spec42>spec42</spec42> <label43>label43</label43> <spec43>spec43</spec43> <label44>label44</label44> <spec44>spec44</spec44> <label45>label45</label45> <spec45>spec45</spec45> <label46>label46</label46> <spec46>spec46</spec46> <label47>label47</label47> <spec47>spec47</spec47> <label48>label48</label48> <spec48>spec48</spec48> <label49>label49</label49> <spec49>spec49</spec49> <label50>label50</label50> <spec50>spec50</spec50> <label51>label51</label51> <spec51>spec51</spec51> <label52>label52</label52> <spec52>spec52</spec52> <label53>label53</label53> <spec53>spec53</spec53> <label54>label54</label54> <spec54>spec54</spec54> <label55>label55</label55> <spec55>spec55</spec55> <label56>label56</label56> <spec56>spec56</spec56> <label57>label57</label57> <spec57>spec57</spec57> <label58>label58</label58> <spec58>spec58</spec58> <label59>label59</label59> <spec59>spec59</spec59> <label60>label60</label60> <spec60>spec60</spec60> </header> <data> <item>A12345</item> <category>snacks</category> <label01>a0</label01> <spec01>1</spec01> <label02>b0</label02> <spec02>cereals</spec02> </data> <data> <item>A245678</item> <category>snacks</category> <label01>a0</label01> <spec01>1</spec01> <label02>b0</label02> <spec02>chips</spec02> <label03>q0</label03> <spec03>potato</spec03> <label04>e1</label04> <spec04>fried</spec04> <label05>i1</label05> <spec05>baked</spec05> <label06>p1</label06> <spec06>20g</spec06> </data> </SpecExportOutputFF>我的 XSLT(它可以工作,但在我看来太复杂了,想对其进行优化)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/SpecExportFF">
<SpecExportOutputFF>
<xsl:for-each select="recordset">
<xsl:variable name="IndexOfCurrentRecordset">
<xsl:value-of select="position()"/>
</xsl:variable>
<xsl:if test="$IndexOfCurrentRecordset = 1">
<header>
<xsl:for-each select="value">
<xsl:variable name="IndexOfCurrentNode" select="position()"/>
<xsl:variable name="ElementSuffix" select="format-number(($IndexOfCurrentNode - 2),'00')"/>
<!--<hello1><xsl:value-of select="$IndexOfCurrentNode"/></hello1>-->
<xsl:choose>
<xsl:when test="$IndexOfCurrentNode = 1">
<xsl:element name="item">item</xsl:element>
</xsl:when>
<xsl:when test="$IndexOfCurrentNode = 2">
<xsl:element name="category">category</xsl:element>
</xsl:when>
<xsl:when test="($IndexOfCurrentNode > 2)">
<xsl:element name="{concat('label',$ElementSuffix)}">
<xsl:value-of select="concat('label',$ElementSuffix)"/>
</xsl:element>
<xsl:element name="{concat('spec',$ElementSuffix)}">
<xsl:value-of select="concat('spec',$ElementSuffix)"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</header>
</xsl:if>
<xsl:if test="$IndexOfCurrentRecordset > 1">
<data>
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="1"/>
<xsl:with-param name="currentNode" select="./value[1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="1"/>
</xsl:call-template>
</data>
</xsl:if>
</xsl:for-each>
</SpecExportOutputFF>
</xsl:template>
<xsl:template name="iterate_values">
<xsl:param name="i"/>
<xsl:param name="currentNode"/>
<xsl:param name="IndexOfCurrentRecordset"/>
<xsl:param name="IndexOfCurrentNode"/>
<xsl:variable name="ElementSuffix" select="format-number($i,'00')"/>
<xsl:choose>
<xsl:when test="$IndexOfCurrentNode = 1">
<xsl:element name="item">
<xsl:value-of select="$currentNode/text()"/>
</xsl:element>
<xsl:if test="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]">
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="$i"/>
<xsl:with-param name="currentNode" select="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="$IndexOfCurrentNode+1"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:when test="$IndexOfCurrentNode = 2">
<xsl:element name="category">
<xsl:value-of select="$currentNode/text()"/>
</xsl:element>
<xsl:if test="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]">
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="$i"/>
<xsl:with-param name="currentNode" select="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="$IndexOfCurrentNode+1"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:when test="$IndexOfCurrentNode > 2 and $currentNode/text() != ''">
<xsl:element name="{concat('label',$ElementSuffix)}">
<xsl:value-of select="/*/*[1]/value[$IndexOfCurrentNode]"/>
</xsl:element>
<xsl:element name="{concat('spec',$ElementSuffix)}">
<xsl:value-of select="$currentNode/text()"/>
</xsl:element>
<xsl:if test="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]">
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="$i+1"/>
<xsl:with-param name="currentNode" select="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="$IndexOfCurrentNode+1"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]">
<xsl:call-template name="iterate_values">
<xsl:with-param name="i" select="$i"/>
<xsl:with-param name="currentNode" select="/SpecExportFF/recordset[position() = $IndexOfCurrentRecordset]/value[position() = $IndexOfCurrentNode+1]"/>
<xsl:with-param name="IndexOfCurrentRecordset" select="$IndexOfCurrentRecordset"/>
<xsl:with-param name="IndexOfCurrentNode" select="$IndexOfCurrentNode+1"/>
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
为了挑战,我想出了你想要做的事情。我认为主要问题是您在命令式思考,但需要转换您的思维方式,因为 XSLT 是一种函数式语言,而且情况非常不同。
确实,这就是我想出的...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:variable name="labels" select="/SpecExportFF/recordset[1]/value[position() > 2]" />
<xsl:template match="SpecExportFF">
<SpecExportOutputFF>
<xsl:apply-templates select="recordset" />
</SpecExportOutputFF>
</xsl:template>
<xsl:template match="recordset[1]">
<header>
<item>item</item>
<category>category</category>
<xsl:for-each select="value">
</xsl:for-each>
</header>
</xsl:template>
<xsl:template match="recordset[1]">
<header>
<item>item</item>
<category>category</category>
<xsl:for-each select="value[position() > 2]">
<xsl:variable name="ElementSuffix" select="format-number(position(),'00')"/>
<xsl:element name="{concat('label',$ElementSuffix)}">
<xsl:value-of select="concat('label',$ElementSuffix)"/>
</xsl:element>
<xsl:element name="{concat('spec',$ElementSuffix)}">
<xsl:value-of select="concat('spec',$ElementSuffix)"/>
</xsl:element>
</xsl:for-each>
</header>
</xsl:template>
<xsl:template match="recordset">
<data>
<item><xsl:value-of select="value[1]" /></item>
<category><xsl:value-of select="value[2]" /></category>
<xsl:for-each select="value[position() > 2][normalize-space()]">
<xsl:variable name="ElementSuffix" select="format-number(position(),'00')"/>
<xsl:variable name="LabelPos" select="count(preceding-sibling::value) - 1" />
<xsl:element name="{concat('label',$ElementSuffix)}">
<xsl:value-of select="$labels[position() = $LabelPos]" />
</xsl:element>
<xsl:element name="{concat('spec',$ElementSuffix)}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</data>
</xsl:template>
</xsl:stylesheet>