#xml #xslt #saxon
Вопрос:
Я хочу создать преобразование из нескольких xml-файлов только в один xml (Output.xml) используя саксонский. XML-файлы будут сгенерированы с помощью определенного файла merge.xslt, предоставленного my softwar (Векторное каноэ). Предположим, в одной папке у меня есть несколько файлов:
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>
Я попытался использовать Saxon в Cmd, используя эту строку cmd :
java -jar saxon-he-10.5.jar -xsl:merge.xslt -s:"test_InitStartOP_report0001.xml;test_InitStartOP_report0002.xml" -o:Output.xml
Но это не работает, кто-нибудь знает, как я могу решить эту проблему?
Комментарии:
1. Поэтому, возможно, спросите своего поставщика программного обеспечения, как этот код XSLT должен вызываться или использоваться с несколькими документами. Что касается Саксона, я думаю
-s
, что для этого нужно выбрать один документ. В XSLT в целом у вас естьdocument
функция для извлечения других входных документов, в XSLT 2 и 3 у вас дополнительно естьdoc
функция, и Saxon позволяет вам использоватьcollection
иuri-collection
обрабатывать последовательность файлов.
Ответ №1:
Возможно, я не совсем понял это требование, но я предполагаю, что, когда вы напишете
<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
элементы во всех входных документах. Если это так, то первым делом нужно иметь переменную $allInputs
, значением которой является набор входных документов, а затем изменить эти выражения, например
<xsl:apply-templates select="$allInputs//testModule/....."/>
Тогда возникает вопрос, как привязать переменную $allInputs
к этому набору документов. Есть несколько способов сделать это:
- используйте функцию collection()
- используйте функцию document() со списком URI
- передайте все документы в качестве одного параметра таблицы стилей
Поскольку вы работаете из командной строки, самым простым подходом может быть изменение командной строки для предоставления параметра таблицы стилей, содержащего список 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">
.