XSLT 从某个元素的文本中逐行获取

发布于 2025-01-08 19:20:24 字数 797 浏览 0 评论 0 原文

我想问一下 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>

并且我想逐行获取并在每行之前添加空格(括号,连字符等)。

感谢您的帮助:-)

I'd like to ask if there is any way in XSLT to take line by line of text in some element and apply something to that line. For example i have

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

10/17/97   9:04         <DIR>    bin
10/16/97  14:11         <DIR>    DOS
10/16/97  14:40         <DIR>    Program Files
10/16/97  14:46         <DIR>    TEMP
10/17/97   9:04         <DIR>    tmp
10/16/97  14:37         <DIR>    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>

and I would like to take line by line and put white space (bracket, hyphen etc.) before every line.

Thank you for any help :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

中二柚 2025-01-15 19:20:24

我。 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         <DIR>    bin
    10/16/97  14:11         <DIR>    DOS
    10/16/97  14:40         <DIR>    Program Files
    10/16/97  14:46         <DIR>    TEMP
    10/17/97   9:04         <DIR>    tmp
    10/16/97  14:37         <DIR>    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>

想要的正确结果(文本节点的每一行都以字符串 开头”行:“)生成

<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         <DIR>    bin
    line:     10/16/97  14:11         <DIR>    DOS
    line:     10/16/97  14:40         <DIR>    Program Files
    line:     10/16/97  14:46         <DIR>    TEMP
    line:     10/17/97   9:04         <DIR>    tmp
    line:     10/16/97  14:37         <DIR>    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() 函数,第二个参数是正则表达式,允许可选的 CR 位于 NL 字符之前。


二. 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, '
'), '
')"/>

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

当此 XSLT 1.0 转换应用于同一个 XML 文档(上面)时,所需的结果(文本节点的每一行,前面加上字符串 "line: "< /code>)生成:

   line: 
   line:     Volume in drive C is SYSTEM         Serial number is 2350:717C
   line:     Directory of  C:\
   line: 
   line:     10/17/97   9:04         <DIR>    bin
   line:     10/16/97  14:11         <DIR>    DOS
   line:     10/16/97  14:40         <DIR>    Program Files
   line:     10/16/97  14:46         <DIR>    TEMP
   line:     10/17/97   9:04         <DIR>    tmp
   line:     10/16/97  14:37         <DIR>    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()< /code>substring-after()哨兵技术,以最大限度地减少代码长度和复杂性。

I. XSLT 2.0 solution:

<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>

when this transformation is applied on the provided XML document:

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

    10/17/97   9:04         <DIR>    bin
    10/16/97  14:11         <DIR>    DOS
    10/16/97  14:40         <DIR>    Program Files
    10/16/97  14:46         <DIR>    TEMP
    10/17/97   9:04         <DIR>    tmp
    10/16/97  14:37         <DIR>    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>

the wanted, correct result (each line of the text node is prepended by the string "line: ") is produced:

<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         <DIR>    bin
    line:     10/16/97  14:11         <DIR>    DOS
    line:     10/16/97  14:40         <DIR>    Program Files
    line:     10/16/97  14:46         <DIR>    TEMP
    line:     10/17/97   9:04         <DIR>    tmp
    line:     10/16/97  14:37         <DIR>    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>

Explanation:

Appropriate use of the tokenize() function with second argument a RegEx that allows an optional CR to precede the NL character.


II. XSLT 1.0 solution:

<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, '
'), '
')"/>

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

When this XSLT 1.0 transformation is applied on the same XML document (above), the wanted result (each line of the text node, prepended with the string "line: ") is produced:

   line: 
   line:     Volume in drive C is SYSTEM         Serial number is 2350:717C
   line:     Directory of  C:\
   line: 
   line:     10/17/97   9:04         <DIR>    bin
   line:     10/16/97  14:11         <DIR>    DOS
   line:     10/16/97  14:40         <DIR>    Program Files
   line:     10/16/97  14:46         <DIR>    TEMP
   line:     10/17/97   9:04         <DIR>    tmp
   line:     10/16/97  14:37         <DIR>    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

Explanation:

  1. Recursive named template to extract and output each next line. Stop condition -- when the string has zero length.

  2. Appropriate use of substring-before(), substring-after() and a sentinel technique to minimize code length and complexity.

拥醉 2025-01-15 19:20:24

好吧,使用 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

Well with XSLT 2.0 as supported by Saxon 9 or AltovaXML tools and others you can use the tokenize function e.g.

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

With XSLT 1.0 you could check whether your processor supports an extension function like http://www.exslt.org/str/functions/tokenize/index.html.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文