2017-03-29 7 views
0

巨大なxml(約300MB)を繰り返し子要素に基づいて小さなファイルに分割しようとしています。この上述したようにXSLTで複数のxmlに分割して親要素を保持

<?xml version="1.0" encoding="UTF-8"?> 
<a> 
    <b></b> 
    <bb></bb> 
    <bbb> 
     <c> 
      <d id="1"> 
       <x></x> 
       <y></y> 
      </d> 
      <d id="2"> 
       <x></x> 
       <y></y> 
      </d> 
      <d id="3"> 
       <x></x> 
       <y></y> 
      </d> 
     </c> 
    </bbb> 
    <e></e> 
    <f></f> 
</a> 

input.xmlにシナリオ

を例示する以下

例繰り返し子要素を有しています。この要素に基づいて、親要素と属性をそのまま維持することによって、別々の出力ファイルが必要になります。

の予想される出力out_1_a.xml

<?xml version="1.0" encoding="UTF-8"?> 
<a> 
    <b></b> 
    <bb></bb> 
    <bbb> 
     <c> 
      <d id="1"> 
       <x></x> 
       <y></y> 
      </d> 
     </c> 
    </bbb> 
    <e></e> 
    <f></f> 
</a> 

の予想される出力out_2_a.xml

<?xml version="1.0" encoding="UTF-8"?> 
<a> 
    <b></b> 
    <bb></bb> 
    <bbb> 
     <c> 
      <d id="2"> 
       <x></x> 
       <y></y> 
      </d> 
     </c> 
    </bbb> 
    <e></e> 
    <f></f> 
</a> 

の予想される出力out_3_a.xml

<?xml version="1.0" encoding="UTF-8"?> 
<a> 
    <b></b> 
    <bb></bb> 
    <bbb> 
     <c> 
      <d id="3"> 
       <x></x> 
       <y></y> 
      </d> 
     </c> 
    </bbb> 
    <e></e> 
    <f></f> 
</a> 

私のXSL - sample.xsl

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

<xsl:output indent="yes"/> 

<xsl:template match="/"> 
    <xsl:for-each select="a/bbb/c/d"> 
    <xsl:variable name="i" select="position()" /> 
    <xsl:result-document method="xml" href="out_{$i}_a.xml"> 
    <a> 
     <b></b> 
     <bb></bb> 
     <bbb> 
      <c> 
       <xsl:copy-of select="../@* | ." /> 
      </c> 
     </bbb> 
     <e></e> 
     <f></f> 
    </a> 
    </xsl:result-document> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

これは、[OK]を動作し、私は私が望む出力を得ます。 しかし、これを達成するためのより良い方法は、a、b、bbなどの親要素をハードコーディングするよりも確実です。また、場合によってはこれらの親要素に属性が含まれており、動的です。だから、ハードコーディングは私が避けたいものです。これを解決するより良い方法はありますか?

答えて

2

あなたはこれを使用することができます:

<xsl:template match="d"> 
    <xsl:variable name="name" select="generate-id()"/> 
    <xsl:variable name="outputposition"><xsl:value-of select="count(preceding::d)+1"></xsl:value-of></xsl:variable> 
    <xsl:result-document method="xml" href="out_{$outputposition}_a.xml" indent="yes"> 
     <xsl:call-template name="spilit"> 
      <xsl:with-param name="name" select="$name"/> 
      <xsl:with-param name="element" select="root()"/> 
     </xsl:call-template> 
    </xsl:result-document> 
</xsl:template> 

<xsl:template name="spilit"> 
    <xsl:param name="name"/> 
    <xsl:param name="element"/> 
    <xsl:for-each select="$element[descendant-or-self::d[generate-id() eq $name]]"> 
     <xsl:choose> 
      <xsl:when test="self::d[generate-id() = $name]"> 
       <xsl:copy> 
        <xsl:copy-of select="@*"></xsl:copy-of> 
        <xsl:copy-of select="node()"></xsl:copy-of> 
       </xsl:copy> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:copy-of select="preceding-sibling::*"/> 
       <xsl:copy> 
        <xsl:call-template name="spilit"> 
         <xsl:with-param name="name" select="$name"/> 
         <xsl:with-param name="element" select="child::*[descendant-or-self::d[generate-id() eq $name]]"/> 
        </xsl:call-template> 
       </xsl:copy> 
       <xsl:copy-of select="following-sibling::*"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
</xsl:template> 
+1

生成される出力ファイルは、OPによって必要とされるものとは異なる構造を持っています。 「先行兄弟」と「兄弟姉妹」のコピーは適切な場所にありません。 –

+0

ありがとう@LingamurthyCS、今私はスクリプトを更新しました – Rupesh

+0

こんにちはルペシュ、これは私のシナリオに完全に動作します。ありがとう。 しかし、要素dのid属性の一致に関する1つの質問。要素dにatttributesがない場合は、それを分割する方法がありますか? –

1

ザ・をXSLT-2.0ソリューションの下に簡単にこの仕事をする必要があります。

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    version="2.0"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 

    <xsl:template match="@* | node()" mode="createDoc"> 
     <xsl:param name="id"/> 
     <xsl:copy> 
      <!-- apply-templates to the attributes and, the desired 'd' child element or all children elements --> 
      <xsl:apply-templates select="@*, if(node()[generate-id() = $id]) then node()[generate-id() = $id] else node()" mode="createDoc"> 
       <xsl:with-param name="id" select="$id"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 

    <!-- template to create documents per `d` element --> 
    <xsl:template match="/"> 
     <xsl:for-each select="a/bbb/c/d"> 
      <xsl:result-document href="out_{@id}_a.xml"> 
       <xsl:apply-templates select="root(.)" mode="createDoc"> 
        <!-- pass the id of the desired element to be copied omitting its siblings--> 
        <xsl:with-param name="id" select="generate-id()"/> 
       </xsl:apply-templates> 
      </xsl:result-document> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

2番目のテンプレートはgenerate-id()を渡すことによってd要素ごとに文書を作成し、再帰的なテンプレート(最初のテンプレート)にマッチした要素の。

最初のテンプレートは、すべての要素を再帰的にコピーします。また、を使用して、generate-id()で目的のd要素のみをコピーし、他の兄弟は省略します。

関連する問題