2017-01-17 8 views
0

ソースXMLを目的のXML形式(インクルード)に変換するためにXSLT(インクルード)を作成できましたが、これは組み込みのXSLT機能を活用して最適化できると確信しています。私の能力を超えています。思考を尊重する。XSLTカウンタ再帰と渡すパラメータ

入力XMLにはヘッダー値とデータが含まれています(最初のレコードにはヘッダー/ラベルが含まれ、後続のレコードにはそれぞれのラベルのデータが含まれているため、出力データは最初のレコードと位置が一致します)名前値のペアの場合、名前はデータ要素(ソースの最初のレコードのヘッダー/ラベル)を表し、要素は「labelXX」、「valueXX」であるため、カウンターがXXをインクリメントする必要があります。出力には、本質的に要素の名前だけを含むヘッダーレコードも含まれ、残りは出力から自明です。ただ、挑戦のため

ソース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> 
+1

より良い場所は、問題のこのタイプを依頼するがhttp://codereview.stackexchange.com –

+0

おかげであり、そこにも掲載します。 – jeep

+0

なぜ必要なロジックを言葉で説明しませんか? –

答えて

0

、私はあなたがやろうとしているように見えるものを作り出しました。 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> 
+0

ありがとう[Tim](http://stackoverflow.com/users/7585/tim-c)、私はまだXSLTに適合するように脳を再調整しています;)しかし、あなたのソリューションは間違いなくよりエレガントです。ただし、XSLで生成された出力XMLには、入力XMLの最初のレコードセットの値と位置的に一致させる必要があるラベル値がありません。 – jeep

+0

おかげでTim、私の最後に間違いだった、あなたのソリューションは完璧に、ありがとう。 – jeep