3

次の XML があります。

<?xml version="1.0" encoding="UTF-8"?>
<Order>
<Item>
    <RECORD_ID>RECORD_ID</RECORD_ID>
    <ENTITY_CODE>ENTITY_CODE</ENTITY_CODE>
    <USER_CODE>USER_CODE</USER_CODE>
    <RECORD_DATE>RECORD_DATE</RECORD_DATE>
    <ITEM_CODE>ITEM_CODE</ITEM_CODE>
    <LINE_QUANTITY>LINE_QUANTITY</LINE_QUANTITY>
    <LINE_FREE_STOCK>LINE_FREE STOCK</LINE_FREE_STOCK>
    <LINE_PRICE>LINE_PRICE</LINE_PRICE>
    <LINE_DISCOUNT_PERCENT>LINE_DISCOUNT PERCENT</LINE_DISCOUNT_PERCENT>
</Item>
<Item>
    <RECORD_ID>9046</RECORD_ID>
    <ENTITY_CODE>12010601</ENTITY_CODE>
    <USER_CODE>122</USER_CODE>
    <RECORD_DATE>2011-08-24</RECORD_DATE>
    <ITEM_CODE>804-008165</ITEM_CODE>
    <LINE_QUANTITY>2</LINE_QUANTITY>
    <LINE_FREE_STOCK>1</LINE_FREE_STOCK>
</Item>
<Item>
    <RECORD_ID>9046</RECORD_ID>
    <ENTITY_CODE>12010601</ENTITY_CODE>
    <USER_CODE>122</USER_CODE>
    <RECORD_DATE>2011-08-24</RECORD_DATE>
    <ITEM_CODE>804-008161</ITEM_CODE>
    <LINE_QUANTITY>1</LINE_QUANTITY>
    <LINE_FREE_STOCK>1</LINE_FREE_STOCK>
</Item>
<Item>
    <RECORD_ID>9046</RECORD_ID>
    <ENTITY_CODE>12010601</ENTITY_CODE>
    <USER_CODE>122</USER_CODE>
    <RECORD_DATE>2011-08-24</RECORD_DATE>
    <ITEM_CODE>804-008225</ITEM_CODE>
    <LINE_QUANTITY>5</LINE_QUANTITY>
</Item>
</Order>

itemタグ内に要素がある場合があります<LINE_FREE_STOCK>。その場合は、出力 XML に追加の位置を作成する必要があります。

今、私はこのスタイルシートを思いつきました:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output encoding="UTF-8" method="xml" indent="yes"/>

<xsl:template match="/">
    <ORDERS05>
        <IDOC BEGIN="1">
            <xsl:apply-templates select="Order"/>
        </IDOC>
    </ORDERS05>
</xsl:template>

<xsl:template match="Order">
    <Header>
        <xsl:value-of select="'some header data'"/>
    </Header>
    <xsl:apply-templates select="Item[position() >1]"/>
    <xsl:apply-templates select="Item[position() >1 and child::LINE_FREE_STOCK]" mode="freestock"/>
</xsl:template>

<xsl:template match="Item">
        <position>
            <item>
                <number><xsl:value-of select="ITEM_CODE"/></number>
                <quantity><xsl:value-of select="LINE_QUANTITY"/></quantity>
            </item>
        </position>
</xsl:template>

<xsl:template match="Item[position() >1 and child::LINE_FREE_STOCK]" mode="freestock">
        <position>
            <item>
                <number><xsl:value-of select="ITEM_CODE"/></number>
                <freestock_quant><xsl:value-of select="LINE_FREE_STOCK"/></freestock_quant>
            </item>
        </position>
</xsl:template>

</xsl:stylesheet>

この(単純化された)必要な出力が作成されます。

<?xml version="1.0" encoding="UTF-8"?>
<ORDERS05>
<IDOC BEGIN="1">
    <Header>some header data</Header>
    <position>
        <item>
            <number>804-008165</number>
            <quantity>2</quantity>
        </item>
    </position>
    <position>
        <item>
            <number>804-008161</number>
            <quantity>1</quantity>
        </item>
    </position>
    <position>
        <item>
            <number>804-008225</number>
            <quantity>5</quantity>
        </item>
    </position>
    <position>
        <item>
            <number>804-008165</number>
            <freestock_quant>1</freestock_quant>
        </item>
    </position>
    <position>
        <item>
            <number>804-008161</number>
            <freestock_quant>1</freestock_quant>
        </item>
    </position>
</IDOC>
</ORDERS05>

804-008165 と 804-008161 は 2 回表示されます。1 回は標準アイテムとして、もう 1 回はそれぞれの数量の無料在庫アイテムとして表示されます。

しかし、私はここで何かを忘れましたか?私が見ていない落とし穴のようなものはありますか?その XSLT は十分に堅牢ですか?

4

4 に答える 4

4

他の人が指摘したように、問題は次のコードにあります

<xsl:apply-templates select="Item"/> 
<xsl:apply-templates select="Item[child::LINE_FREE_STOCK]" mode="freestock"/> 

childItemを持つ子がある場合LINE_FREE_STOCK、テンプレートはこのItem要素に 2 回適用されます。出力で繰り返しを取得する方法は次のとおりです。

変換は大幅に短縮でき、モードや明示的な条件命令はまったく必要ありません

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output encoding="UTF-8" indent="yes"/>

 <xsl:template match="/">
    <ORDERS05>
        <IDOC BEGIN="1">
            <xsl:apply-templates select="Order"/>
        </IDOC>
    </ORDERS05>
 </xsl:template>

 <xsl:template match="Order">
    <Header>
        <xsl:value-of select="'some header data'"/>
    </Header>
        <xsl:apply-templates select="Item[position() >1]"/>
 </xsl:template>

 <xsl:template match="Item">
  <position>
    <item>
      <number>
        <xsl:value-of select="ITEM_CODE"/>
      </number>

      <xsl:apply-templates select=
        "self::node()[not(LINE_FREE_STOCK)]/LINE_QUANTITY
       |
         LINE_FREE_STOCK"/>
     </item>
  </position>
 </xsl:template>

 <xsl:template match="LINE_QUANTITY">
   <quantity>
     <xsl:value-of select="."/>
   </quantity>
 </xsl:template>

 <xsl:template match="LINE_FREE_STOCK">
   <freestock_quant>
     <xsl:value-of select="."/>
   </freestock_quant>
 </xsl:template>
</xsl:stylesheet>

この変換が提供された XML ドキュメントに適用されると、次のようになります。

<Order>
    <Item>
        <RECORD_ID>RECORD_ID</RECORD_ID>
        <ENTITY_CODE>ENTITY_CODE</ENTITY_CODE>
        <USER_CODE>USER_CODE</USER_CODE>
        <RECORD_DATE>RECORD_DATE</RECORD_DATE>
        <ITEM_CODE>ITEM_CODE</ITEM_CODE>
        <LINE_QUANTITY>LINE_QUANTITY</LINE_QUANTITY>
        <LINE_FREE_STOCK>LINE_FREE STOCK</LINE_FREE_STOCK>
        <LINE_PRICE>LINE_PRICE</LINE_PRICE>
        <LINE_DISCOUNT_PERCENT>LINE_DISCOUNT PERCENT</LINE_DISCOUNT_PERCENT>
    </Item>
    <Item>
        <RECORD_ID>9046</RECORD_ID>
        <ENTITY_CODE>12010601</ENTITY_CODE>
        <USER_CODE>122</USER_CODE>
        <RECORD_DATE>2011-08-24</RECORD_DATE>
        <ITEM_CODE>804-008165</ITEM_CODE>
        <LINE_QUANTITY>2</LINE_QUANTITY>
        <LINE_FREE_STOCK>1</LINE_FREE_STOCK>
    </Item>
    <Item>
        <RECORD_ID>9046</RECORD_ID>
        <ENTITY_CODE>12010601</ENTITY_CODE>
        <USER_CODE>122</USER_CODE>
        <RECORD_DATE>2011-08-24</RECORD_DATE>
        <ITEM_CODE>804-008161</ITEM_CODE>
        <LINE_QUANTITY>1</LINE_QUANTITY>
        <LINE_FREE_STOCK>1</LINE_FREE_STOCK>
    </Item>
    <Item>
        <RECORD_ID>9046</RECORD_ID>
        <ENTITY_CODE>12010601</ENTITY_CODE>
        <USER_CODE>122</USER_CODE>
        <RECORD_DATE>2011-08-24</RECORD_DATE>
        <ITEM_CODE>804-008225</ITEM_CODE>
        <LINE_QUANTITY>5</LINE_QUANTITY>
    </Item>
</Order>

必要な正しい結果が生成されます。

<ORDERS05>
   <IDOC BEGIN="1">
      <Header>some header data</Header>
      <position>
         <item>
            <number>804-008165</number>
            <freestock_quant>1</freestock_quant>
         </item>
      </position>
      <position>
         <item>
            <number>804-008161</number>
            <freestock_quant>1</freestock_quant>
         </item>
      </position>
      <position>
         <item>
            <number>804-008225</number>
            <quantity>5</quantity>
         </item>
      </position>
   </IDOC>
</ORDERS05>
于 2011-08-26T03:05:37.887 に答える
1

必要な出力が何であるかは明確ではありません。おそらくあなたが望む:

<xsl:apply-templates select="Item[not(LINE_FREE_STOCK)"/>
<xsl:apply-templates select="Item[LINE_FREE_STOCK]" mode="freestock"/>

あなたの代わりに

  <xsl:apply-templates select="Item"/>
  <xsl:apply-templates select="Item[child::LINE_FREE_STOCK]" mode="freestock"/>
于 2011-08-25T14:57:32.320 に答える
1

これは、アイテムに対して 2 つの一致テンプレートがあるためです。

<xsl:template match="Item">
  <xsl:if test="position() &gt; 1">
    <position>
      <item>
        <number><xsl:value-of select="ITEM_CODE"/></number>
        <quantity><xsl:value-of select="LINE_QUANTITY"/></quantity>
      </item>
    </position>
  </xsl:if>
</xsl:template>

<xsl:template match="Item[child::LINE_FREE_STOCK]" mode="freestock">
  <xsl:if test="position() &gt; 1">            
    <position>
      <item>
        <number><xsl:value-of select="ITEM_CODE"/></number>
        <freestock_quant><xsl:value-of select="LINE_FREE_STOCK"/></freestock_quant>
      </item>
    </position>
  </xsl:if>
</xsl:template>

最初にデフォルトの Item テンプレートが一致し、次に LINE_FREE_STOCK を持つ Item が子 LINE_FREE_STOCK テンプレートを持つ Item にも一致するため、LINE_FREE_STOCK を持つ Item の複製になります。

代わりに、次のように 1 つのテンプレートだけを使用してください。

<xsl:template match="Item">
  <xsl:if test="position() &gt; 1">
    <position>
      <item>
        <number><xsl:value-of select="ITEM_CODE"/></number>
        <xsl:choose>
          <xsl:when test="child::LINE_FREE_STOCK">
            <freestock_quant><xsl:value-of select="LINE_FREE_STOCK"/></freestock_quant>
          </xsl:when>
          <xsl:otherwise>
            <quantity><xsl:value-of select="LINE_QUANTITY"/></quantity>
          </xsl:otherwise>
        </xsl:choose>
      </item>
    </position>
  </xsl:if>
</xsl:template>

単一のテンプレートを使用すると、注文テンプレートも簡素化されます。

<xsl:template match="Order">
  <Header>
    <xsl:value-of select="'some header data'"/>
  </Header>
  <xsl:apply-templates select="Item"/>
</xsl:template>

この方法では、モードも使用する必要はありません。

于 2011-08-25T14:56:23.727 に答える
1

追加のフィルタリングが必要になります

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output encoding="UTF-8" method="xml" indent="yes"/>

<xsl:template match="/">
    <ORDERS05>
        <IDOC BEGIN="1">
            <xsl:apply-templates select="Order"/>
        </IDOC>
    </ORDERS05>
</xsl:template>

<xsl:template match="Order">
    <Header>
        <xsl:value-of select="'some header data'"/>
    </Header>
    <xsl:apply-templates select="Item[not(child::LINE_FREE_STOCK)]"/>
    <xsl:apply-templates select="Item[child::LINE_FREE_STOCK]" mode="freestock"/>
</xsl:template>

<xsl:template match="Item">
    <xsl:if test="position() &gt; 1">
        <position>
            <item>
                <number><xsl:value-of select="ITEM_CODE"/></number>
                <quantity><xsl:value-of select="LINE_QUANTITY"/></quantity>
            </item>
        </position>
    </xsl:if>
</xsl:template>

<xsl:template match="Item[child::LINE_FREE_STOCK]" mode="freestock">
    <xsl:if test="position() &gt; 1">            
        <position>
            <item>
                <number><xsl:value-of select="ITEM_CODE"/></number>
                <freestock_quant><xsl:value-of select="LINE_FREE_STOCK"/></freestock_quant>
            </item>
        </position>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>
于 2011-08-25T14:58:11.863 に答える