2012-03-21 12 views
2

私はXSLTを使用してXML要素のテキストコンテンツを解析しています。このテキストに改行が含まれていますが、正しく解析できないようです。私はテキストを切り詰めるためにオンラインで見つけたコードを使用しています。ここにコードの関連部分があります。XSLTでは、要素のテキストコンテンツを行に分割するにはどうすればよいですか?

<xsl:variable name="first"> 
    <xsl:value-of select="substring-before($source, $newline)"/> 
</xsl:variable> 
<xsl:variable name="rest"> 
    <xsl:value-of select="substring-after($source, $newline)"/> 
</xsl:variable> 

これは、$ restを自分自身にプッシュするrecusriveテンプレートの一部です。

問題は、コードサンプルが$ newlineを定義していないことです。 $ newlineを 's'のような文字に設定した場合、テキストはちょうど上に分割されます(例えば、入力が「再」と「再」に変わります)。しかし、$ newlineを改行文字に設定しようとすると、それは&#xa;または&#xa0;です。それは永遠に再帰し、私にスタックオーバーフローを与えます。また改行のENTITYを定義しようとしましたが、違いはありません。

入力には、各行の最後に普通のCR/LFがあります(Windowsのボックスにあります)。

誰かが私が間違っていることを知っているか、アプローチを提案していますか?

おかげで、 Mathijs

答えて

2

は、私は一度、このテンプレートを使用しています。名前付きテンプレートなので、必要な場所で呼び出すことができます。ここのテキストは70文字で分割されています:

<xsl:template name="Texts"> 
    <xsl:param name="string" select="TEXTITEM" /> 
    <xsl:param name="line-length" select="70"/> 
    <xsl:variable name="line" select="substring($string,1,$line-length)"/> 
    <xsl:variable name="rest" select="substring($string, $line-length+1)"/> 
    <xsl:if test="$line"> 
     <MYTEXT> 
      <xsl:value-of select="$line"/> 
     </MYTEXT> 
    </xsl:if> 
    <xsl:if test="$rest"> 
     <xsl:call-template name="Texts"> 
      <xsl:with-param name="string" select="$rest"/> 
      <xsl:with-param name="line-length" select="$line-length"/> 
     </xsl:call-template> 
    </xsl:if> 
</xsl:template> 

あなたのために働くかどうか教えてください。

よろしく、 ピーター

+0

申し訳ありませんが、私は新しい行の文字について言及していませんでした。「0x0d 0x0a」はASCII CR + LFです。だから$ newline = "0x0d 0x0a"ベスト、ピーター – Peter

+0

これは、私が必要なものではない等しい長さのチャンクにそれを切り刻む。私が実際に達成したいのは、どれが最長であるかを見つけることです。 –

+0

$ newlineを0x0d0x0という値に設定すると、$ firstと$ restの両方が空になります。 \ nまたは\ n \ rに設定した場合と同じです。または、私が –

2

あなたは、XSLT 2.0とstr:tokenize

<xsl:for-each select="str:tokenize($source, $newline)"> 
    <xsl:value-of select="."/> 
    <xsl:text>&#x0a;</xsl:text> 
</xsl:for-each> 

または同様にしてみてくださいEXSLTを使用することができた場合:

<xsl:for-each select="tokenize($source, $newline)"> 
    <xsl:sequence select="."/> 
    <xsl:text>&#x0a;</xsl:text> 
</xsl:for-each> 
+0

悲しいことに、私はどちらも持っていません。私はAntスクリプトからXSLTを呼び出しています。 –

2

あなたは以下を使用することができます。

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <root> 
      <xsl:for-each select="root/str"> 
       <str> 
        <xsl:call-template name="strSplit"> 
         <xsl:with-param name="str" select="."/> 
         <xsl:with-param name="seqno" select="1"/> 
        </xsl:call-template> 
       </str> 
      </xsl:for-each> 
     </root> 
    </xsl:template> 

    <xsl:template name="strSplit"> 
     <xsl:param name="str"/> 
     <xsl:param name="seqno"/> 

     <xsl:variable name="afterLeadingWS" 
      select="substring-after($str, substring-before($str,substring-before(normalize-space($str), ' ')))"/> 

     <xsl:choose> 
      <xsl:when test="contains($afterLeadingWS, '&#xA;')"> 
       <line> 
        <xsl:attribute name="seqno"><xsl:value-of select="$seqno"/></xsl:attribute> 
        <xsl:attribute name="length"><xsl:value-of select="string-length(substring-before($afterLeadingWS, '&#xA;'))"/></xsl:attribute> 
        <xsl:value-of select="substring-before($afterLeadingWS, '&#xA;')"/> 
       </line> 
       <xsl:call-template name="strSplit"> 
        <xsl:with-param name="str" select="substring-after($afterLeadingWS, '&#xA;')"/> 
        <xsl:with-param name="seqno" select="$seqno + 1"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <line> 
        <xsl:attribute name="seqno"><xsl:value-of select="$seqno"/></xsl:attribute> 
        <xsl:value-of select="$afterLeadingWS"/> 
       </line> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <str> 
     yigifgniuq h 
     eukwgf kuew hgk.uhgku 
     ,/v.,silghouihhg 
    </str> 
    <str> 
     09734ymmnyr n.0808 
     o149013483ymr7rg 
     738924m c0 

    </str> 
</root> 

に印加される出力結果は、先頭のタブ(またはブランク)はラインの一部として見られること

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <str> 
     <line seqno="1" length="13">yigifgniuq h </line> 
     <line seqno="2" length="21">eukwgf kuew hgk.uhgku</line> 
     <line seqno="3" length="18">  ,/v.,silghouihhg</line> 
     <line seqno="4"> </line> 
    </str> 
    <str> 
     <line seqno="1" length="18">09734ymmnyr n.0808</line> 
     <line seqno="2" length="16">o149013483ymr7rg</line> 
     <line seqno="3" length="11">738924m c0 </line> 
     <line seqno="4" length="2">  </line> 
     <line seqno="5"> </line> 
    </str> 
</root> 

注です。

+0

これは非常に役立つように見えますが、トークン化された行を出力する代わりに、最も長い行の長さを知りたいと思います。 –

+0

別の属性を追加する: - 上記の編集を参照してください。 – Maestro13

+0

驚くべきことに、生のアドレス(改行で区切られたもの)を ' blah ...' –

2

マエストロ13の答えは私に最も近いものをもたらし、私は彼と一緒に持っていたテンプレートをマージしてこれを作り出しました。私はこれを次世代のために共有します。これは、渡す文字列の最長行の長さを返すテンプレートです。

<xsl:template name="longestCodeLine"> 
    <xsl:param name="str"/> 

    <xsl:choose> 
    <!-- Is this the last line? --> 
    <xsl:when test="contains($str, '&#xA;')"> 
     <!-- No. First isolate all remaining lines, and recurse to find its longest line. --> 
     <xsl:variable name="bestOfTheRest"> 
      <xsl:call-template name="longestCodeLine"> 
       <xsl:with-param name="str" select="substring-after($str, '&#xA;')"/>       
      </xsl:call-template> 
     </xsl:variable> 
     <xsl:choose> 
      <!-- Compare the longest of the remaining lines to this one. Which one's longer? --> 
      <!-- If the longest of the remaining lines is longer, return that line. --> 
      <xsl:when test="string-length($bestOfTheRest) &gt; string-length(substring-before($str, '&#xA;'))"> 
       <xsl:value-of select="$bestOfTheRest"/> 
      </xsl:when> 
      <!-- If this line longer, return this line. --> 
      <xsl:otherwise> 
       <xsl:value-of select="substring-before($str, '&#xA;')"/> 
      </xsl:otherwise> 
     </xsl:choose> 
      </xsl:when> 
    <!-- If there are no \n's left, this is your last string. So it is by definition the longest one left. --> 
    <xsl:otherwise> 
     <xsl:value-of select="$str"/> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
+0

に分割するように修正できました。最後のコードをお寄せいただきありがとうございます。私はそれと "#xA;"の違いについても調べます。 「0x0a」はわかりません。私はそれについてもフォローアップしなければならない。敬具、Peter +1 – Peter

1

私は空白の後に改行を追加する行分割コードを追加したいと思います。

<xsl:function name="kode:splitLongLine"> 
    <xsl:param name="string"/> 
    <xsl:variable name="regex"> 
    <xsl:text>(((.){1,55})(|$))</xsl:text> 
    </xsl:variable> 

    <xsl:variable name="result"> 
    <xsl:analyze-string select="$string" regex="{$regex}"> 
    <xsl:matching-substring> 
    <xsl:value-of select="concat(regex-group(1),'&#10;')"/> 
    </xsl:matching-substring> 
    <xsl:non-matching-substring> 
    <xsl:value-of select="concat('REPORT ERROR: ', .)"/> 
    </xsl:non-matching-substring> 
    </xsl:analyze-string> 
    </xsl:variable> 

    <xsl:sequence select="$result"/> 
</xsl:function> 
関連する問題