2009-04-27 15 views
1

SupplierIdの値が変更されたときに、何か特別なことをするためにxsl/xpath(バージョン1.0)を使う必要があります。私は3つのバリエーションを処理する必要があります。ときに最初の注文 (仕入先の最初の出現)OrderIdでO3の XPath/Xslを使用して、異なる子の同じ子要素と子要素を比較するにはどうすればよいですか?

  • がsomwthingを行い上

    1. が何かをするとき、最後の注文に(何かをする
    2. (仕入先はS1からS2に変更しました) SupplierIdの最後の出現)

    <?xml version="1.0" encoding="utf-8"?> 
    <Orders> 
        <Order> 
         <OrderId>O1</OrderId> 
         <SupplierId>S1</SupplierId> 
        </Order> 
        <Order> 
         <OrderId>O2</OrderId> 
         <SupplierId>S1</SupplierId> 
        </Order> 
        <Order> 
         <OrderId>O3</OrderId> 
         <SupplierId>S2</SupplierId> 
        </Order> 
        <Order> 
         <OrderId>O4</OrderId> 
         <SupplierId>S2</SupplierId> 
        </Order> 
        <Order> 
         <OrderId>O5</OrderId> 
         <SupplierId>S2</SupplierId> 
        </Order> 
    </Orders> 
    

    先行兄弟、兄弟姉妹などを使用しようとしましたが、まだ見つかりませんでした。私はこの初心者の質問の助けを感謝します。

    ウォーリー

  • +1

    XMLにルート要素が含まれていません。したがって、それはうまく形成されません。 – Cerebrus

    +0

    また、作業しているXPathのバージョンについては言及していません。これは、XPath 2.0が問題を単純化する多くの新機能をもたらすため、問題を複雑にします。 – Cerebrus

    答えて

    1

    <Orders> 
        <Order> 
         <OrderId>O1</OrderId> 
         <SupplierId>S1</SupplierId> 
        </Order> 
        <Order> 
         <OrderId>O2</OrderId> 
         <SupplierId>S1</SupplierId> 
        </Order> 
        <Order> 
         <OrderId>O3</OrderId> 
         <SupplierId>S2</SupplierId> 
        </Order> 
        <Order> 
         <OrderId>O4</OrderId> 
         <SupplierId>S2</SupplierId> 
        </Order> 
        <Order> 
         <OrderId>O5</OrderId> 
         <SupplierId>S2</SupplierId> 
        </Order> 
    </Orders> 
    

    所望の結果が製造される:

    First OrderId = O1 
    
        Changes in Order OrderId = O3 
        SupplierId = S2 
        Previous Order OrderId = O2 
          SupplierId = S1 
    
        Last OrderId = O5 
    
    この変換が提供されるXML文書に適用され

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    
        <xsl:template match="Order[1]"> 
         First OrderId = <xsl:text/> 
         <xsl:value-of select="OrderId"/> 
        </xsl:template> 
    
        <xsl:template match="Order[last()]"> 
    
         Last OrderId = <xsl:text/> 
         <xsl:value-of select="OrderId"/> 
        </xsl:template> 
    
        <xsl:template match= 
         "Order[not(position() = 1)] 
         [not(SupplierId 
          = 
          preceding-sibling::Order[1]/SupplierId 
          ) 
         ]"> 
    
         Changes in Order OrderId = <xsl:text/> 
         <xsl:value-of select="OrderId"/> 
         SupplierId = <xsl:text/> 
         <xsl:value-of select="SupplierId"/> 
         Previous Order OrderId = <xsl:text/> 
         <xsl:value-of select= 
         "preceding-sibling::Order[1]/OrderId"/> 
           SupplierId = <xsl:text/> 
         <xsl:value-of select= 
         "preceding-sibling::Order[1]/SupplierId"/> 
        </xsl:template> 
    
        <xsl:template match="text()"/> 
    </xsl:stylesheet> 
    

    これは、1つの天然及び簡単な解決策あります

    +0

    +1、非常に良い。 「先行する兄弟」軸にパフォーマンス上の問題が繰り返し発生する可能性がありますか? – Tomalak

    +0

    @Tomalakこの場合、「先行兄弟」軸を参照することは問題にはなりません。先行兄弟:: someThing [1]は、最適でないひどいXSLTプロセッサがない限り、一定の時間がかかります。 –

    +0

    @Dimitre:私の答えにあなたのコメントに親切に私の応答を参照してください...ああ、何でも! ;-) – Cerebrus

    0

    ルート要素Ordersを仮定するとなる各条件に合致するXPath式:

    一次(仕入先の最初の出現)

    XPath 1.0 - /Orders/Order[SupplierId][1] 
    XPath 2.0 - /Orders/Order[exists(SupplierId)][1] 
    

    B。 OrderIdでO3で

    /Orders/Order[OrderId = 'O3' and SupplierId = 'S2'] 
    

    C(仕入先がS1からS2に変更しました)。最後の注文日(仕入先の最後の出現)

    /Orders/Order[SupplierId][last()] 
    
    +0

    OPは何かを尋ねています:SupplierIdが前の注文から現在の注文に変更されたときを検出する方法。もう1つの注意点は、提供されたXPath式(およびXPath 2.0にはさらに問題がある!)は、最初のOrderのSupplierIdではなく、SupplierIdがある最初のOrderを選択することです。 –

    +0

    @Dimitre:ご意見ありがとうございます。オーダーノードの選択に関しては、質問(または少なくとも私の意味の解釈)に記載されている要件に従って完全に意図的です。私の表現を回帰的にテストするために、サンプルXMLの最初のOrderノードと最後のOrderノードからSupplierIdノードを削除しました。ノード変更の検出に関しては、コードまたはOP自身のXSLT実装を介して行われると仮定しました。 – Cerebrus

    0

    あなたが行くように、現在の値に前の値を比較し、一つずつ注文のリストをステップダウンするために再帰を使用することができますが(解決策が暗示それは、以下の、兄弟軸を使用するため、そのドキュメントの順序)は、既に正しい:

    <xsl:stylesheet 
        version="1.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    > 
    
        <xsl:template match="/Orders"> 
        <xsl:apply-templates select="Order[1]" mode="watch_SupplierId" /> 
        </xsl:template> 
    
        <xsl:template match="Order" mode="watch_SupplierId"> 
        <xsl:param name="PrevValue" select="''" /> 
    
        <xsl:if test="string(SupplierId) != $PrevValue"> 
         <xsl:call-template name="DoSomething" /> 
        </xsl:if> 
    
        <xsl:variable name="next" select="following-sibling::Order[1]" /> 
        <xsl:choose> 
         <xsl:when test="$next"> 
         <xsl:apply-templates select="$next" mode="watch_SupplierId"> 
          <xsl:with-param name="PrevValue" select="string(SupplierId)" /> 
         </xsl:apply-templates> 
         </xsl:when> 
         <xsl:otherwise> 
         <xsl:value-of select="concat('last Order found: ', OrderId, '&#10;')" /> 
         </xsl:otherwise> 
        </xsl:choose> 
        </xsl:template> 
    
        <xsl:template name="DoSomething"> 
        <xsl:value-of select="concat(
         '@SupplierId changed to &quot;' 
         , SupplierId/text() 
         , '&quot; in Order ' 
         , OrderId 
         , '&#10;' 
        )" /> 
        </xsl:template> 
    
    </xsl:stylesheet> 
    

    出力:

     
    @SupplierId changed to "S1" in Order O1 
    @SupplierId changed to "S2" in Order O3 
    last Order found: O5 
    
    +0

    実際には、この問題を解決するために再帰は必要ありません:) –

    +0

    実際、私はあなたがそれを言うと予想しました。 :) – Tomalak

    関連する問題