2017-02-21 16 views
0

次のトランスフォームの問題に対する洗練されたXSLT 1.0または2.0ソリューションを探しています。下のマークアップを簡略化して、「a」は開始マイルストーン要素、「b」は終了マイルストーン要素です。 "a"と "b"の間のすべては、要素 "c"で囲まなければなりません。シングルトン/マイルストーン要素のXSLT変換

入力:

<doc> 
<line>Text text <a/>text<b/></line> 
<line>Text <a/>text text</line> 
<line>Text<b/> text <a/>text</line> 
<line>Text text text</line> 
<line>Text text<b/> text</line> 
</doc> 

出力:実世界の場合

<doc> 
<line>Text text <c>text</c></line> 
<line>Text <c>text text</c></line> 
<line><c>Text</c> text <c>text</c></line> 
<line><c>Text text text</c></line> 
<line><c>Text text</c> text</line> 
</doc> 

は、A/B/C素子の各々は、に対応するために、少なくとも5のバリエーションがあります。何万行もあり、その多くにa/bまたはそのバリエーションが含まれていません。実際のケースでは、行のグループをラップする「秒」要素もあります。ここでは、a/bビヘイビアはまだ動作する必要があります。

私たちの初期のソリューションには、前述の:: *の使用が含まれていましたが、これは大きなXML文書では明らかに大きなパフォーマンス上の問題を引き起こします。

+0

パフォーマンスの問題は、先行するのではなく前の兄弟を使用するだけで解決できる場合があります。行に表示されているノード数よりもかなり多くのノードが含まれていない限り、先行する兄弟姉妹と兄弟姉妹はあまりにも高価であってはなりません。 –

+0

ありがとう@MichaelKay。私たちは現在先行兄弟を使用していますが、現在の行の状態を正しく判断するためには、ドキュメント全体を振り返る必要があるため、縮尺は変わりません。単純な状態フラグのセットを使用してこれを解決するには、SAX処理アプローチに切り替える必要があると思います。 –

+0

OK、私はマイルストーンタグの意味を理解していなかったと思います。つまり、再帰を使用して状態を維持するか、xsl:iterateを使用してXSLT 3.0で状態を維持して、線を通って前進する必要があります。 –

答えて

0

感謝のためにMichaely Kayに感謝します。

出力を与える
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" /> 

<xsl:template match="/doc" > 
    <xsl:copy> 
     <xsl:iterate select="line"> 
      <xsl:param name="state">b</xsl:param> 
      <xsl:variable name="lastState" select="local-name((a|b)[last()])"/> 
      <xsl:variable name="nextState"> 
       <xsl:choose> 
        <xsl:when test="$lastState"> 
         <xsl:value-of select="$lastState"/> 
        </xsl:when> 
        <xsl:otherwise> 
         <xsl:value-of select="$state"/> 
        </xsl:otherwise> 
       </xsl:choose> 
      </xsl:variable> 

      <xsl:copy> 
       <xsl:if test="$state = 'a'"><startC/></xsl:if> 
       <xsl:apply-templates/> 
       <xsl:if test="$nextState = 'a'"><endC/></xsl:if>      
      </xsl:copy> 

      <xsl:next-iteration> 
       <xsl:with-param name="state" select="$nextState"/> 
      </xsl:next-iteration>           
     </xsl:iterate> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="a"> 
    <startC/> 
</xsl:template> 

<xsl:template match="b"> 
    <endC/> 
</xsl:template> 

なるようにXSLT 3.0現れで実装されているC > <を包むの仕組みについての瞬間を忘れる... </C >要素、正しいアルゴリズム
<doc> 
    <line>Text text <startC/>text<endC/></line> 
    <line>Text <startC/>text text<endC/></line> 
    <line><startC/>Text<endC/> text <startC/>text<endC/></line> 
    <line><startC/>Text text text<endC/></line> 
    <line><startC/>Text text<endC/> text</line> 
</doc>