【问题标题】:How to output ANSI Escape Sequences with XSLT / xsltproc如何使用 XSLT / xsltproc 输出 ANSI 转义序列
【发布时间】:2021-02-21 16:15:30
【问题描述】:

我想用 xsltproc(所以 XSLT 1.1!)转换一个 XML 文件(例如 junit.xml 文件)以生成一个文本文件,该文件将显示在类 unix 终端中。为清楚起见,我想使用 ANSI 转义序列用颜色突出显示某些部分。

例如,给定示例 XML 文件 in.xml

<?xml version="1.0" encoding="UTF-8"?>
<red>I love XML</red>

还有一个示例 XSLT 文件 color.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <xsl:output method="text" indent="no"/>
  <xsl:template match="red">
    <xsl:value-of select="."/>
  </xsl:template>
</xsl:stylesheet>

使用xsltproc,我得到:

如何更改 XSLT 文件以生成以下结果?

我试过了:

  • 使用select="concat(string('&amp;#27;[31m'),.)"。我收到parser error : xmlParseCharRef: invalid xmlChar value 27
  • 使用CDATA
  • &lt;xsl:text disable-output-escaping="yes"&gt;

但是对于xsltproc,这个简单的事情似乎是不可能的。


注意:现在,我将只添加一个后处理步骤,例如在 XSL 文件中使用 select="concat(string('&amp;amp;#27;[31m'),.)"/&gt;,然后

xsltproc color.xsl in.xml | sed -r 's/&#27;/\x1b/g'

【问题讨论】:

  • xsltproc 是否有支持 XML 1.1 而不是 XML 1.0 的开关?因为在 XML 1.1 中你可以使用&amp;#27;
  • 我怀疑您会发现 xsltproc 只能生成包含有效 XML 1.0 字符的输出,其中不包括 x1B 等控制字符。
  • 感谢提升 XML 版本的建议。不幸的是,xsltproc 确实不支持它。

标签: xml bash xslt


【解决方案1】:

如果您可以将 XSLT 创作为 XML 1.1,例如使用 Saxon 9 或 10,则可能

<?xml version="1.1" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    expand-text="yes"
    exclude-result-prefixes="#all"
    version="3.0">
    
    <xsl:param name="color-map" as="map(xs:string, xs:string)"
        select="map { 'red' : '31m',
        'blue' : '34m',
        'black' : '30m',
        'green' : '32m',
        'yellow' : '33m',
        'magenta' : '35m',
        'cyan' : '36m'
        }"/>
    
    <xsl:output method="text"/>
    
    <xsl:template match="red | blue | black | green | yellow | magenta | cyan">&#27;[{$color-map(local-name())}{.}&#27;[39;49m</xsl:template>
    
</xsl:stylesheet>

或使用 Xalan C++:

<?xml version="1.1" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exsl="http://exslt.org/common"
    exclude-result-prefixes="exsl" version="1.0">

    <xsl:param name="color-map">
        <color name="green">32m</color>
        <color name="cyan">36m</color>
        <color name="magenta">35m</color>
        <color name="red">31m</color>
        <color name="yellow">33m</color>
        <color name="blue">34m</color>
        <color name="black">30m</color>
    </xsl:param>
    
    <xsl:variable name="colors" select="exsl:node-set($color-map)/color"/>

    <xsl:output method="text"/>

    <xsl:template match="red | blue | black | green | yellow | magenta | cyan">
        <xsl:text>&#27;[</xsl:text>
        <xsl:value-of select="$colors[@name = local-name(current())]"/>
        <xsl:value-of select="."/>
        <xsl:text>&#27;[39;49m</xsl:text>
    </xsl:template>

</xsl:stylesheet>

似乎 xsltproc 不支持 XML 1.1,当我运行上面的 XSLT 1.0 但 XML 1.1 样式表与 Xalan C++ 和 xsltproc 一起工作时,我收到警告“解析器警告:不支持的版本 '1.1'”。

【讨论】:

  • fwiw - 为了让它与 xsltproc 一起工作,我使用了这个变体 template.xsl。然后通过 CLI 运行:echo -e "$(xsltproc /some/path/to/template.xsl /some/path/to/in.xml)"
  • 感谢有趣的样式表,尽管它们确实不适用于 xsltproc。切换到更好工具的另一个理由,但对我们来说不是一个简单的选择。如果没有更好的答案,我会改写我的问题并接受你的问题。 @RobC,感谢您提供有趣的解决方法!您基本上输出了转义的转义序列,让 echo 进行处理。与 sed post-proc 相比有点 hack,但非常聪明。
猜你喜欢
  • 2019-08-28
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 2014-05-11
  • 2012-11-18
  • 1970-01-01
  • 2012-04-14
  • 1970-01-01
相关资源
最近更新 更多