xsltproc 在多个文件前后添加文本

xsltproc add text before and after multiple files

我正在使用 xsltproc 实用程序,使用如下命令将多个 xml 测试结果转换为漂亮的打印控制台输出。

xsltproc stylesheet.xslt testresults/*

其中 stylesheet.xslt 看起来像这样:

<!-- One testsuite per xml test report file -->
<xsl:template match="/testsuite">
  <xsl:text>begin</xsl:text>
  ...
  <xsl:text>end</xsl:text>
</xsl:template>

这给了我类似这样的输出:

begin
TestSuite: 1
end
begin
TestSuite: 2
end
begin
TestSuite: 3
end

我想要的是:

begin
TestSuite: 1
TestSuite: 2
TestSuite: 3
end

谷歌搜索结果为空。我怀疑我可以在将 xml 文件交给 xsltproc 之前以某种方式合并它们,但我希望有一个更简单的解决方案。

xsltproc 分别转换每个指定的 XML 文档,这确实是它唯一明智的做法,因为 XSLT 在单个源代码树上运行,而 xsltproc 不会有足够的信息将多个文档组合成一棵树。由于您的模板发出带有 "begin" 和 "end" 文本的文本节点,因此会为每个输入文档发出这些节点。

您可以通过多种方式安排只有一个 "begin" 和一个 "end"。 所有 合理的开始都是从 <testsuite> 元素的模板中提取文本节点。如果输出中的每个 "TestSuite:" 行都应对应一个 <testsuite> 元素,那么即使您实际合并输入文档,您也需要这样做。

一个解决方案是从 XSLT 中完全删除 "begin" 和 "end" 行的责任。例如,从样式表中删除 xsl:text 元素并编写如下简单的脚本:

echo begin
xsltproc stylesheet.xslt testresults/*
echo end

或者,如果单个 XML 文件不是以 XML 声明开头,那么您可以通过 运行 xsltproc 等命令动态合并它们这个:

{ echo "<suites>"; cat testresults/*; echo "</suites>"; } \
    | xsltproc stylesheet.xslt -

相应的样式表可能会采用以下形式:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>

  <xsl:template match="/suites">
    <!-- the transform of the root element produces the "begin" and "end" -->
    <xsl:text>begin&#x0A;</xsl:text>
    <xsl:apply-templates select="testsuite"/>
    <xsl:text>&#x0A;end</xsl:text>
  </xsl:template>

  <xsl:template match="testsuite">
    ...
  </xsl:template>
</xsl:stylesheet>