使用 Saxon 和 xslt 样式表合并两个 xml 文件并获得一个 xml 输出

Merge two xml files and get one xml output using Saxon and xslt Stylesheet

我想使用 Saxon 创建从多个 xml 文件到一个 xml (Output.xml) 的转换。 xml 文件将由我的软件 (Vector CANoe) 提供的特定 merge.xslt 文件生成。假设在一个文件夹中我有几个文件:

test_InitStartOP_report0001.xml
test_InitStartOP_report0002.xml
test_InitStartOP_report0003.xml

我想使用此样式表中的此模板输出一个 xml 文件:

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- Merge list of XML reports to one single report  -->
<!-- merge.xslt                                      -->
<!-- Version 1.2                                     -->
<!-- (c) 2005  Vector Informatik GmbH, Stuttgart     -->

<xsl:output method="xml" version="1.0" encoding="utf-8" standalone="yes"/>

<xsl:template match="/">
  <testmodule starttime="-" timestamp="-">
    <xsl:apply-templates select="//testmodule" />
    <xsl:variable name="testmoduleresult">
      <xsl:choose>
        <xsl:when test="//testmodule/verdict/@result='fail'">fail</xsl:when>
        <xsl:otherwise>pass</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <verdict time="-" timestamp="-" endtime="-" endtimestamp="-" result='{$testmoduleresult}' />
    <title>Test Report</title>
    
    <xsl:apply-templates select="//testmodule[1]/engineer|//testmodule[1]/testsetup|//testmodule[1]/sut|//testmodule[1]/hardware" />
    <xsl:apply-templates select="//testmodule/miscinfo|//testmodule/extendedinfo" />
    
  </testmodule>
</xsl:template>

<xsl:template match="testmodule">
  <testgroup>
    <xsl:apply-templates select="preparation|completion|testgroup|testcase|skipped|violation|moduledetails|externalref" />
    <xsl:copy-of select="title" />
    <xsl:copy-of select="description" />
    
    <!-- Write test module information -->
    <xsl:if test="testsetup">
      <xsl:for-each select="testsetup/xinfo|testsetup/info">
        <xsl:if test="local-name(.) != 'xinfo' or (name != 'Version' and name != 'Configuration' and name != 'Konfiguration' and name != 'Configuration Comment' and name != 'Konfigurationskommentar' and name != 'Windows Computer Name' and name != 'Windows Computer-Name' and not(starts-with(name, 'Nodelayer Module')) and not(starts-with(name, 'Nodelayer-Modul')))">
          <xsl:apply-templates select="." mode="tminfo" />
        </xsl:if>
      </xsl:for-each>
    </xsl:if>
  </testgroup>
</xsl:template>

<xsl:template match="info" mode="tminfo">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="xinfo" mode="tminfo">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="preparation">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="completion">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="testgroup">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="testcase">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="skipped">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="violation">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="moduledetails">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="miscinfo">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="extendedinfo">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="engineer">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="hardware">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="externalref">
  <xsl:copy-of select="." />
</xsl:template>

<xsl:template match="testsetup">
  <testsetup>
    <xsl:for-each select="xinfo">
      <xsl:if test="name = 'Version' or name = 'Configuration' or name = 'Konfiguration' or name = 'Configuration Comment' or name = 'Konfigurationskommentar' or name = 'Windows Computer Name' or name = 'Windows Computer-Name' or starts-with(name, 'Nodelayer Module') or starts-with(name, 'Nodelayer-Modul')">
        <xsl:copy-of select="." />
      </xsl:if>
    </xsl:for-each>
  </testsetup>
</xsl:template>

<xsl:template match="sut">
  <xsl:copy-of select="." />
</xsl:template>

</xsl:stylesheet>

我尝试使用此 cmd 行在 Cmd 中使用 Saxon:

java -jar saxon-he-10.5.jar -xsl:merge.xslt -s:"test_InitStartOP_report0001.xml;test_InitStartOP_report0002.xml" -o:Output.xml

但是它不起作用,有人知道我该如何解决这个问题吗?

我可能没看清楚需求,但我猜你写的时候

<xsl:apply-templates select="//testmodule[1]/engineer|//testmodule[1]/testsetup|//testmodule[1]/sut|//testmodule[1]/hardware" />
<xsl:apply-templates select="//testmodule/miscinfo|//testmodule/extendedinfo" />
    

您实际上想要 select testModule 个元素在所有输入文档中。如果是这样的话,那么首先要有一个变量$allInputs,其值为输入文档的集合,然后将这些表达式更改为,例如

<xsl:apply-templates select="$allInputs//testModule/....."/>

接下来的问题是如何将变量$allInputs绑定到这组文档。有几种方法可以做到这一点:

  • 使用 collection() 函数

  • 使用带有 URI 列表的 document() 函数

  • 将所有文档作为单个样式表参数传入

由于您 运行 来自命令行,最简单的方法可能是更改命令行以提供包含 URI 列表的样式表参数,以分号分隔:

inputFiles="test_InitStartOP_report0001.xml;test_InitStartOP_report0002.xml"

然后在样式表中你可以做

<xsl:param name="inputFiles" as="xs:string" required="yes"/>
<xsl:variable name="allInputs" select="tokenize($inputFiles, ';')!document(.)" as="document-node()*"/>

请注意,您不需要“主要输入文档”- 在命令行中删除 -s 选项,改用 -it,并将 <xsl:template match="/"> 更改为 <xsl:template name="xsl:initial-template">