2012-12-30 77 views
1

我需要能夠輸出由換行符分隔的XML文檔的文本。換句話說,在XML:如何檢測XSLT中的換行符

<programlisting> 
public static void main(String[] args){ 
    System.out.println("Be happy!"); 
    System.out.println("And now we add annotations."); 
} 
</programlisting> 

需求被表示爲:(「\ n」)

<para>public static void main(String[] args){</para> 
<para> System.out.println("Be happy!"); </para> 
<para> System.out.println("And now we add annotations."); </para> 
<para>}</para> 

我想我應該能夠使用子-之前,但對於一些因爲它沒有識別換行符。

我也嘗試將每行輸出爲一個CDATA部分,以便我可以分別拉出這些部分,但遇到了將它們全部集中到一個文本節點的事實。

我只是在這裏使用常規的Java進行轉換。任何想法如何實現這一目標?

謝謝...

回答

0

一XSLT 2.0解決方案

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

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

<xsl:template match="text()"> 
    <xsl:for-each select="tokenize(., '\n\r?')[.]"> 
    <para><xsl:sequence select="."></xsl:sequence></para> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

當這種變換所提供的XML文檔應用:

<programlisting> 
public static void main(String[] args){ 
    System.out.println("Be happy!"); 
    System.out.println("And now we add annotations."); 
} 
</programlisting> 

通緝,會產生正確的結果:

<programlisting> 
    <para>public static void main(String[] args){</para> 
    <para> System.out.println("Be happy!");</para> 
    <para> System.out.println("And now we add annotations.");</para> 
    <para>}</para> 
</programlisting> 

II。 XSLT 1.0溶液,使用str-split-to-words模板的FXSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext"> 
    <xsl:import href="strSplit-to-Words.xsl"/> 
    <xsl:output indent="yes" omit-xml-declaration="yes"/> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes" omit-xml-declaration="yes"/> 

    <xsl:param name="pDelims" select="'&#xA;&#xD;'"/> 

    <xsl:template match="/"> 
     <xsl:variable name="vwordNodes"> 
     <xsl:call-template name="str-split-to-words"> 
      <xsl:with-param name="pStr" select="/"/> 
      <xsl:with-param name="pDelimiters" 
          select="$pDelims"/> 
     </xsl:call-template> 
     </xsl:variable> 

     <xsl:apply-templates select= 
     "ext:node-set($vwordNodes)/*[normalize-space()]"/> 
    </xsl:template> 

    <xsl:template match="word"> 
     <para><xsl:value-of select="."/></para> 
    </xsl:template> 
</xsl:stylesheet> 

當這種轉化是在同一個XML文檔(以上)應用中,相同的正確的結果產生

<para>public static void main(String[] args){</para> 
<para> System.out.println("Be happy!");</para> 
<para> System.out.println("And now we add annotations.");</para> 
<para>}</para> 
+0

工作很好,謝謝! XSLT 2.0並不適用於我,但是一旦我從http://sourceforge.net/projects/fxsl/files/fxsl/FXSL%201.2/獲得了所有FXSL,它就是一帆風順的。 – NickChase

+0

@NickChase,不客氣。 –

+0

這隻給出答案和輸出,但不能解釋它爲什麼起作用。 –

1

作爲在this answer中解釋過,XML中的所有換行符都被視爲實體&#10;。這意味着,要在換行符處拆分字符串,必須在此實體上拆分。

因此,在普通的XSLT 1.0(不擴展)的溶液可以看起來像:

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

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

    <xsl:template match="programlisting/text()"> 
    <xsl:param name="text" select="."/> 
    <para> 
     <!-- Because we would rely on $text containing a line break when using 
      substring-before($text,'&#10;') and the last line might not have a 
      trailing line break, we append one before doing substring-before(). --> 
     <xsl:value-of select="substring-before(concat($text,'&#10;'),'&#10;')"/> 
    </para> 
    <xsl:if test="contains($text,'&#10;')"> 
     <xsl:apply-templates select="."> 
     <xsl:with-param name="text" select="substring-after($text,'&#10;')"/> 
     </xsl:apply-templates> 
    </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

隨着你的給定的XML源,這個輸出在第一和最後斷行一些空<para>元件。也可以檢查空行(像Dimitre一樣)。但是,這也會刪除代碼清單中間的空行。如果在開始和結束時刪除空行很重要,同時在中間保留空行,那麼需要採取更聰明的方法。

這只是證明使用普通XSLT 1.0的任務並不困難。