2017-05-04 10 views
0

私の要件は多少複雑one.Iは、以下の入力XMLを持っている値:ノードに基づいてXMLを変換すること

<results> 
    <row> 
     <CASEID>C1</CASEID> 
     <CASEBA>MEDICAID</CASEBA> 
     <ISSUEID>I1</ISSUEID> 
     <ISSUEBA>MEDICAID</ISSUEBA> 
     <OBJECTID>1</OBJECTID> 
    </row> 
    <row> 
     <CASEID>C1</CASEID> 
     <CASEBA>MEDICAID</CASEBA> 
     <ISSUEID>I2</ISSUEID> 
     <ISSUEBA>MEDICAID</ISSUEBA> 
     <OBJECTID>2</OBJECTID> 
    </row> 
    <row> 
     <CASEID>C1</CASEID> 
     <CASEBA>MEDICAID</CASEBA> 
     <ISSUEID>I1</ISSUEID> 
     <ISSUEBA>MEDICAID</ISSUEBA> 
     <OBJECTID>extra</OBJECTID> 
    </row> 
    <row> 
     <CASEID>C2</CASEID> 
     <CASEBA>MEDICAID</CASEBA> 
     <ISSUEID>I3</ISSUEID> 
     <ISSUEBA>MEDICAID</ISSUEBA> 
     <OBJECTID>3</OBJECTID> 
    </row> 
</results> 

私は、以下の条件に従うことによって、XSLTを使用したシンプルなものに上記のXMLを変換する必要があります。

1)最初のターゲットは、新しい<CASE>タグの下にある値が等しいすべての<CASEID><CASEBA>ノードに移動することです。例については

<CASE> 
    <CASEID>C1</CASEID> 
    <CASEBA>MEDICAID</CASEBA> 
</CASE> 

2)一覧うち<CASEID>年代異なる<row>が等しい年代と最近作成<CASE>タグ内に新しいタグ<ISSUE>の下に移動し、すべての<ISSUEID> & <ISSUEBA>。例えば

<CASE> 
    <CASEID>C1</CASEID> 
    <CASEBA>MEDICAID</CASEBA> 
    <ISSUE> 
     <ISSUEID>I1</ISSUEID> 
     <ISSUEBA>MEDICAID</ISSUEBA> 
    </ISSUE> 
    <ISSUE> 
     <ISSUEID>I2</ISSUEID> 
     <ISSUEBA>MEDICAID</ISSUEBA> 
    </ISSUE> 
    </CASE> 

3)一覧すべてのアウト "その<ISSUEID>の年代別の<row>年代が等しく、間違いなく下になります<ISSUE>タグ内に新しい<SOURCE>タグの下にそれらを移動<OBJECTID><CASE>。 例えば:

<CASE> 
     <CASEID>C1</CASEID> 
     <CASEBA>MEDICAID</CASEBA> 
     <ISSUE> 
      <ISSUEID>I1</ISSUEID> 
      <ISSUEBA>MEDICAID</ISSUEBA> 
      <SOURCE> 
       <OBJECTID>1</OBJECTID> 
      </SOURCE> 
      <SOURCE> 
       <OBJECTID>extra</OBJECTID> 
      </SOURCE> 
     </ISSUE> 
     <ISSUE> 
      <ISSUEID>I2</ISSUEID> 
      <ISSUEBA>MEDICAID</ISSUEBA> 
      <SOURCE> 
       <OBJECTID>2</OBJECTID> 
      </SOURCE> 
     </ISSUE> 
     </CASE> 

最終出力XMLは以下のようにする必要があります:

<results> 
    <CASE> 
     <CASEID>C1</CASEID> 
     <CASEBA>MEDICAID</CASEBA> 
     <ISSUE> 
     <ISSUEID>I1</ISSUEID> 
     <ISSUEBA>MEDICAID</ISSUEBA> 
     <SOURCE> 
      <OBJECTID>1</OBJECTID> 
     </SOURCE> 
     <SOURCE> 
      <OBJECTID>extra</OBJECTID> 
     </SOURCE> 
     </ISSUE> 
     <ISSUE> 
     <ISSUEID>I2</ISSUEID> 
     <ISSUEBA>MEDICAID</ISSUEBA> 
     <SOURCE> 
      <OBJECTID>2</OBJECTID> 
     </SOURCE> 
     </ISSUE> 
    </CASE> 
    <CASE> 
     <CASEID>C2</CASEID> 
     <CASEBA>MEDICAID</CASEBA> 
     <ISSUE> 
     <ISSUEID>I3</ISSUEID> 
     <ISSUEBA>MEDICAID</ISSUEBA> 
     <SOURCE> 
      <OBJECTID>3</OBJECTID> 
     </SOURCE> 
     </ISSUE> 
    </CASE> 
</results> 

私はきちんと私の要件を説明していない場合はご容赦ください。追加情報が必要な場合は私に尋ねてください。もし誰かが私を助けてくれたら本当に素晴らしいだろう。

+1

XSLT 1または2?これは、これがどのくらい複雑になるかに大きな違いをもたらします。 –

+0

@ G_H、お返事ありがとうございます。 XSLT 2が必要です。 '

+1

これは標準的なグループ化アプリケーションです。 XSLTの教科書やチュートリアルでコードをグループ化する例があります。 XSLT 2.0では、XSLT 1.0よりもグループ化がはるかに簡単です。 –

答えて

1

XSLT 1では "Muenchian grouping"というテクニックを使わなければならず、物事は少し複雑になります。 XSLT 2では、<xsl:for-each-group>要素とcurrent-group()関数を使用できます。以下のスタイルシートは、あなたの特定の入力に必要な正確な出力を生成します。

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:key name="caseID" match="row" use="CASEID" /> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="/results"> 
     <results> 
      <xsl:for-each-group select="row" group-by="CASEID"> 
       <xsl:call-template name="handleCase" /> 
      </xsl:for-each-group> 
     </results> 
    </xsl:template> 

    <xsl:template name="handleCase"> 
     <CASE> 
      <xsl:copy-of select="CASEID" /> 
      <xsl:copy-of select="CASEBA" /> 
      <xsl:for-each-group select="current-group()" group-by="ISSUEID"> 
       <xsl:call-template name="handleIssue" /> 
      </xsl:for-each-group> 
     </CASE> 
    </xsl:template> 

    <xsl:template name="handleIssue"> 
     <ISSUE> 
      <xsl:copy-of select="ISSUEID" /> 
      <xsl:copy-of select="ISSUEBA" /> 
      <xsl:apply-templates select="current-group()/OBJECTID" /> 
     </ISSUE> 
    </xsl:template> 

    <xsl:template match="OBJECTID"> 
     <SOURCE> 
      <xsl:copy-of select="." /> 
     </SOURCE> 
    </xsl:template> 

</xsl:transform> 

あなたは巣全体をできたが、私はいくつかの名前付きテンプレートにそれを分割しまし読めるそれを維持します。幸いにも別のテンプレートを呼び出すと、現在のグループコンテキストが保持され、そのグループ内でさらにグループ化できます。

+0

うわー!スーパー!!私の複雑な要件の解決に感謝します。あなたの迅速な対応のためにプラス1。 –

+0

私はJDKを使用してXSLTを実行しています。残念ながら、それは 'for-each-group'を特定していません。私は自分の仕事を達成するためにXSLT1.0だけを使うべきです。 XSLT 1.0を使って同じことを準備する方法を教えてください。私はここに新しいスレッドをオープンしました.http://stackoverflow.com/questions/43818999/complex-grouping-based-on-node-values-using-xslt-1-0 –

関連する問題