XSLT从一些元素的文本中逐行获取

时间:2012-02-25 17:57:24

标签: xslt line-by-line

我想问一下,在XSLT中是否有任何方法可以在某个元素中逐行显示文本并对该行应用某些内容。例如我有

<screen>
Volume in drive C is SYSTEM         Serial number is 2350:717C    
Directory of  C:\

10/17/97   9:04         &lt;DIR&gt;    bin
10/16/97  14:11         &lt;DIR&gt;    DOS
10/16/97  14:40         &lt;DIR&gt;    Program Files
10/16/97  14:46         &lt;DIR&gt;    TEMP
10/17/97   9:04         &lt;DIR&gt;    tmp
10/16/97  14:37         &lt;DIR&gt;    WINNT
10/16/97  14:25             119  AUTOEXEC.BAT
2/13/94   6:21          54,619  COMMAND.COM
10/16/97  14:25             115  CONFIG.SYS
11/16/97  17:17      61,865,984  pagefile.sys
2/13/94   6:21           9,349  WINA20.386
</screen>

我想逐行采取并在每一行之前放置空格(括号,连字符等)。

感谢您的帮助: - )

2 个答案:

答案 0 :(得分:4)

使用Saxon 9或AltovaXML工具和其他工具支持的XSLT 2.0,您可以使用tokenize函数,例如。

<xsl:template match="screen">
  <xsl:for-each select="tokenize(., '\n')">
    <xsl:value-of select="concat('-', .)"/>
  </xsl:for-each>
</xsl:template>

使用XSLT 1.0,您可以检查您的处理器是否支持http://www.exslt.org/str/functions/tokenize/index.html等扩展功能。

答案 1 :(得分:3)

<强>予。 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="/*">
  <screen>
   <xsl:for-each select="tokenize(., '\r?\n')">
    line: <xsl:sequence select="."/>
   </xsl:for-each>
  </screen>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于提供的XML文档

<screen>
    Volume in drive C is SYSTEM         Serial number is 2350:717C
    Directory of  C:\

    10/17/97   9:04         &lt;DIR&gt;    bin
    10/16/97  14:11         &lt;DIR&gt;    DOS
    10/16/97  14:40         &lt;DIR&gt;    Program Files
    10/16/97  14:46         &lt;DIR&gt;    TEMP
    10/17/97   9:04         &lt;DIR&gt;    tmp
    10/16/97  14:37         &lt;DIR&gt;    WINNT
    10/16/97  14:25             119  AUTOEXEC.BAT
    2/13/94   6:21          54,619  COMMAND.COM
    10/16/97  14:25             115  CONFIG.SYS
    11/16/97  17:17      61,865,984  pagefile.sys
    2/13/94   6:21           9,349  WINA20.386
</screen>

生成了想要的正确结果(文本节点的每一行以字符串"line: "为前缀)

<screen>
    line: 
    line:     Volume in drive C is SYSTEM         Serial number is 2350:717C
    line:     Directory of  C:\
    line: 
    line:     10/17/97   9:04         &lt;DIR&gt;    bin
    line:     10/16/97  14:11         &lt;DIR&gt;    DOS
    line:     10/16/97  14:40         &lt;DIR&gt;    Program Files
    line:     10/16/97  14:46         &lt;DIR&gt;    TEMP
    line:     10/17/97   9:04         &lt;DIR&gt;    tmp
    line:     10/16/97  14:37         &lt;DIR&gt;    WINNT
    line:     10/16/97  14:25             119  AUTOEXEC.BAT
    line:     2/13/94   6:21          54,619  COMMAND.COM
    line:     10/16/97  14:25             115  CONFIG.SYS
    line:     11/16/97  17:17      61,865,984  pagefile.sys
    line:     2/13/94   6:21           9,349  WINA20.386
    line: </screen>

<强>解释

适当使用 tokenize() 函数,第二个参数是RegEx,允许可选的CR在NL字符之前。


<强> II。 XSLT 1.0解决方案:

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

 <xsl:template match="text()" name="lines">
  <xsl:param name="pText" select="."/>

  <xsl:if test="string-length($pText)">
   line: <xsl:text/>

   <xsl:value-of select=
   "substring-before(concat($pText, '&#xA;'), '&#xA;')"/>

   <xsl:call-template name="lines">
    <xsl:with-param name="pText" select=
     "substring-after($pText, '&#xA;')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

当在同一个XML文档(上面)上应用此XSLT 1.0转换时,将生成所需结果(文本节点的每一行,前面带有字符串"line: "):

   line: 
   line:     Volume in drive C is SYSTEM         Serial number is 2350:717C
   line:     Directory of  C:\
   line: 
   line:     10/17/97   9:04         &lt;DIR&gt;    bin
   line:     10/16/97  14:11         &lt;DIR&gt;    DOS
   line:     10/16/97  14:40         &lt;DIR&gt;    Program Files
   line:     10/16/97  14:46         &lt;DIR&gt;    TEMP
   line:     10/17/97   9:04         &lt;DIR&gt;    tmp
   line:     10/16/97  14:37         &lt;DIR&gt;    WINNT
   line:     10/16/97  14:25             119  AUTOEXEC.BAT
   line:     2/13/94   6:21          54,619  COMMAND.COM
   line:     10/16/97  14:25             115  CONFIG.SYS
   line:     11/16/97  17:17      61,865,984  pagefile.sys
   line:     2/13/94   6:21           9,349  WINA20.386

<强>解释

  1. 递归命名模板以提取并输出每个下一行。停止条件 - 当字符串长度为零时。

  2. 适当使用 substring-before() substring-after() sentinel technique 以尽量减少代码长度和复杂性。