2

XSLTに少し問題があります..私はそれを完全に間違った方法で行っている可能性があると思います..特別な1ステータスのアイテムのSKUで顧客名を一列に表示しようとしています...次に特別な2の顧客アイテムなど、パート2(まだ開始していません)ステータスのないアイテム自体

したがって、このXMLファイルの場合、出力は次のようになります。

Joe prod1 //special1
Joe prod3 //special2
Joe prod2 //no status
Joe prod4 //no status
Joe prod5 //no status
John Smith prod6 prod8 //special1
John Smith prod7 //no status
John Smith prod9 //no status
John Smith prod10 //no status

現時点ではある程度は機能しますが、問題は、special1またはspecial2がない場合、顧客名を印刷しないようにする方法がわからないことです。

後でステータスのないものを表示する方法もわかりません-助けていただければ幸いです!

XML:

<customer>
<name>Joe</name>
<order>
    <item>
      <SKU>prod1</SKU>
      <status>special1</status>
    </item>
    <item>
      <SKU>prod2</SKU>
    </item>
    <item>
      <SKU>prod3</SKU>
      <status>special2</status>
    </item>
    <item>
      <SKU>prod4</SKU>
    </item>
    <item>
      <SKU>prod5</SKU>
    </item>
</order>
 </customer>
 <customer
<name>John Smith</name>
<order>
    <item>
      <SKU>prod6</SKU>
      <status>special1</status>
    </item>
    <item>
      <SKU>prod7</SKU>
    </item>
    <item>
      <SKU>prod8</SKU>  
      <status>special1</status>
    </item>
    <item>
     <SKU>prod9</SKU>
</item>
    <item>
      <SKU>prod10</SKU>
    </item>
</order>

XSLT:

<!DOCTYPE xsl:stylesheet[ <!ENTITY nl "&#xd;&#xa;"> ]>

<xsl:template match="customer">
    <xsl:value-of select="name" /><xsl:apply-templates select="order/item[status='special1']" /><xsl:text>&nl;</xsl:text>
    <xsl:value-of select="name" /><xsl:apply-templates select="order/item[status='special2']" /><xsl:text>&nl;</xsl:text>
</xsl:template>

<xsl:template match="item[status='special1']"><xsl:text> </xsl:text><xsl:value-of select="SKU" /></xsl:template>
<xsl:template match="item[status=special2']"><xsl:text> </xsl:text><xsl:value-of select="SKU" /></xsl:template>

<xsl:template match="text()"/>

4

3 に答える 3

0

私はあなたが異なるステータスのセットを事前に知らないと仮定しています。したがって、XMLを保守可能にしたくない場合(異なるステータスを追加するたびにXMLを変更する必要がない場合)、次のソリューションを使用できます。

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" />

    <!-- Use the following key for grouping -->
    <xsl:key name="status-key"
             match="item"
             use="status" />

    <!-- Cache the following operation to avoid doing it several times in the future.
         You can improve performance by changing // to a fixed path in your XML where
         all the items are (e.g. /customers/customer/order/item)  -->
    <xsl:variable name="item-group"
                  select="//item[generate-id(.) = generate-id(key('status-key', status)[1])]" />


    <xsl:template match="customer">

        <!-- Obtain the following values before losing the current context -->
        <xsl:variable name="current-id" select="generate-id(.)" />
        <xsl:variable name="current-name" select="name" />

        <!-- Display the products with a status defined -->
        <xsl:for-each select="$item-group">
            <!-- Obtain list of status for this costumer -->
            <xsl:variable name="customer-status"
                          select="key('status-key', status)[generate-id(../..) = $current-id]" />
            <!-- Print the status information if the costumer has at least one status -->
            <xsl:if test="$customer-status">
                <!-- Display the name of the costumer -->
                <xsl:value-of select="$current-name" />
                <!-- Group the product by status -->
                <xsl:for-each select="$customer-status">
                    <xsl:value-of select="concat(' ', SKU)" />
                </xsl:for-each>
                <!-- Output the status -->
                <xsl:value-of select="concat(' //', status, '&#xa;')" />
            </xsl:if>
        </xsl:for-each>

        <!-- Display the prodcuts without status -->
        <xsl:for-each select="order/item[not(status)]">
            <xsl:value-of select="concat($current-name, ' ', SKU, ' //no-status&#xa;')" />
        </xsl:for-each>

    </xsl:template>

    <xsl:template match="text()" />

</xsl:stylesheet>
于 2013-02-17T12:13:46.860 に答える
0

これは「グループ化」の問題の例です。顧客とステータスの組み合わせでアイテムをグループ化しようとしています。これを解決するためのアプローチは、XSLT 1.0 と XSLT 2.0 のどちらを使用しているかによって異なります。XSLT 1.0 では、Muenchian Grouping と呼ばれる手法を使用します。グループ化するノードを保持するキーを定義することから始めます。この場合、顧客アイテムでグループ化しています

<xsl:key name="items" match="item" use="concat(generate-id(../..), '|', status)" />

次に、一致する顧客要素ごとに、次のように各アイテムの個別のステータス要素を取得します。

<xsl:apply-templates select="order/item
    [status != '']
    [generate-id() = generate-id(key('items', concat(generate-id(../..), '|', status))[1])]" />

基本的にこれが行っていることは、顧客の各項目を見て、ステータス要素に定義したキーで最初に発生する項目を選択することです。

次に、ステータスを持つアイテムに一致するテンプレートで、次のように同じステータスを持つ個々のアイテムを取得できます。

<xsl:apply-templates select="key('items', concat(generate-id(../..), '|', status))/SKU" />

ステータスのないアイテムを選択する方がはるかに簡単ですが

<xsl:apply-templates select="order/item[not(status != '')]" />

ここに完全な XSLT があります

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text"/>
   <xsl:key name="items" match="item" use="concat(generate-id(../..), '|', status)" />

   <xsl:template match="customer">
      <xsl:apply-templates select="order/item[status != ''][generate-id() = generate-id(key('items', concat(generate-id(../..), '|', status))[1])]" />
      <xsl:apply-templates select="order/item[not(status != '')]" />
   </xsl:template>

   <xsl:template match="item[status !='']">
      <xsl:value-of select="../../name" />
      <xsl:apply-templates select="key('items', concat(generate-id(../..), '|', status))/SKU" />
      <xsl:value-of select="concat(' //', status, '&#13;')" />
   </xsl:template>

   <xsl:template match="item">
      <xsl:value-of select="concat(../../name, ' ', SKU, ' // no status&#13;')" />
   </xsl:template>

   <xsl:template match="SKU">
      <xsl:value-of select="concat(' ', .)" />
   </xsl:template>
</xsl:stylesheet>

XML に適用すると、次のように出力されます。

Joe prod1 //special1
Joe prod3 //special2
Joe prod2 // no status
Joe prod4 // no status
Joe prod5 // no status
John Smith prod6 prod8 //special1
John Smith prod7 // no status
John Smith prod9 // no status
John Smith prod10 // no status

XSLT2.0 を使用していた場合は、グループ化を処理するためにxsl:for-each-groupを作成できるため、従うのが少し簡単になります。

<xsl:for-each-group select="order/item[status != '']" group-by="status">

そして、グループでアイテムを取得するには、current-group()関数を使用します

<xsl:apply-templates select="current-group()/SKU" />

これも同じ結果を出力する完全な XSLT2.0 スタイルシートです。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text"/>

   <xsl:template match="customer">
      <xsl:for-each-group select="order/item[status != '']" group-by="status">
          <xsl:value-of select="../../name" />
          <xsl:apply-templates select="current-group()/SKU" />
          <xsl:value-of select="concat(' //', status, '&#13;')" />          
      </xsl:for-each-group>

      <xsl:apply-templates select="order/item[not(status != '')]" />
   </xsl:template>

   <xsl:template match="item">
      <xsl:value-of select="concat(../../name, ' ', SKU, ' // no status&#13;')" />
   </xsl:template>

   <xsl:template match="SKU">
      <xsl:value-of select="concat(' ', .)" />
   </xsl:template>
</xsl:stylesheet>
于 2013-02-17T12:31:26.417 に答える
0

最も簡単なオプションは xsl:if です

<xsl:template match="customer">
    <xsl:if test="order/item[status='special1']">
        <xsl:value-of select="name" /><xsl:apply-templates select="order/item[status='special1']" /><xsl:text>&nl;</xsl:text>
    </xsl:if>
    <xsl:if test="order/item[status='special2']">
        <xsl:value-of select="name" /><xsl:apply-templates select="order/item[status='special2']" /><xsl:text>&nl;</xsl:text>
    </xsl:if>
</xsl:template>
于 2013-02-17T07:52:22.933 に答える